megadetector 5.0.22__py3-none-any.whl → 5.0.24__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of megadetector might be problematic. Click here for more details.
- megadetector/api/synchronous/api_core/animal_detection_api/api_backend.py +2 -3
- megadetector/classification/merge_classification_detection_output.py +2 -2
- megadetector/data_management/coco_to_labelme.py +2 -1
- megadetector/data_management/databases/integrity_check_json_db.py +15 -14
- megadetector/data_management/databases/subset_json_db.py +49 -21
- megadetector/data_management/mewc_to_md.py +340 -0
- megadetector/data_management/wi_to_md.py +41 -0
- megadetector/data_management/yolo_output_to_md_output.py +15 -8
- megadetector/detection/process_video.py +24 -7
- megadetector/detection/pytorch_detector.py +841 -160
- megadetector/detection/run_detector.py +340 -146
- megadetector/detection/run_detector_batch.py +306 -70
- megadetector/detection/run_inference_with_yolov5_val.py +61 -4
- megadetector/detection/tf_detector.py +6 -1
- megadetector/postprocessing/{combine_api_outputs.py → combine_batch_outputs.py} +10 -13
- megadetector/postprocessing/compare_batch_results.py +68 -6
- megadetector/postprocessing/md_to_labelme.py +7 -7
- megadetector/postprocessing/md_to_wi.py +40 -0
- megadetector/postprocessing/merge_detections.py +1 -1
- megadetector/postprocessing/postprocess_batch_results.py +10 -3
- megadetector/postprocessing/separate_detections_into_folders.py +32 -4
- megadetector/postprocessing/validate_batch_results.py +9 -4
- megadetector/utils/ct_utils.py +172 -57
- megadetector/utils/gpu_test.py +107 -0
- megadetector/utils/md_tests.py +363 -108
- megadetector/utils/path_utils.py +9 -2
- megadetector/utils/wi_utils.py +1794 -0
- megadetector/visualization/visualization_utils.py +82 -16
- megadetector/visualization/visualize_db.py +25 -7
- megadetector/visualization/visualize_detector_output.py +60 -13
- {megadetector-5.0.22.dist-info → megadetector-5.0.24.dist-info}/LICENSE +0 -0
- {megadetector-5.0.22.dist-info → megadetector-5.0.24.dist-info}/METADATA +129 -143
- {megadetector-5.0.22.dist-info → megadetector-5.0.24.dist-info}/RECORD +35 -33
- {megadetector-5.0.22.dist-info → megadetector-5.0.24.dist-info}/top_level.txt +0 -0
- megadetector/detection/detector_training/__init__.py +0 -0
- megadetector/detection/detector_training/model_main_tf2.py +0 -114
- megadetector/utils/torch_test.py +0 -32
- {megadetector-5.0.22.dist-info → megadetector-5.0.24.dist-info}/WHEEL +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
yolo_output_to_md_output.py
|
|
4
4
|
|
|
5
|
-
Converts the output of YOLOv5's detect.py or val.py to the MD
|
|
5
|
+
Converts the output of YOLOv5's detect.py or val.py to the MD output format.
|
|
6
6
|
|
|
7
7
|
**Converting .txt files**
|
|
8
8
|
|
|
@@ -74,7 +74,7 @@ def read_classes_from_yolo_dataset_file(fn):
|
|
|
74
74
|
with open(fn,'r') as f:
|
|
75
75
|
lines = f.readlines()
|
|
76
76
|
|
|
77
|
-
pat = '\d+:.+'
|
|
77
|
+
pat = r'\d+:.+'
|
|
78
78
|
for s in lines:
|
|
79
79
|
if re.search(pat,s) is not None:
|
|
80
80
|
tokens = s.split(':')
|
|
@@ -281,7 +281,7 @@ def yolo_json_output_to_md_output(yolo_json_file,
|
|
|
281
281
|
output_det['category'] = str(int(yolo_cat_id))
|
|
282
282
|
conf = det['score']
|
|
283
283
|
if truncate_to_standard_md_precision:
|
|
284
|
-
conf = ct_utils.
|
|
284
|
+
conf = ct_utils.round_float(conf,CONF_DIGITS)
|
|
285
285
|
output_det['conf'] = conf
|
|
286
286
|
input_bbox = det['bbox']
|
|
287
287
|
|
|
@@ -301,7 +301,7 @@ def yolo_json_output_to_md_output(yolo_json_file,
|
|
|
301
301
|
box_width_relative,box_height_relative]
|
|
302
302
|
|
|
303
303
|
if truncate_to_standard_md_precision:
|
|
304
|
-
output_bbox = ct_utils.
|
|
304
|
+
output_bbox = ct_utils.round_float_array(output_bbox,COORD_DIGITS)
|
|
305
305
|
|
|
306
306
|
output_det['bbox'] = output_bbox
|
|
307
307
|
im['detections'].append(output_det)
|
|
@@ -332,7 +332,8 @@ def yolo_json_output_to_md_output(yolo_json_file,
|
|
|
332
332
|
def yolo_txt_output_to_md_output(input_results_folder,
|
|
333
333
|
image_folder,
|
|
334
334
|
output_file,
|
|
335
|
-
detector_tag=None
|
|
335
|
+
detector_tag=None,
|
|
336
|
+
truncate_to_standard_md_precision=True):
|
|
336
337
|
"""
|
|
337
338
|
Converts a folder of YOLO-output .txt files to MD .json format.
|
|
338
339
|
|
|
@@ -347,7 +348,9 @@ def yolo_txt_output_to_md_output(input_results_folder,
|
|
|
347
348
|
output_file (str): the MD-formatted .json file to which we should write
|
|
348
349
|
results
|
|
349
350
|
detector_tag (str, optional): string to put in the 'detector' field in the
|
|
350
|
-
output file
|
|
351
|
+
output file
|
|
352
|
+
truncate_to_standard_md_precision (bool, optional): set this to truncate to
|
|
353
|
+
COORD_DIGITS and CONF_DIGITS, like the standard MD pipeline does.
|
|
351
354
|
"""
|
|
352
355
|
|
|
353
356
|
assert os.path.isdir(input_results_folder)
|
|
@@ -398,12 +401,16 @@ def yolo_txt_output_to_md_output(input_results_folder,
|
|
|
398
401
|
api_box = ct_utils.convert_yolo_to_xywh([float(row[1]), float(row[2]),
|
|
399
402
|
float(row[3]), float(row[4])])
|
|
400
403
|
|
|
401
|
-
conf =
|
|
404
|
+
conf = float(row[5])
|
|
405
|
+
|
|
406
|
+
if truncate_to_standard_md_precision:
|
|
407
|
+
conf = ct_utils.round_float(conf, precision=CONF_DIGITS)
|
|
408
|
+
api_box = ct_utils.round_float_array(api_box, precision=COORD_DIGITS)
|
|
402
409
|
|
|
403
410
|
detections.append({
|
|
404
411
|
'category': str(category),
|
|
405
412
|
'conf': conf,
|
|
406
|
-
'bbox':
|
|
413
|
+
'bbox': api_box
|
|
407
414
|
})
|
|
408
415
|
|
|
409
416
|
images_entries.append({
|
|
@@ -28,6 +28,7 @@ from uuid import uuid1
|
|
|
28
28
|
from megadetector.detection import run_detector_batch
|
|
29
29
|
from megadetector.visualization import visualize_detector_output
|
|
30
30
|
from megadetector.utils.ct_utils import args_to_object
|
|
31
|
+
from megadetector.utils.ct_utils import dict_to_kvp_list, parse_kvp_list
|
|
31
32
|
from megadetector.utils.path_utils import insert_before_extension, clean_path
|
|
32
33
|
from megadetector.detection.video_utils import video_to_frames
|
|
33
34
|
from megadetector.detection.video_utils import run_callback_on_frames
|
|
@@ -163,7 +164,7 @@ class ProcessVideoOptions:
|
|
|
163
164
|
self.max_width = None
|
|
164
165
|
|
|
165
166
|
#: Run the model at this image size (don't mess with this unless you know what you're
|
|
166
|
-
#: getting into)
|
|
167
|
+
#: getting into)... if you just want to pass smaller frames to MD, use max_width
|
|
167
168
|
self.image_size = None
|
|
168
169
|
|
|
169
170
|
#: Enable image augmentation
|
|
@@ -178,6 +179,9 @@ class ProcessVideoOptions:
|
|
|
178
179
|
#: frame result for each video (default), or every frame that was processed?
|
|
179
180
|
self.include_all_processed_frames = False
|
|
180
181
|
|
|
182
|
+
#: Detector-specific options
|
|
183
|
+
self.detector_options = None
|
|
184
|
+
|
|
181
185
|
# ...class ProcessVideoOptions
|
|
182
186
|
|
|
183
187
|
|
|
@@ -402,7 +406,7 @@ def process_video(options):
|
|
|
402
406
|
print('Warning: frame_folder specified, but keep_extracted_frames is ' + \
|
|
403
407
|
'not; no raw frames will be written')
|
|
404
408
|
|
|
405
|
-
detector = load_detector(options.model_file)
|
|
409
|
+
detector = load_detector(options.model_file,detector_options=options.detector_options)
|
|
406
410
|
|
|
407
411
|
def frame_callback(image_np,image_id):
|
|
408
412
|
return detector.generate_detections_one_image(image_np,
|
|
@@ -475,7 +479,8 @@ def process_video(options):
|
|
|
475
479
|
class_mapping_filename=options.class_mapping_filename,
|
|
476
480
|
quiet=True,
|
|
477
481
|
augment=options.augment,
|
|
478
|
-
image_size=options.image_size
|
|
482
|
+
image_size=options.image_size,
|
|
483
|
+
detector_options=options.detector_options)
|
|
479
484
|
|
|
480
485
|
results = _add_frame_numbers_to_results(results)
|
|
481
486
|
|
|
@@ -612,7 +617,7 @@ def process_video_folder(options):
|
|
|
612
617
|
print('Warning: frame_folder specified, but keep_extracted_frames is ' + \
|
|
613
618
|
'not; no raw frames will be written')
|
|
614
619
|
|
|
615
|
-
detector = load_detector(options.model_file)
|
|
620
|
+
detector = load_detector(options.model_file,detector_options=options.detector_options)
|
|
616
621
|
|
|
617
622
|
def frame_callback(image_np,image_id):
|
|
618
623
|
return detector.generate_detections_one_image(image_np,
|
|
@@ -719,7 +724,8 @@ def process_video_folder(options):
|
|
|
719
724
|
class_mapping_filename=options.class_mapping_filename,
|
|
720
725
|
quiet=True,
|
|
721
726
|
augment=options.augment,
|
|
722
|
-
image_size=options.image_size
|
|
727
|
+
image_size=options.image_size,
|
|
728
|
+
detector_options=options.detector_options)
|
|
723
729
|
|
|
724
730
|
_add_frame_numbers_to_results(results)
|
|
725
731
|
|
|
@@ -910,6 +916,8 @@ def options_to_command(options):
|
|
|
910
916
|
cmd += ' --force_extracted_frame_folder_deletion'
|
|
911
917
|
if options.force_rendered_frame_folder_deletion:
|
|
912
918
|
cmd += ' --force_rendered_frame_folder_deletion'
|
|
919
|
+
if options.detector_options is not None and len(options.detector_options) > 0:
|
|
920
|
+
cmd += '--detector_options {}'.format(dict_to_kvp_list(options.detector_options))
|
|
913
921
|
|
|
914
922
|
return cmd
|
|
915
923
|
|
|
@@ -1209,14 +1217,23 @@ def main():
|
|
|
1209
1217
|
parser.add_argument('--allow_empty_videos',
|
|
1210
1218
|
action='store_true',
|
|
1211
1219
|
help='By default, videos with no retrievable frames cause an error, this makes it a warning')
|
|
1212
|
-
|
|
1220
|
+
|
|
1221
|
+
parser.add_argument(
|
|
1222
|
+
'--detector_options',
|
|
1223
|
+
nargs='*',
|
|
1224
|
+
metavar='KEY=VALUE',
|
|
1225
|
+
default='',
|
|
1226
|
+
help='Detector-specific options, as a space-separated list of key-value pairs')
|
|
1227
|
+
|
|
1213
1228
|
if len(sys.argv[1:]) == 0:
|
|
1214
1229
|
parser.print_help()
|
|
1215
1230
|
parser.exit()
|
|
1216
1231
|
|
|
1217
1232
|
args = parser.parse_args()
|
|
1218
|
-
options = ProcessVideoOptions()
|
|
1233
|
+
options = ProcessVideoOptions()
|
|
1219
1234
|
args_to_object(args,options)
|
|
1235
|
+
|
|
1236
|
+
options.detector_options = parse_kvp_list(args.detector_options)
|
|
1220
1237
|
|
|
1221
1238
|
if os.path.isdir(options.input_video_file):
|
|
1222
1239
|
process_video_folder(options)
|