Core Usage
This section presents the core usage of fmdt-python. Any examples assume that
fmdt has already been imported with:
FMDT executables
We call the main executables fmdt-* using fmdt.*.
# Save the standard output of fmdt-detect to trk.txt
fmdt.detect(vid_in_path="2022_05_31_tauh_34_meteors.mp4", trk_path="trk.txt")
# Run a detection and generate necessary files for log-parser and visu
fmdt.detect(vid_in_path="2022_05_31_tauh_34_meteors.mp4",
log_path="log",
trk_path="trk.txt",
trk_roi_path="trk2roi.txt")
complete signature
def detect(
#=================== fmdt-detect parameters ================
vid_in_path: str,
vid_in_start: int | None = None,
vid_in_stop: int | None = None,
vid_in_skip: int | None = None,
vid_in_buff: bool | None = None,
vid_in_loop: int | None = None,
vid_in_threads: int | None = None,
ccl_hyst_lo: int | None = None,
ccl_hyst_hi: int | None = None,
ccl_fra_path: str | None = None,
ccl_fra_id: bool | None = None,
cca_mag: bool | None = None,
cca_ell: bool | None = None,
mrp_s_min: int | None = None,
mrp_s_max: int | None = None,
knn_k: int | None = None,
knn_d: int | None = None,
knn_s: int | None = None,
trk_ext_d: int | None = None,
trk_ext_o: int | None = None,
trk_angle: float | None = None,
trk_star_min: int | None = None,
trk_meteor_min: int | None = None,
trk_meteor_max: int | None = None,
trk_ddev: float | None = None,
trk_all: bool | None = None,
trk_roi_path: str | None = None,
log_path: str | None = None,
#================== Additional Parameters ====================
trk_path: str | None = None,
verbose: bool = False,
timeout: float = None,
cache: bool = False,
save_df: bool = False
) -> fmdt.res.DetectionResult:
complete signature
def log_parser(
log_path: str,
trk_roi_path: str | None = None,
log_flt: str | None = None,
fra_path: str | None = None,
ftr_name: str | None = None,
ftr_path: str | None = None,
trk_path: str | None = None,
trk_json_path: str | None = None,
trk_bb_path: str | None = None,
) -> fmdt.res.LogParserResult:
complete signature
def visu(
vid_in_path: str,
trk_path: str,
trk_bb_path: str,
vid_out_path: str,
vid_in_start: int | None = None,
vid_in_stop: int | None = None,
vid_in_threads: int | None = None,
trk_id: bool | None = None,
trk_nat_num: bool | None = None,
trk_only_meteor: bool | None = None,
gt_path: str | None = None,
#========================== Additional Options ========================
verbose: bool = False,
stdout: str | None = None
) -> fmdt.res.VisuResult:
These functions are designed to be chained together.
detect --> check
When calling fmdt.check in isolation, we need to specify the trk_path and gt_path. However, when
chaining with a call to fmdt.detect, fmdt's internal logic manages these parameters with sensible defaults.
detect --> log-parser --> visu
dres = fmdt.detect(vid_in_path="2022_05_31_tauh_34_meteors.mp4",
log_path="log").log_parser().visu()
Similarly, fmdt.detect will automatically populate the parameters trk_path and trk_roi_path with
2022_05_31_tauh_34_meteors_trk.txt and 2022_05_31_tauh_34_meteors_bb.txt, respectively. However,
creating additional log files is opt-in and must be specified with log_path.
Consult fmdt.api for more information about
fmdt's interface.
Configuration
Info
You only need to configure fmdt-python once. If you haven't already done
so, follow these instruction.
We configure fmdt-python by indicating where our
database videos are stored on disk using
fmdt.init():
Example
For unix user ejovo with videos stored on a remote hard drive
Seagate Portable Drive we configure fmdt with:
Print information about our local database configuration with the function
local_info():
Printing information about the local environment
================================================================================
Draconids-6mm*.avi videos configured with dir: /run/media/ejovo/Seagate Portable Drive/Meteors/Watec6mm/Meteor/
================================================================================
52 videos exist on disc out of the 52 videos in our database
38 of which have ground truths out of 38 ground truths in our database
================================================================================
Draconids-12mm*.avi videos configured with dir: /run/media/ejovo/Seagate Portable Drive/Meteors/Watec12mm/Meteor/
================================================================================
41 videos exist on disc out of the 41 videos in our database
37 of which have ground truths out of 37 ground truths in our database
================================================================================
window*.mp4 videos configured with dir: /run/media/ejovo/Seagate Portable Drive/Meteors/
================================================================================
8 videos exist on disc out of the 8 videos in our database
0 of which have ground truths out of 0 ground truths in our database
Loading Video Objects
After configuration we can load in Video objects using fmdt.load_*
>>> fmdt.load_draco6()
[Draconids-6mm1.00-2750-163200.avi, Draconids-6mm1.05-0750-164200.avi, Draconids-6mm1.14-1400-170300.avi, Draconids-6mm1.20-2350-171600.avi, Draconids-6mm1.29-2550-173600.avi, Draconids-6mm1.30-2050-173800.avi, Draconids-6mm1.32-3150-174200.avi, Draconids-6mm1.34-3050-174700.avi, Draconids-6mm2.00.01-1000-201100.avi, Draconids-6mm2.00.01-1500-201200.avi, Draconids-6mm2.00.01-2150-201200.avi, Draconids-6mm2.00.02-0700-201300.avi, Draconids-6mm2.00.03-0450-201500.avi, Draconids-6mm2.00.03-0550-201500.avi, Draconids-6mm2.00.03-0950-201500.avi, Draconids-6mm2.00.04-1500-201800.avi, Draconids-6mm2.00.04-1900-201900.avi, Draconids-6mm2.00.04-2950-201900.avi, Draconids-6mm2.00.05-0120-202000.avi, Draconids-6mm2.00.05-0200-202000.avi, Draconids-6mm2.00.05-0350-202000.avi, Draconids-6mm2.00.07-0900-202400.avi, Draconids-6mm2.00.07-2400-202500.avi, Draconids-6mm2.00.07-3000-202530.avi, Draconids-6mm2.00.09-0600-202900.avi, Draconids-6mm2.00.09-1650-203000.avi, Draconids-6mm2.00.09-3000-203030.avi, Draconids-6mm2.00.10-0300-203100.avi, Draconids-6mm2.00.10-0350-203110.avi, Draconids-6mm2.00.10-1050-203200.avi, Draconids-6mm2.00.11-2100-203400.avi, Draconids-6mm2.00.11-680-203300.avi, Draconids-6mm2.00.11-780-203310.avi, Draconids-6mm2.00.12-1550-203600.avi, Draconids-6mm2.00.12-2550-203700.avi, Draconids-6mm2.00.12-3100-203730.avi, Draconids-6mm2.00.13-0680-203800.avi, Draconids-6mm2.00.13-3100-204000.avi, Draconids-6mm2.00.15-0750-204200.avi, Draconids-6mm2.00.15-2300-204300.avi, Draconids-6mm2.00.15-2850-204330.avi, Draconids-6mm2.00.170050-204700.avi, Draconids-6mm2.00.18-0000-204900.avi, Draconids-6mm2.00.18-2850-205000.avi, Draconids-6mm2.00.19-0680-205100.avi, Draconids-6mm2.00.19-1550-205200.avi, Draconids-6mm2.00.20-2600-205500.avi, Draconids-6mm2.00.20-2900-205510.avi, Draconids-6mm2.00.22-3150-205900.avi, Draconids-6mm2.00.25-2250-210600.avi, Draconids-6mm2.00.26-450-210700.avi, Draconids-6mm2.00.28-1950-211200.avi]
>>> fmdt.load_draco12()
[Draconids-12mm1.01-1950-163100.avi, Draconids-12mm1.02-1500-163500.avi, Draconids-12mm1.09-800-164900.avi, Draconids-12mm1.11-150-165300.avi, Draconids-12mm1.13-1350-165800.avi, Draconids-12mm1.15-650-170200.avi, Draconids-12mm1.16-250-170400.avi, Draconids-12mm1.19-2400-171200.avi, Draconids-12mm1.20-650-171300.avi, Draconids-12mm1.26-3100-172700.avi, Draconids-12mm1.27-2800-173000.avi, Draconids-12mm1.28-350-173100.avi, Draconids-12mm1.30-1700-173600.avi, Draconids-12mm1.33-2350-174300.avi, Draconids-12mm2.00.01-3000-201200.avi, Draconids-12mm2.00.01-3100-201200.avi, Draconids-12mm2.00.02-1550-201300.avi, Draconids-12mm2.00.02-2950-201400.avi, Draconids-12mm2.00.03-2000-201600.avi, Draconids-12mm2.00.03-550-201500.avi, Draconids-12mm2.00.04-1550-201900.avi, Draconids-12mm2.00.04-2550-201900.avi, Draconids-12mm2.00.04-750-201800.avi, Draconids-12mm2.00.05-150-202000.avi, Draconids-12mm2.00.05-1600-202100.avi, Draconids-12mm2.00.05-2900-202100.avi, Draconids-12mm2.00.05-2950-202100.avi, Draconids-12mm2.00.06-1400-202200.avi, Draconids-12mm2.00.08-3250-202700.avi, Draconids-12mm2.00.09-1250-202900.avi, Draconids-12mm2.00.09-1450-202900.avi, Draconids-12mm2.00.11-650-203300.avi, Draconids-12mm2.00.14-800-204000.avi, Draconids-12mm2.00.15-1850-204300.avi, Draconids-12mm2.00.15-2950-204300.avi, Draconids-12mm2.00.15-3050-204300.avi, Draconids-12mm2.00.21-1250-205500.avi, Draconids-12mm2.00.22-2250-205900.avi, Draconids-12mm2.00.27-1750-210900.avi, Draconids-12mm2.00.28-1800-211100.avi, Draconids-12mm2.00.28-2400-211200.avi]
>>> fmdt.load_window_clips()
[window_3_sony_0400-0405UTC.mp4 [773, 802], window_3_sony_0400-0405UTC.mp4 [1213, 1262], window_3_sony_0400-0405UTC.mp4 [1414, 1451], window_3_sony_0400-0405UTC.mp4 [2276, 2335], window_3_sony_0400-0405UTC.mp4 [2823, 2862], window_3_sony_0400-0405UTC.mp4 [2850, 2900], window_3_sony_0400-0405UTC.mp4 [2916, 2945], window_3_sony_0400-0405UTC.mp4 [3414, 3446], window_3_sony_0400-0405UTC.mp4 [3845, 3874], window_3_sony_0400-0405UTC.mp4 [4143, 4191], window_3_sony_0400-0405UTC.mp4 [4250, 4280], window_3_sony_0400-0405UTC.mp4 [4435, 4472], window_3_sony_0400-0405UTC.mp4 [5311, 5342], window_3_sony_0400-0405UTC.mp4 [6778, 6823], window_3_sony_0400-0405UTC.mp4 [7187, 7219], window_3_sony_0405-0410UTC.mp4 [261, 290], window_3_sony_0405-0410UTC.mp4 [306, 349], window_3_sony_0405-0410UTC.mp4 [1454, 1489], window_3_sony_0405-0410UTC.mp4 [2405, 2441], window_3_sony_0405-0410UTC.mp4 [3046, 3076], window_3_sony_0405-0410UTC.mp4 [3780, 3814], window_3_sony_0405-0410UTC.mp4 [4601, 4645], window_3_sony_0405-0410UTC.mp4 [5568, 5600], window_3_sony_0405-0410UTC.mp4 [6842, 6874], window_3_sony_0405-0410UTC.mp4 [6906, 6948], window_3_sony_0405-0410UTC.mp4 [7069, 7120], window_3_sony_0405-0410UTC.mp4 [7475, 7500], window_3_sony_0410-0415UTC.mp4 [0, 18], window_3_sony_0410-0415UTC.mp4 [104, 141], window_3_sony_0410-0415UTC.mp4 [349, 377], window_3_sony_0410-0415UTC.mp4 [943, 979], window_3_sony_0410-0415UTC.mp4 [2006, 2038], window_3_sony_0410-0415UTC.mp4 [2232, 2262], window_3_sony_0410-0415UTC.mp4 [2768, 2801], window_3_sony_0410-0415UTC.mp4 [3551, 3587], window_3_sony_0410-0415UTC.mp4 [4316, 4352], window_3_sony_0410-0415UTC.mp4 [4342, 4377], window_3_sony_0410-0415UTC.mp4 [4507, 4540], window_3_sony_0410-0415UTC.mp4 [4636, 4663], window_3_sony_0410-0415UTC.mp4 [6076, 6116], window_3_sony_0410-0415UTC.mp4 [6162, 6192], window_3_sony_0410-0415UTC.mp4 [6585, 6624], window_3_sony_0410-0415UTC.mp4 [6727, 6769], window_3_sony_0410-0415UTC.mp4 [7239, 7286], window_3_sony_0415-0420UTC.mp4 [30, 68], window_3_sony_0415-0420UTC.mp4 [425, 458], window_3_sony_0415-0420UTC.mp4 [709, 736], window_3_sony_0415-0420UTC.mp4 [1054, 1086], window_3_sony_0415-0420UTC.mp4 [1363, 1406], window_3_sony_0415-0420UTC.mp4 [1413, 1446], window_3_sony_0415-0420UTC.mp4 [1890, 1922], window_3_sony_0415-0420UTC.mp4 [2068, 2111], window_3_sony_0415-0420UTC.mp4 [2299, 2329], window_3_sony_0415-0420UTC.mp4 [2689, 2745], window_3_sony_0415-0420UTC.mp4 [2878, 2907], window_3_sony_0415-0420UTC.mp4 [3362, 3392], window_3_sony_0415-0420UTC.mp4 [3711, 3761], window_3_sony_0415-0420UTC.mp4 [3963, 3999], window_3_sony_0415-0420UTC.mp4 [5592, 5626], window_3_sony_0415-0420UTC.mp4 [5880, 5920], window_3_sony_0415-0420UTC.mp4 [6481, 6524], window_3_sony_0415-0420UTC.mp4 [6775, 6810], window_3_sony_0415-0420UTC.mp4 [6961, 7009], window_3_sony_0420-0425UTC.mp4 [520, 549], window_3_sony_0420-0425UTC.mp4 [1743, 1779], window_3_sony_0420-0425UTC.mp4 [2173, 2213], window_3_sony_0420-0425UTC.mp4 [2656, 2693], window_3_sony_0420-0425UTC.mp4 [3091, 3127], window_3_sony_0420-0425UTC.mp4 [3292, 3329], window_3_sony_0420-0425UTC.mp4 [4286, 4330], window_3_sony_0420-0425UTC.mp4 [6043, 6079], window_3_sony_0420-0425UTC.mp4 [6230, 6262], window_3_sony_0425-0430UTC.mp4 [474, 507], window_3_sony_0425-0430UTC.mp4 [1001, 1033], window_3_sony_0425-0430UTC.mp4 [1125, 1156], window_3_sony_0425-0430UTC.mp4 [1314, 1353], window_3_sony_0425-0430UTC.mp4 [1914, 1952], window_3_sony_0425-0430UTC.mp4 [2104, 2143], window_3_sony_0425-0430UTC.mp4 [3921, 3956], window_3_sony_0425-0430UTC.mp4 [4256, 4290], window_3_sony_0425-0430UTC.mp4 [4865, 4896], window_3_sony_0425-0430UTC.mp4 [5484, 5516], window_3_sony_0425-0430UTC.mp4 [6595, 6639], window_3_sony_0425-0430UTC.mp4 [7058, 7091], window_3_sony_0500-0505UTC.mp4 [137, 170], window_3_sony_0500-0505UTC.mp4 [504, 537], window_3_sony_0500-0505UTC.mp4 [1172, 1203], window_3_sony_0500-0505UTC.mp4 [2262, 2289], window_3_sony_0500-0505UTC.mp4 [2532, 2566], window_3_sony_0500-0505UTC.mp4 [2624, 2667], window_3_sony_0500-0505UTC.mp4 [2883, 2912], window_3_sony_0500-0505UTC.mp4 [3528, 3560], window_3_sony_0500-0505UTC.mp4 [4537, 4568], window_3_sony_0500-0505UTC.mp4 [4781, 4809], window_3_sony_0500-0505UTC.mp4 [5147, 5184], window_3_sony_0500-0505UTC.mp4 [5217, 5271], window_3_sony_0500-0505UTC.mp4 [6314, 6349], window_3_sony_0500-0505UTC.mp4 [7073, 7109], window_3_sony_0500-0505UTC.mp4 [7377, 7404], window_3_sony_0500-0505UTC.mp4 [7422, 7457]]
Use fmdt.load_all to load all the sequences that contain a meteor in our
database
>>> fmdt.load_all()
[Draconids-6mm1.00-2750-163200.avi, Draconids-6mm1.05-0750-164200.avi, Draconids-6mm1.14-1400-170300.avi, Draconids-6mm1.20-2350-171600.avi, Draconids-6mm1.29-2550-173600.avi, Draconids-6mm1.30-2050-173800.avi, Draconids-6mm1.32-3150-174200.avi, Draconids-6mm1.34-3050-174700.avi, Draconids-6mm2.00.01-1000-201100.avi, Draconids-6mm2.00.01-1500-201200.avi, Draconids-6mm2.00.01-2150-201200.avi, Draconids-6mm2.00.02-0700-201300.avi, Draconids-6mm2.00.03-0450-201500.avi, Draconids-6mm2.00.03-0550-201500.avi, Draconids-6mm2.00.03-0950-201500.avi, Draconids-6mm2.00.04-1500-201800.avi, Draconids-6mm2.00.04-1900-201900.avi, Draconids-6mm2.00.04-2950-201900.avi, Draconids-6mm2.00.05-0120-202000.avi, Draconids-6mm2.00.05-0350-202000.avi, Draconids-6mm2.00.07-0900-202400.avi, Draconids-6mm2.00.07-2400-202500.avi, Draconids-6mm2.00.07-3000-202530.avi, Draconids-6mm2.00.09-0600-202900.avi, Draconids-6mm2.00.09-1650-203000.avi, Draconids-6mm2.00.09-3000-203030.avi, Draconids-6mm2.00.10-0300-203100.avi, Draconids-6mm2.00.10-0350-203110.avi, Draconids-6mm2.00.10-1050-203200.avi, Draconids-6mm2.00.11-2100-203400.avi, Draconids-6mm2.00.11-680-203300.avi, Draconids-6mm2.00.11-780-203310.avi, Draconids-6mm2.00.12-1550-203600.avi, Draconids-6mm2.00.12-2550-203700.avi, Draconids-6mm2.00.12-3100-203730.avi, Draconids-6mm2.00.13-0680-203800.avi, Draconids-6mm2.00.13-3100-204000.avi, Draconids-6mm2.00.15-0750-204200.avi, Draconids-12mm1.01-1950-163100.avi, Draconids-12mm1.02-1500-163500.avi, Draconids-12mm1.09-800-164900.avi, Draconids-12mm1.11-150-165300.avi, Draconids-12mm1.13-1350-165800.avi, Draconids-12mm1.15-650-170200.avi, Draconids-12mm1.16-250-170400.avi, Draconids-12mm1.20-650-171300.avi, Draconids-12mm1.26-3100-172700.avi, Draconids-12mm1.27-2800-173000.avi, Draconids-12mm1.28-350-173100.avi, Draconids-12mm1.30-1700-173600.avi, Draconids-12mm1.33-2350-174300.avi, Draconids-12mm2.00.01-3000-201200.avi, Draconids-12mm2.00.01-3100-201200.avi, Draconids-12mm2.00.02-1550-201300.avi, Draconids-12mm2.00.03-2000-201600.avi, Draconids-12mm2.00.04-1550-201900.avi, Draconids-12mm2.00.04-2550-201900.avi, Draconids-12mm2.00.05-150-202000.avi, Draconids-12mm2.00.05-1600-202100.avi, Draconids-12mm2.00.05-2900-202100.avi, Draconids-12mm2.00.05-2950-202100.avi, Draconids-12mm2.00.06-1400-202200.avi, Draconids-12mm2.00.08-3250-202700.avi, Draconids-12mm2.00.09-1250-202900.avi, Draconids-12mm2.00.09-1450-202900.avi, Draconids-12mm2.00.11-650-203300.avi, Draconids-12mm2.00.14-800-204000.avi, Draconids-12mm2.00.15-1850-204300.avi, Draconids-12mm2.00.15-2950-204300.avi, Draconids-12mm2.00.15-3050-204300.avi, Draconids-12mm2.00.21-1250-205500.avi, Draconids-12mm2.00.22-2250-205900.avi, Draconids-12mm2.00.27-1750-210900.avi, Draconids-12mm2.00.28-1800-211100.avi, Draconids-12mm2.00.28-2400-211200.avi, window_3_sony_0400-0405UTC.mp4 [773, 802], window_3_sony_0400-0405UTC.mp4 [1213, 1262], window_3_sony_0400-0405UTC.mp4 [1414, 1451], window_3_sony_0400-0405UTC.mp4 [2276, 2335], window_3_sony_0400-0405UTC.mp4 [2823, 2862], window_3_sony_0400-0405UTC.mp4 [2850, 2900], window_3_sony_0400-0405UTC.mp4 [2916, 2945], window_3_sony_0400-0405UTC.mp4 [3414, 3446], window_3_sony_0400-0405UTC.mp4 [3845, 3874], window_3_sony_0400-0405UTC.mp4 [4143, 4191], window_3_sony_0400-0405UTC.mp4 [4250, 4280], window_3_sony_0400-0405UTC.mp4 [4435, 4472], window_3_sony_0400-0405UTC.mp4 [5311, 5342], window_3_sony_0400-0405UTC.mp4 [6778, 6823], window_3_sony_0400-0405UTC.mp4 [7187, 7219], window_3_sony_0405-0410UTC.mp4 [261, 290], window_3_sony_0405-0410UTC.mp4 [306, 349], window_3_sony_0405-0410UTC.mp4 [1454, 1489], window_3_sony_0405-0410UTC.mp4 [2405, 2441], window_3_sony_0405-0410UTC.mp4 [3046, 3076], window_3_sony_0405-0410UTC.mp4 [3780, 3814], window_3_sony_0405-0410UTC.mp4 [4601, 4645], window_3_sony_0405-0410UTC.mp4 [5568, 5600], window_3_sony_0405-0410UTC.mp4 [6842, 6874], window_3_sony_0405-0410UTC.mp4 [6906, 6948], window_3_sony_0405-0410UTC.mp4 [7069, 7120], window_3_sony_0405-0410UTC.mp4 [7475, 7500], window_3_sony_0410-0415UTC.mp4 [0, 18], window_3_sony_0410-0415UTC.mp4 [104, 141], window_3_sony_0410-0415UTC.mp4 [349, 377], window_3_sony_0410-0415UTC.mp4 [943, 979], window_3_sony_0410-0415UTC.mp4 [2006, 2038], window_3_sony_0410-0415UTC.mp4 [2232, 2262], window_3_sony_0410-0415UTC.mp4 [2768, 2801], window_3_sony_0410-0415UTC.mp4 [3551, 3587], window_3_sony_0410-0415UTC.mp4 [4316, 4352], window_3_sony_0410-0415UTC.mp4 [4342, 4377], window_3_sony_0410-0415UTC.mp4 [4507, 4540], window_3_sony_0410-0415UTC.mp4 [4636, 4663], window_3_sony_0410-0415UTC.mp4 [6076, 6116], window_3_sony_0410-0415UTC.mp4 [6162, 6192], window_3_sony_0410-0415UTC.mp4 [6585, 6624], window_3_sony_0410-0415UTC.mp4 [6727, 6769], window_3_sony_0410-0415UTC.mp4 [7239, 7286], window_3_sony_0415-0420UTC.mp4 [30, 68], window_3_sony_0415-0420UTC.mp4 [425, 458], window_3_sony_0415-0420UTC.mp4 [709, 736], window_3_sony_0415-0420UTC.mp4 [1054, 1086], window_3_sony_0415-0420UTC.mp4 [1363, 1406], window_3_sony_0415-0420UTC.mp4 [1413, 1446], window_3_sony_0415-0420UTC.mp4 [1890, 1922], window_3_sony_0415-0420UTC.mp4 [2068, 2111], window_3_sony_0415-0420UTC.mp4 [2299, 2329], window_3_sony_0415-0420UTC.mp4 [2689, 2745], window_3_sony_0415-0420UTC.mp4 [2878, 2907], window_3_sony_0415-0420UTC.mp4 [3362, 3392], window_3_sony_0415-0420UTC.mp4 [3711, 3761], window_3_sony_0415-0420UTC.mp4 [3963, 3999], window_3_sony_0415-0420UTC.mp4 [5592, 5626], window_3_sony_0415-0420UTC.mp4 [5880, 5920], window_3_sony_0415-0420UTC.mp4 [6481, 6524], window_3_sony_0415-0420UTC.mp4 [6775, 6810], window_3_sony_0415-0420UTC.mp4 [6961, 7009], window_3_sony_0420-0425UTC.mp4 [520, 549], window_3_sony_0420-0425UTC.mp4 [1743, 1779], window_3_sony_0420-0425UTC.mp4 [2173, 2213], window_3_sony_0420-0425UTC.mp4 [2656, 2693], window_3_sony_0420-0425UTC.mp4 [3091, 3127], window_3_sony_0420-0425UTC.mp4 [3292, 3329], window_3_sony_0420-0425UTC.mp4 [4286, 4330], window_3_sony_0420-0425UTC.mp4 [6043, 6079], window_3_sony_0420-0425UTC.mp4 [6230, 6262], window_3_sony_0425-0430UTC.mp4 [474, 507], window_3_sony_0425-0430UTC.mp4 [1001, 1033], window_3_sony_0425-0430UTC.mp4 [1125, 1156], window_3_sony_0425-0430UTC.mp4 [1314, 1353], window_3_sony_0425-0430UTC.mp4 [1914, 1952], window_3_sony_0425-0430UTC.mp4 [2104, 2143], window_3_sony_0425-0430UTC.mp4 [3921, 3956], window_3_sony_0425-0430UTC.mp4 [4256, 4290], window_3_sony_0425-0430UTC.mp4 [4865, 4896], window_3_sony_0425-0430UTC.mp4 [5484, 5516], window_3_sony_0425-0430UTC.mp4 [6595, 6639], window_3_sony_0425-0430UTC.mp4 [7058, 7091], window_3_sony_0500-0505UTC.mp4 [137, 170], window_3_sony_0500-0505UTC.mp4 [504, 537], window_3_sony_0500-0505UTC.mp4 [1172, 1203], window_3_sony_0500-0505UTC.mp4 [2262, 2289], window_3_sony_0500-0505UTC.mp4 [2532, 2566], window_3_sony_0500-0505UTC.mp4 [2624, 2667], window_3_sony_0500-0505UTC.mp4 [2883, 2912], window_3_sony_0500-0505UTC.mp4 [3528, 3560], window_3_sony_0500-0505UTC.mp4 [4537, 4568], window_3_sony_0500-0505UTC.mp4 [4781, 4809], window_3_sony_0500-0505UTC.mp4 [5147, 5184], window_3_sony_0500-0505UTC.mp4 [5217, 5271], window_3_sony_0500-0505UTC.mp4 [6314, 6349], window_3_sony_0500-0505UTC.mp4 [7073, 7109], window_3_sony_0500-0505UTC.mp4 [7377, 7404], window_3_sony_0500-0505UTC.mp4 [7422, 7457]]
>>> len(fmdt.load_all())
175
Filtering
We can filter which videos to load using the require_exist, require_gt and require_best_det
parameters.
Of course, any combination of these three options is permitted, as long as the function supports each filtering option. Note that having a best detection stored in our database implies the presence of a ground truth.
Thus,
returns a superset of
Video interface
The Video class allows use to call our FMDT executables using a very succinct
syntax. Let's get familiar with how we use this class by loading in our demo
video 2022_05_31_tauh_34_meteors.mp4 using fmdt.load_demo()
Warning
This operation instantiates a Video object associated with
2022_05_31_tauh_34_meteors.mp4 from our video.db file. The presence of v
does not imply that 2022_05_31_tauh_32_meteors.mp4 exists on disk nor that
it will be found by fmdt in the case that it does. For more information,
consult our page on configuring fmdt.
We can get the full path of a Video with the full_path() function and check
if the file that we are pointing to exists on disk with exists():
>>> v.full_path()
'/run/media/ejovo/Seagate Portable Drive/Meteors/2022_05_31_tauh_34_meteors.mp4'
>>> v.exists()
True
Meteors
We can check if v has any meteors in our ground truth database using
has_meteors()
and use meteors() to retrieve them when the previous result is True.
>>> v.meteors()
[<fmdt.truth.HumanDetection object at 0x7fec74ccbee0>, <fmdt.truth.HumanDetection object at 0x7febad89b520>, <fmdt.truth.HumanDetection object at 0x7febad89b3d0>, <fmdt.truth.HumanDetection object at 0x7febad89b5e0>, <fmdt.truth.HumanDetection object at 0x7febad89b430>, <fmdt.truth.HumanDetection object at 0x7febad89b640>, <fmdt.truth.HumanDetection object at 0x7febad89b490>, <fmdt.truth.HumanDetection object at 0x7febad89b6a0>, <fmdt.truth.HumanDetection object at 0x7febad89b4f0>, <fmdt.truth.HumanDetection object at 0x7febad89b700>, <fmdt.truth.HumanDetection object at 0x7febad89b550>, <fmdt.truth.HumanDetection object at 0x7febad89b760>, <fmdt.truth.HumanDetection object at 0x7febad89b5b0>, <fmdt.truth.HumanDetection object at 0x7febad89b7c0>, <fmdt.truth.HumanDetection object at 0x7febad89b610>, <fmdt.truth.HumanDetection object at 0x7febad89b820>, <fmdt.truth.HumanDetection object at 0x7febad89b670>, <fmdt.truth.HumanDetection object at 0x7febad89b880>, <fmdt.truth.HumanDetection object at 0x7febad89b6d0>, <fmdt.truth.HumanDetection object at 0x7febad89b8e0>, <fmdt.truth.HumanDetection object at 0x7febad89b730>, <fmdt.truth.HumanDetection object at 0x7febad89b940>, <fmdt.truth.HumanDetection object at 0x7febad89b790>, <fmdt.truth.HumanDetection object at 0x7febad89b9a0>, <fmdt.truth.HumanDetection object at 0x7febad89b7f0>, <fmdt.truth.HumanDetection object at 0x7febad89ba00>, <fmdt.truth.HumanDetection object at 0x7febad89b850>, <fmdt.truth.HumanDetection object at 0x7febad89ba60>, <fmdt.truth.HumanDetection object at 0x7febad89b8b0>, <fmdt.truth.HumanDetection object at 0x7febad89bac0>, <fmdt.truth.HumanDetection object at 0x7febad89b910>, <fmdt.truth.HumanDetection object at 0x7febad89bb20>, <fmdt.truth.HumanDetection object at 0x7febad89b970>, <fmdt.truth.HumanDetection object at 0x7febad89bb80>]
FMDT Executables
We can run all three of our core executables starting with a Video object.
Warning
If v is not on disc (v.exists() == False) then v.detect() will
raise an exception
We can run a detection with detect():
>>> res = v.detect()
(II) Frame n° 255 -- Tracks = ['meteor': 38, 'star': 0, 'noise': 0, 'total': 38]
[<Meteor (102, 108)>, <Meteor (110, 126)>, <Meteor (111, 118)>, <Meteor (121, 123)>, <Meteor (127, 129)>, <Meteor (129, 131)>, <Meteor (133, 141)>, <Meteor (134, 143)>, <Meteor (134, 137)>, <Meteor (136, 138)>, <Meteor (139, 144)>, <Meteor (139, 142)>, <Meteor (140, 150)>, <Meteor (146, 149)>, <Meteor (156, 158)>, <Meteor (156, 165)>, <Meteor (157, 162)>, <Meteor (160, 163)>, <Meteor (164, 167)>, <Meteor (167, 169)>, <Meteor (171, 175)>, <Meteor (174, 180)>, <Meteor (178, 185)>, <Meteor (179, 181)>, <Meteor (179, 189)>, <Meteor (180, 184)>, <Meteor (183, 189)>, <Meteor (194, 197)>, <Meteor (197, 199)>, <Meteor (199, 201)>, <Meteor (200, 205)>, <Meteor (201, 203)>, <Meteor (202, 204)>, <Meteor (223, 229)>, <Meteor (224, 228)>, <Meteor (227, 231)>, <Meteor (249, 252)>, <Meteor (251, 253)>]
Movement Statistics
We can additionally store movement statistics if we manually specify a log
directory with the log_path argument.
>>> res = v.detect(log_path="log")
(II) Frame n° 255 -- Tracks = ['meteor': 38, 'star': 0, 'noise': 0, 'total': 38]
Trying to retrieve log info here: log
>>> print(res)
fmdt.res.DetectionResult with args digest: 74fffad3f5036080
objects in trk_list: 38 meteor(s), 0 star(s), 0 noise
nroi nassoc mean_err std_dev
0 45 0 0.0000 0.0000
1 63 17 0.1663 0.1411
2 67 19 0.2939 0.3953
3 82 24 0.2738 0.2614
4 35 18 0.1601 0.2101
.. ... ... ... ...
251 52 18 0.3344 0.3212
252 59 22 0.9310 1.2554
253 65 17 0.1500 0.1209
254 50 17 0.1251 0.1058
255 66 19 0.3721 0.2947
[256 rows x 4 columns]
The estimated movement statistics are stored in the df member of our
fmdt.res.DetectionResult.
Unique log_path
When running multiple diffent videos with the same core set of arguments, it
might be a good idea to isolate out log_path. To automatically cache the
log information in a unique folder, call detect with the save_df
parameter set to True instead of using log_path:
Danger
TODO: Explain the save_df argument. What does the df acronym mean?
>>> res = v.detect(save_df=True)
Save_df activated in final detect call
(II) Frame n° 255 -- Tracks = ['meteor': 38, 'star': 0, 'noise': 0, 'total': 38]
Trying to retrieve log info here: /home/ejovo/.cache/fmdt_python/31a2dd4832e985d6
This will automatically cache our log results in a unique directory. Consult this to guide to learn how to monitor and clear the cache.
Failure
fmdt.log_parser() is currently unavailable.
Failure
Video.visu() is currently unavailable.
We can retrieve the tracking statistics produced by fmdt-check by chaining
the function calls detect() and check() together.
>>> check_res.gt_table
id types detects gts starts stops tracks
0 1 meteor 7 7 102 108 1
1 2 meteor 17 16 110 125 1
2 3 meteor 8 9 111 119 1
3 4 meteor 3 3 121 123 1
4 5 meteor 3 3 127 129 1
5 6 meteor 3 3 129 131 1
6 7 meteor 9 10 133 142 1
7 8 meteor 10 10 134 143 1
8 9 meteor 4 4 134 137 1
9 10 meteor 3 4 135 138 1
10 11 meteor 6 10 137 146 1
11 12 meteor 4 4 139 142 1
12 13 meteor 11 11 140 150 1
13 14 meteor 4 4 146 149 1
14 15 meteor 3 3 156 158 1
15 16 meteor 10 10 156 165 1
16 17 meteor 6 6 157 162 1
17 18 meteor 4 4 160 163 1
18 19 meteor 4 4 164 167 1
19 20 meteor 3 3 167 169 1
20 21 meteor 5 5 171 175 1
21 22 meteor 7 7 174 180 1
22 23 meteor 8 8 178 185 1
23 24 meteor 11 11 179 189 1
24 25 meteor 3 3 179 181 1
25 26 meteor 5 5 180 184 1
26 27 meteor 7 7 183 189 1
27 28 meteor 4 4 194 197 1
28 29 meteor 3 4 197 200 1
29 30 meteor 6 5 199 203 2
30 31 meteor 6 6 200 205 1
31 32 meteor 7 7 223 229 1
32 33 meteor 5 5 224 228 1
33 34 meteor 4 4 249 252 1
>>> check_res.meteor_stats()
type meteor
gt 34
ntrk 38
tpos 35
fpos 3
tneg 0
fneg 0
trk_rate 0.95
Name: 0, dtype: object
>>> check_res.star_stats()
type star
gt 0
ntrk 0
tpos 0
fpos 0
tneg 38
fneg 0
trk_rate NaN
Name: 1, dtype: object
>>> check_res.noise_stats()
type noise
gt 0
ntrk 0
tpos 0
fpos 0
tneg 38
fneg 0
trk_rate NaN
Name: 2, dtype: object
>>> check_res.all_stats()
type all
gt 34
ntrk 38
tpos 35
fpos 3
tneg 76
fneg 0
trk_rate 0.95
Name: 3, dtype: object
For more information about the results of these executables, consult this section.
VideoClip
The class fmdt.VideoClip is a subclass of fmdt.Video and is used to
represent a portion of specific video that contains meteors. This class is
primarily used when working with the window
videos as they are all 5 minutes long and each contain multiple meteors.
Creation
We can create a list[VideoClip] starting from a Video with known ground
truths. Let's take the first window as an example.
Make sure our video has ground truths in our database with has_meteors() and
then instantiate some VideoClip objects with create_clips()
>>> clips
[window_3_sony_0400-0405UTC.mp4 [773, 802], window_3_sony_0400-0405UTC.mp4 [1213, 1262], window_3_sony_0400-0405UTC.mp4 [1414, 1451], window_3_sony_0400-0405UTC.mp4 [2276, 2335], window_3_sony_0400-0405UTC.mp4 [2823, 2862], window_3_sony_0400-0405UTC.mp4 [2850, 2900], window_3_sony_0400-0405UTC.mp4 [2916, 2945], window_3_sony_0400-0405UTC.mp4 [3414, 3446], window_3_sony_0400-0405UTC.mp4 [3845, 3874], window_3_sony_0400-0405UTC.mp4 [4143, 4191], window_3_sony_0400-0405UTC.mp4 [4250, 4280], window_3_sony_0400-0405UTC.mp4 [4435, 4472], window_3_sony_0400-0405UTC.mp4 [5311, 5342], window_3_sony_0400-0405UTC.mp4 [6778, 6823], window_3_sony_0400-0405UTC.mp4 [7187, 7219]]
If we want to actually save these clips to disk, we add the parameter
save_to_disk=True
Running command 'ffmpeg -ss 00:00:30.920 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.160 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f0773-0802_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:00:48.520 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.960 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f1213-1262_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:00:56.560 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.480 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f1414-1451_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:01:31.040 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:02.360 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f2276-2335_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:01:52.920 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.560 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f2823-2862_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:01:54.000 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:02.000 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f2850-2900_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:01:56.640 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.160 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f2916-2945_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:02:16.560 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.280 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f3414-3446_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:02:33.800 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.160 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f3845-3874_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:02:45.720 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.920 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f4143-4191_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:02:50.000 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.200 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f4250-4280_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:02:57.400 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.480 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f4435-4472_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:03:32.440 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.240 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f5311-5342_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:04:31.120 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.800 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f6778-6823_.mp4 -loglevel error'
Running command 'ffmpeg -ss 00:04:47.480 -i /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC.mp4 -t 00:00:01.280 /run/media/ejovo/Seagate Portable Drive/Meteors/window_3_sony_0400-0405UTC/f7187-7219_.mp4 -loglevel error'
Each individual clip can be interfaced just like as a Video above thanks to
class inheritance. Here we showcase a few examples.
Retrieve the path to the video from which this clip was generated
Retrieve the full path to this clip
Run a detection
Ground Truths
We can retrieve all the ground truths from our database that are associated with
a particular video by using the Video.meteors() function. Start by loading in
our Draco6 videos.
d6_all = fmdt.load_draco6() # Loads all 52 Draco6 videos in our database
d6 = [v for v in d6_all if v.has_meteors()] # Filter out the 38 that have gts in our database
>>> len(d6_all)
52
>>> len(d6)
38
>>> d6
[Draconids-6mm1.00-2750-163200.avi, Draconids-6mm1.05-0750-164200.avi, Draconids-6mm1.14-1400-170300.avi, Draconids-6mm1.20-2350-171600.avi, Draconids-6mm1.29-2550-173600.avi, Draconids-6mm1.30-2050-173800.avi, Draconids-6mm1.32-3150-174200.avi, Draconids-6mm1.34-3050-174700.avi, Draconids-6mm2.00.01-1000-201100.avi, Draconids-6mm2.00.01-1500-201200.avi, Draconids-6mm2.00.01-2150-201200.avi, Draconids-6mm2.00.02-0700-201300.avi, Draconids-6mm2.00.03-0450-201500.avi, Draconids-6mm2.00.03-0550-201500.avi, Draconids-6mm2.00.03-0950-201500.avi, Draconids-6mm2.00.04-1500-201800.avi, Draconids-6mm2.00.04-1900-201900.avi, Draconids-6mm2.00.04-2950-201900.avi, Draconids-6mm2.00.05-0120-202000.avi, Draconids-6mm2.00.05-0350-202000.avi, Draconids-6mm2.00.07-0900-202400.avi, Draconids-6mm2.00.07-2400-202500.avi, Draconids-6mm2.00.07-3000-202530.avi, Draconids-6mm2.00.09-0600-202900.avi, Draconids-6mm2.00.09-1650-203000.avi, Draconids-6mm2.00.09-3000-203030.avi, Draconids-6mm2.00.10-0300-203100.avi, Draconids-6mm2.00.10-0350-203110.avi, Draconids-6mm2.00.10-1050-203200.avi, Draconids-6mm2.00.11-2100-203400.avi, Draconids-6mm2.00.11-680-203300.avi, Draconids-6mm2.00.11-780-203310.avi, Draconids-6mm2.00.12-1550-203600.avi, Draconids-6mm2.00.12-2550-203700.avi, Draconids-6mm2.00.12-3100-203730.avi, Draconids-6mm2.00.13-0680-203800.avi, Draconids-6mm2.00.13-3100-204000.avi, Draconids-6mm2.00.15-0750-204200.avi]
After only keeping videos that have ground truths in our database we retrieve the list of meteors associated with the first video:
>>> d6[2].full_path()
'/run/media/ejovo/Seagate Portable Drive/Meteors/Watec6mm/Meteor/Draconids-6mm1.14-1400-170300.avi'
>>> d6[2].meteors()
[<fmdt.truth.HumanDetection object at 0x7fcd9ae92bf0>]
So we can conclude that Draconids-6mm1.14-1400-170300.avi has one
human-verified ground truth meteor in our database.
Let's hold onto that truth.
Retrieve the trk list to see if the human detection is spotted.
res = d6[2].detect(ccl_hyst_lo=253, ccl_hyst_hi=255)
>>> fmdt.truth.is_meteor_detected(meteor=hum_det, tracking_list=res.trk_list)
True
Awesome! With args:
>>> print(res.args)
<fmdt.args.Args object>
====================
Detect parameters:
{'vid_in_path': '/run/media/ejovo/Seagate Portable Drive/Meteors/Watec6mm/Meteor/Draconids-6mm1.14-1400-170300.avi', 'ccl_hyst_lo': 253, 'ccl_hyst_hi': 255, 'trk_path': 'trk.txt'}
The meteor
>>> print(hum_det)
(Draconids-6mm1.14-1400-170300.avi, f0: 11, fT: 24, pos0: (11.0, 233.0), posT: (14.0, 273.0))
is associated with