megadetector 10.0.13__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/__init__.py +0 -0
- megadetector/api/__init__.py +0 -0
- megadetector/api/batch_processing/integration/digiKam/setup.py +6 -0
- megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +465 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/config_template.py +5 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +125 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +55 -0
- megadetector/classification/__init__.py +0 -0
- megadetector/classification/aggregate_classifier_probs.py +108 -0
- megadetector/classification/analyze_failed_images.py +227 -0
- megadetector/classification/cache_batchapi_outputs.py +198 -0
- megadetector/classification/create_classification_dataset.py +626 -0
- megadetector/classification/crop_detections.py +516 -0
- megadetector/classification/csv_to_json.py +226 -0
- megadetector/classification/detect_and_crop.py +853 -0
- megadetector/classification/efficientnet/__init__.py +9 -0
- megadetector/classification/efficientnet/model.py +415 -0
- megadetector/classification/efficientnet/utils.py +608 -0
- megadetector/classification/evaluate_model.py +520 -0
- megadetector/classification/identify_mislabeled_candidates.py +152 -0
- megadetector/classification/json_to_azcopy_list.py +63 -0
- megadetector/classification/json_validator.py +696 -0
- megadetector/classification/map_classification_categories.py +276 -0
- megadetector/classification/merge_classification_detection_output.py +509 -0
- megadetector/classification/prepare_classification_script.py +194 -0
- megadetector/classification/prepare_classification_script_mc.py +228 -0
- megadetector/classification/run_classifier.py +287 -0
- megadetector/classification/save_mislabeled.py +110 -0
- megadetector/classification/train_classifier.py +827 -0
- megadetector/classification/train_classifier_tf.py +725 -0
- megadetector/classification/train_utils.py +323 -0
- megadetector/data_management/__init__.py +0 -0
- megadetector/data_management/animl_to_md.py +161 -0
- megadetector/data_management/annotations/__init__.py +0 -0
- megadetector/data_management/annotations/annotation_constants.py +33 -0
- megadetector/data_management/camtrap_dp_to_coco.py +270 -0
- megadetector/data_management/cct_json_utils.py +566 -0
- megadetector/data_management/cct_to_md.py +184 -0
- megadetector/data_management/cct_to_wi.py +293 -0
- megadetector/data_management/coco_to_labelme.py +284 -0
- megadetector/data_management/coco_to_yolo.py +702 -0
- megadetector/data_management/databases/__init__.py +0 -0
- megadetector/data_management/databases/add_width_and_height_to_db.py +107 -0
- megadetector/data_management/databases/combine_coco_camera_traps_files.py +210 -0
- megadetector/data_management/databases/integrity_check_json_db.py +528 -0
- megadetector/data_management/databases/subset_json_db.py +195 -0
- megadetector/data_management/generate_crops_from_cct.py +200 -0
- megadetector/data_management/get_image_sizes.py +164 -0
- megadetector/data_management/labelme_to_coco.py +559 -0
- megadetector/data_management/labelme_to_yolo.py +349 -0
- megadetector/data_management/lila/__init__.py +0 -0
- megadetector/data_management/lila/create_lila_blank_set.py +556 -0
- megadetector/data_management/lila/create_lila_test_set.py +187 -0
- megadetector/data_management/lila/create_links_to_md_results_files.py +106 -0
- megadetector/data_management/lila/download_lila_subset.py +182 -0
- megadetector/data_management/lila/generate_lila_per_image_labels.py +777 -0
- megadetector/data_management/lila/get_lila_annotation_counts.py +174 -0
- megadetector/data_management/lila/get_lila_image_counts.py +112 -0
- megadetector/data_management/lila/lila_common.py +319 -0
- megadetector/data_management/lila/test_lila_metadata_urls.py +164 -0
- megadetector/data_management/mewc_to_md.py +344 -0
- megadetector/data_management/ocr_tools.py +873 -0
- megadetector/data_management/read_exif.py +964 -0
- megadetector/data_management/remap_coco_categories.py +195 -0
- megadetector/data_management/remove_exif.py +156 -0
- megadetector/data_management/rename_images.py +194 -0
- megadetector/data_management/resize_coco_dataset.py +663 -0
- megadetector/data_management/speciesnet_to_md.py +41 -0
- megadetector/data_management/wi_download_csv_to_coco.py +247 -0
- megadetector/data_management/yolo_output_to_md_output.py +594 -0
- megadetector/data_management/yolo_to_coco.py +876 -0
- megadetector/data_management/zamba_to_md.py +188 -0
- megadetector/detection/__init__.py +0 -0
- megadetector/detection/change_detection.py +840 -0
- megadetector/detection/process_video.py +479 -0
- megadetector/detection/pytorch_detector.py +1451 -0
- megadetector/detection/run_detector.py +1267 -0
- megadetector/detection/run_detector_batch.py +2159 -0
- megadetector/detection/run_inference_with_yolov5_val.py +1314 -0
- megadetector/detection/run_md_and_speciesnet.py +1494 -0
- megadetector/detection/run_tiled_inference.py +1038 -0
- megadetector/detection/tf_detector.py +209 -0
- megadetector/detection/video_utils.py +1379 -0
- megadetector/postprocessing/__init__.py +0 -0
- megadetector/postprocessing/add_max_conf.py +72 -0
- megadetector/postprocessing/categorize_detections_by_size.py +166 -0
- megadetector/postprocessing/classification_postprocessing.py +1752 -0
- megadetector/postprocessing/combine_batch_outputs.py +249 -0
- megadetector/postprocessing/compare_batch_results.py +2110 -0
- megadetector/postprocessing/convert_output_format.py +403 -0
- megadetector/postprocessing/create_crop_folder.py +629 -0
- megadetector/postprocessing/detector_calibration.py +570 -0
- megadetector/postprocessing/generate_csv_report.py +522 -0
- megadetector/postprocessing/load_api_results.py +223 -0
- megadetector/postprocessing/md_to_coco.py +428 -0
- megadetector/postprocessing/md_to_labelme.py +351 -0
- megadetector/postprocessing/md_to_wi.py +41 -0
- megadetector/postprocessing/merge_detections.py +392 -0
- megadetector/postprocessing/postprocess_batch_results.py +2077 -0
- megadetector/postprocessing/remap_detection_categories.py +226 -0
- megadetector/postprocessing/render_detection_confusion_matrix.py +677 -0
- megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +206 -0
- megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +82 -0
- megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +1665 -0
- megadetector/postprocessing/separate_detections_into_folders.py +795 -0
- megadetector/postprocessing/subset_json_detector_output.py +964 -0
- megadetector/postprocessing/top_folders_to_bottom.py +238 -0
- megadetector/postprocessing/validate_batch_results.py +332 -0
- megadetector/taxonomy_mapping/__init__.py +0 -0
- megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +491 -0
- megadetector/taxonomy_mapping/map_new_lila_datasets.py +213 -0
- megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +165 -0
- megadetector/taxonomy_mapping/preview_lila_taxonomy.py +543 -0
- megadetector/taxonomy_mapping/retrieve_sample_image.py +71 -0
- megadetector/taxonomy_mapping/simple_image_download.py +224 -0
- megadetector/taxonomy_mapping/species_lookup.py +1008 -0
- megadetector/taxonomy_mapping/taxonomy_csv_checker.py +159 -0
- megadetector/taxonomy_mapping/taxonomy_graph.py +346 -0
- megadetector/taxonomy_mapping/validate_lila_category_mappings.py +83 -0
- megadetector/tests/__init__.py +0 -0
- megadetector/tests/test_nms_synthetic.py +335 -0
- megadetector/utils/__init__.py +0 -0
- megadetector/utils/ct_utils.py +1857 -0
- megadetector/utils/directory_listing.py +199 -0
- megadetector/utils/extract_frames_from_video.py +307 -0
- megadetector/utils/gpu_test.py +125 -0
- megadetector/utils/md_tests.py +2072 -0
- megadetector/utils/path_utils.py +2832 -0
- megadetector/utils/process_utils.py +172 -0
- megadetector/utils/split_locations_into_train_val.py +237 -0
- megadetector/utils/string_utils.py +234 -0
- megadetector/utils/url_utils.py +825 -0
- megadetector/utils/wi_platform_utils.py +968 -0
- megadetector/utils/wi_taxonomy_utils.py +1759 -0
- megadetector/utils/write_html_image_list.py +239 -0
- megadetector/visualization/__init__.py +0 -0
- megadetector/visualization/plot_utils.py +309 -0
- megadetector/visualization/render_images_with_thumbnails.py +243 -0
- megadetector/visualization/visualization_utils.py +1940 -0
- megadetector/visualization/visualize_db.py +630 -0
- megadetector/visualization/visualize_detector_output.py +479 -0
- megadetector/visualization/visualize_video_output.py +705 -0
- megadetector-10.0.13.dist-info/METADATA +134 -0
- megadetector-10.0.13.dist-info/RECORD +147 -0
- megadetector-10.0.13.dist-info/WHEEL +5 -0
- megadetector-10.0.13.dist-info/licenses/LICENSE +19 -0
- megadetector-10.0.13.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
camtrap_dp_to_coco.py
|
|
4
|
+
|
|
5
|
+
Parse a very limited subset of the Camtrap DP data package format:
|
|
6
|
+
|
|
7
|
+
https://camtrap-dp.tdwg.org/
|
|
8
|
+
|
|
9
|
+
...and convert to COCO format. Assumes that all required metadata files have been
|
|
10
|
+
put in the same directory (which is standard).
|
|
11
|
+
|
|
12
|
+
Does not currently parse bounding boxes, just attaches species labels to images.
|
|
13
|
+
|
|
14
|
+
Currently supports only sequence-level labeling.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
#%% Imports and constants
|
|
19
|
+
|
|
20
|
+
import os
|
|
21
|
+
import json
|
|
22
|
+
import argparse
|
|
23
|
+
|
|
24
|
+
import pandas as pd
|
|
25
|
+
|
|
26
|
+
from dateutil import parser as dateparser
|
|
27
|
+
|
|
28
|
+
from collections import defaultdict
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
#%% Functions
|
|
32
|
+
|
|
33
|
+
def camtrap_dp_to_coco(camtrap_dp_folder,output_file=None):
|
|
34
|
+
"""
|
|
35
|
+
Convert the Camtrap DP package in [camtrap_dp_folder] to COCO.
|
|
36
|
+
|
|
37
|
+
Does not validate images, just converts. Use integrity_check_json_db to validate
|
|
38
|
+
the resulting COCO file.
|
|
39
|
+
|
|
40
|
+
Optionally writes the results to [output_file]
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
camtrap_dp_folder (str): input folder, containing a CamtrapDP package
|
|
44
|
+
output_file (str, optional): COCO-formatted output file
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
required_files = ('datapackage.json','deployments.csv','events.csv','media.csv','observations.csv')
|
|
48
|
+
|
|
49
|
+
for fn in required_files:
|
|
50
|
+
fn_abs = os.path.join(camtrap_dp_folder,fn)
|
|
51
|
+
assert os.path.isfile(fn_abs), 'Could not find required file {}'.format(fn_abs)
|
|
52
|
+
|
|
53
|
+
with open(os.path.join(camtrap_dp_folder,'datapackage.json'),'r') as f:
|
|
54
|
+
datapackage = json.load(f)
|
|
55
|
+
|
|
56
|
+
assert datapackage['profile'] == 'https://raw.githubusercontent.com/tdwg/camtrap-dp/1.0/camtrap-dp-profile.json', \
|
|
57
|
+
'I only know how to parse Camtrap DP 1.0 packages'
|
|
58
|
+
|
|
59
|
+
deployments_file = None
|
|
60
|
+
events_file = None
|
|
61
|
+
media_file = None
|
|
62
|
+
observations_file = None
|
|
63
|
+
|
|
64
|
+
resources = datapackage['resources']
|
|
65
|
+
for r in resources:
|
|
66
|
+
if r['name'] == 'deployments':
|
|
67
|
+
deployments_file = r['path']
|
|
68
|
+
elif r['name'] == 'media':
|
|
69
|
+
media_file = r['path']
|
|
70
|
+
elif r['name'] == 'events':
|
|
71
|
+
events_file = r['path']
|
|
72
|
+
elif r['name'] == 'observations':
|
|
73
|
+
observations_file = r['path']
|
|
74
|
+
|
|
75
|
+
assert deployments_file is not None, 'No deployment file specified'
|
|
76
|
+
assert events_file is not None, 'No events file specified'
|
|
77
|
+
assert media_file is not None, 'No media file specified'
|
|
78
|
+
assert observations_file is not None, 'No observation file specified'
|
|
79
|
+
|
|
80
|
+
deployments_df = pd.read_csv(os.path.join(camtrap_dp_folder,deployments_file))
|
|
81
|
+
events_df = pd.read_csv(os.path.join(camtrap_dp_folder,events_file))
|
|
82
|
+
media_df = pd.read_csv(os.path.join(camtrap_dp_folder,media_file))
|
|
83
|
+
observations_df = pd.read_csv(os.path.join(camtrap_dp_folder,observations_file))
|
|
84
|
+
|
|
85
|
+
print('Read {} deployment lines'.format(len(deployments_df)))
|
|
86
|
+
print('Read {} events lines'.format(len(events_df)))
|
|
87
|
+
print('Read {} media lines'.format(len(media_df)))
|
|
88
|
+
print('Read {} observation lines'.format(len(observations_df)))
|
|
89
|
+
|
|
90
|
+
media_id_to_media_info = {}
|
|
91
|
+
|
|
92
|
+
# i_row = 0; row = media_df.iloc[i_row]
|
|
93
|
+
for i_row,row in media_df.iterrows():
|
|
94
|
+
media_info = {}
|
|
95
|
+
media_info['file_name'] = os.path.join(row['filePath'],row['fileName']).replace('\\','/')
|
|
96
|
+
media_info['location'] = row['deploymentID']
|
|
97
|
+
media_info['id'] = row['mediaID']
|
|
98
|
+
media_info['datetime'] = row['timestamp']
|
|
99
|
+
media_info['datetime'] = dateparser.parse(media_info['datetime'])
|
|
100
|
+
media_info['frame_num'] = -1
|
|
101
|
+
media_info['seq_num_frames'] = -1
|
|
102
|
+
media_id_to_media_info[row['mediaID']] = media_info
|
|
103
|
+
|
|
104
|
+
event_id_to_media_ids = defaultdict(list)
|
|
105
|
+
|
|
106
|
+
# i_row = 0; row = events_df.iloc[i_row]
|
|
107
|
+
for i_row,row in events_df.iterrows():
|
|
108
|
+
media_id = row['mediaID']
|
|
109
|
+
assert media_id in media_id_to_media_info
|
|
110
|
+
event_id_to_media_ids[row['eventID']].append(media_id)
|
|
111
|
+
|
|
112
|
+
event_id_to_category_names = defaultdict(set)
|
|
113
|
+
|
|
114
|
+
# i_row = 0; row = observations_df.iloc[i_row]
|
|
115
|
+
for i_row,row in observations_df.iterrows():
|
|
116
|
+
|
|
117
|
+
if row['observationLevel'] != 'event':
|
|
118
|
+
raise ValueError("I don't know how to parse image-level events yet")
|
|
119
|
+
|
|
120
|
+
if row['observationType'] == 'blank':
|
|
121
|
+
event_id_to_category_names[row['eventID']].add('empty')
|
|
122
|
+
elif row['observationType'] == 'unknown':
|
|
123
|
+
event_id_to_category_names[row['eventID']].add('unknown')
|
|
124
|
+
elif row['observationType'] == 'human':
|
|
125
|
+
assert row['scientificName'] == 'Homo sapiens'
|
|
126
|
+
event_id_to_category_names[row['eventID']].add(row['scientificName'])
|
|
127
|
+
else:
|
|
128
|
+
assert row['observationType'] == 'animal'
|
|
129
|
+
assert isinstance(row['scientificName'],str)
|
|
130
|
+
event_id_to_category_names[row['eventID']].add(row['scientificName'])
|
|
131
|
+
|
|
132
|
+
# Sort images within an event into frame numbers
|
|
133
|
+
#
|
|
134
|
+
# event_id = next(iter(event_id_to_media_ids))
|
|
135
|
+
for event_id in event_id_to_media_ids.keys():
|
|
136
|
+
media_ids_this_event = event_id_to_media_ids[event_id]
|
|
137
|
+
media_info_this_event = [media_id_to_media_info[media_id] for media_id in media_ids_this_event]
|
|
138
|
+
media_info_this_event = sorted(media_info_this_event, key=lambda x: x['datetime'])
|
|
139
|
+
for i_media,media_info in enumerate(media_info_this_event):
|
|
140
|
+
media_info['frame_num'] = i_media
|
|
141
|
+
media_info['seq_num_frames'] = len(media_info_this_event)
|
|
142
|
+
media_info['seq_id'] = event_id
|
|
143
|
+
|
|
144
|
+
# Create category names
|
|
145
|
+
category_name_to_category_id = {'empty':0}
|
|
146
|
+
for event_id in event_id_to_category_names:
|
|
147
|
+
category_names_this_event = event_id_to_category_names[event_id]
|
|
148
|
+
for name in category_names_this_event:
|
|
149
|
+
if name not in category_name_to_category_id:
|
|
150
|
+
category_name_to_category_id[name] = len(category_name_to_category_id)
|
|
151
|
+
|
|
152
|
+
# Move everything into COCO format
|
|
153
|
+
images = list(media_id_to_media_info.values())
|
|
154
|
+
|
|
155
|
+
categories = []
|
|
156
|
+
for name in category_name_to_category_id:
|
|
157
|
+
categories.append({'name':name,'id':category_name_to_category_id[name]})
|
|
158
|
+
info = {'version':1.0,'description':datapackage['name']}
|
|
159
|
+
|
|
160
|
+
# Create annotations
|
|
161
|
+
annotations = []
|
|
162
|
+
|
|
163
|
+
for event_id in event_id_to_media_ids.keys():
|
|
164
|
+
i_ann = 0
|
|
165
|
+
media_ids_this_event = event_id_to_media_ids[event_id]
|
|
166
|
+
media_info_this_event = [media_id_to_media_info[media_id] for media_id in media_ids_this_event]
|
|
167
|
+
categories_this_event = event_id_to_category_names[event_id]
|
|
168
|
+
for im in media_info_this_event:
|
|
169
|
+
for category_name in categories_this_event:
|
|
170
|
+
ann = {}
|
|
171
|
+
ann['id'] = event_id + '_' + str(i_ann)
|
|
172
|
+
i_ann += 1
|
|
173
|
+
ann['image_id'] = im['id']
|
|
174
|
+
ann['category_id'] = category_name_to_category_id[category_name]
|
|
175
|
+
ann['sequence_level_annotation'] = True
|
|
176
|
+
annotations.append(ann)
|
|
177
|
+
|
|
178
|
+
coco_data = {}
|
|
179
|
+
coco_data['images'] = images
|
|
180
|
+
coco_data['annotations'] = annotations
|
|
181
|
+
coco_data['categories'] = categories
|
|
182
|
+
coco_data['info'] = info
|
|
183
|
+
|
|
184
|
+
for im in coco_data['images']:
|
|
185
|
+
im['datetime'] = str(im['datetime'] )
|
|
186
|
+
|
|
187
|
+
if output_file is not None:
|
|
188
|
+
with open(output_file,'w') as f:
|
|
189
|
+
json.dump(coco_data,f,indent=1)
|
|
190
|
+
|
|
191
|
+
return coco_data
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
#%% Interactive driver
|
|
195
|
+
|
|
196
|
+
if False:
|
|
197
|
+
|
|
198
|
+
pass
|
|
199
|
+
|
|
200
|
+
#%%
|
|
201
|
+
|
|
202
|
+
camtrap_dp_folder = r'C:\temp\pilot2\pilot2'
|
|
203
|
+
coco_file = os.path.join(camtrap_dp_folder,'test-coco.json')
|
|
204
|
+
coco_data = camtrap_dp_to_coco(camtrap_dp_folder,
|
|
205
|
+
output_file=coco_file)
|
|
206
|
+
|
|
207
|
+
#%% Validate
|
|
208
|
+
|
|
209
|
+
from megadetector.data_management.databases.integrity_check_json_db import \
|
|
210
|
+
integrity_check_json_db, IntegrityCheckOptions
|
|
211
|
+
|
|
212
|
+
options = IntegrityCheckOptions()
|
|
213
|
+
|
|
214
|
+
options.baseDir = camtrap_dp_folder
|
|
215
|
+
options.bCheckImageSizes = False
|
|
216
|
+
options.bCheckImageExistence = True
|
|
217
|
+
options.bFindUnusedImages = True
|
|
218
|
+
options.bRequireLocation = True
|
|
219
|
+
options.iMaxNumImages = -1
|
|
220
|
+
options.nThreads = 1
|
|
221
|
+
options.verbose = True
|
|
222
|
+
|
|
223
|
+
sorted_categories, data, error_info = integrity_check_json_db(coco_file,options)
|
|
224
|
+
|
|
225
|
+
#%% Preview
|
|
226
|
+
|
|
227
|
+
from megadetector.visualization.visualize_db import DbVizOptions, visualize_db
|
|
228
|
+
|
|
229
|
+
options = DbVizOptions()
|
|
230
|
+
options.parallelize_rendering = True
|
|
231
|
+
options.parallelize_rendering_with_threads = True
|
|
232
|
+
options.parallelize_rendering_n_cores = 10
|
|
233
|
+
|
|
234
|
+
preview_dir = r'c:\temp\camtrapdp-preview'
|
|
235
|
+
html_output_file, image_db = visualize_db(coco_file, preview_dir, camtrap_dp_folder, options=options)
|
|
236
|
+
|
|
237
|
+
from megadetector.utils.path_utils import open_file
|
|
238
|
+
open_file(html_output_file)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
#%% Command-line driver
|
|
242
|
+
|
|
243
|
+
def main():
|
|
244
|
+
"""
|
|
245
|
+
Command-line interface to convert Camtrap DP to COCO.
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
parser = argparse.ArgumentParser(description='Convert Camtrap DP to COCO format')
|
|
249
|
+
parser.add_argument('camtrap_dp_folder', type=str,
|
|
250
|
+
help='Input folder, containing a CamtrapDP package')
|
|
251
|
+
parser.add_argument('--output_file', type=str, default=None,
|
|
252
|
+
help='COCO-formatted output file (defaults to [camtrap_dp_folder]_coco.json)')
|
|
253
|
+
|
|
254
|
+
args = parser.parse_args()
|
|
255
|
+
|
|
256
|
+
if args.output_file is None:
|
|
257
|
+
# Default output file name: [camtrap_dp_folder]_coco.json
|
|
258
|
+
#
|
|
259
|
+
# Remove trailing slash if present
|
|
260
|
+
folder_name = args.camtrap_dp_folder.rstrip(os.sep)
|
|
261
|
+
output_file = folder_name + '_coco.json'
|
|
262
|
+
else:
|
|
263
|
+
output_file = args.output_file
|
|
264
|
+
|
|
265
|
+
camtrap_dp_to_coco(camtrap_dp_folder=args.camtrap_dp_folder, output_file=output_file)
|
|
266
|
+
print(f"Successfully converted Camtrap DP package at '{args.camtrap_dp_folder}' to " + \
|
|
267
|
+
f"COCO format at '{output_file}'")
|
|
268
|
+
|
|
269
|
+
if __name__ == '__main__':
|
|
270
|
+
main()
|