megadetector 5.0.8__py3-none-any.whl → 5.0.10__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.

Files changed (190) hide show
  1. api/__init__.py +0 -0
  2. api/batch_processing/__init__.py +0 -0
  3. api/batch_processing/api_core/__init__.py +0 -0
  4. api/batch_processing/api_core/batch_service/__init__.py +0 -0
  5. api/batch_processing/api_core/batch_service/score.py +0 -1
  6. api/batch_processing/api_core/server_job_status_table.py +0 -1
  7. api/batch_processing/api_core_support/__init__.py +0 -0
  8. api/batch_processing/api_core_support/aggregate_results_manually.py +0 -1
  9. api/batch_processing/api_support/__init__.py +0 -0
  10. api/batch_processing/api_support/summarize_daily_activity.py +0 -1
  11. api/batch_processing/data_preparation/__init__.py +0 -0
  12. api/batch_processing/data_preparation/manage_local_batch.py +65 -65
  13. api/batch_processing/data_preparation/manage_video_batch.py +8 -8
  14. api/batch_processing/integration/digiKam/xmp_integration.py +0 -1
  15. api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +0 -1
  16. api/batch_processing/postprocessing/__init__.py +0 -0
  17. api/batch_processing/postprocessing/add_max_conf.py +12 -12
  18. api/batch_processing/postprocessing/categorize_detections_by_size.py +32 -14
  19. api/batch_processing/postprocessing/combine_api_outputs.py +68 -54
  20. api/batch_processing/postprocessing/compare_batch_results.py +113 -43
  21. api/batch_processing/postprocessing/convert_output_format.py +41 -16
  22. api/batch_processing/postprocessing/load_api_results.py +16 -17
  23. api/batch_processing/postprocessing/md_to_coco.py +31 -21
  24. api/batch_processing/postprocessing/md_to_labelme.py +52 -22
  25. api/batch_processing/postprocessing/merge_detections.py +14 -14
  26. api/batch_processing/postprocessing/postprocess_batch_results.py +246 -174
  27. api/batch_processing/postprocessing/remap_detection_categories.py +32 -25
  28. api/batch_processing/postprocessing/render_detection_confusion_matrix.py +60 -27
  29. api/batch_processing/postprocessing/repeat_detection_elimination/find_repeat_detections.py +53 -44
  30. api/batch_processing/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +25 -14
  31. api/batch_processing/postprocessing/repeat_detection_elimination/repeat_detections_core.py +242 -158
  32. api/batch_processing/postprocessing/separate_detections_into_folders.py +159 -114
  33. api/batch_processing/postprocessing/subset_json_detector_output.py +146 -169
  34. api/batch_processing/postprocessing/top_folders_to_bottom.py +77 -43
  35. api/synchronous/__init__.py +0 -0
  36. api/synchronous/api_core/animal_detection_api/__init__.py +0 -0
  37. api/synchronous/api_core/animal_detection_api/api_backend.py +0 -2
  38. api/synchronous/api_core/animal_detection_api/api_frontend.py +266 -268
  39. api/synchronous/api_core/animal_detection_api/config.py +35 -35
  40. api/synchronous/api_core/tests/__init__.py +0 -0
  41. api/synchronous/api_core/tests/load_test.py +109 -109
  42. classification/__init__.py +0 -0
  43. classification/aggregate_classifier_probs.py +21 -24
  44. classification/analyze_failed_images.py +11 -13
  45. classification/cache_batchapi_outputs.py +51 -51
  46. classification/create_classification_dataset.py +69 -68
  47. classification/crop_detections.py +54 -53
  48. classification/csv_to_json.py +97 -100
  49. classification/detect_and_crop.py +105 -105
  50. classification/evaluate_model.py +43 -42
  51. classification/identify_mislabeled_candidates.py +47 -46
  52. classification/json_to_azcopy_list.py +10 -10
  53. classification/json_validator.py +72 -71
  54. classification/map_classification_categories.py +44 -43
  55. classification/merge_classification_detection_output.py +68 -68
  56. classification/prepare_classification_script.py +157 -154
  57. classification/prepare_classification_script_mc.py +228 -228
  58. classification/run_classifier.py +27 -26
  59. classification/save_mislabeled.py +30 -30
  60. classification/train_classifier.py +20 -20
  61. classification/train_classifier_tf.py +21 -22
  62. classification/train_utils.py +10 -10
  63. data_management/__init__.py +0 -0
  64. data_management/annotations/__init__.py +0 -0
  65. data_management/annotations/annotation_constants.py +18 -31
  66. data_management/camtrap_dp_to_coco.py +238 -0
  67. data_management/cct_json_utils.py +102 -59
  68. data_management/cct_to_md.py +176 -158
  69. data_management/cct_to_wi.py +247 -219
  70. data_management/coco_to_labelme.py +272 -263
  71. data_management/coco_to_yolo.py +79 -58
  72. data_management/databases/__init__.py +0 -0
  73. data_management/databases/add_width_and_height_to_db.py +20 -16
  74. data_management/databases/combine_coco_camera_traps_files.py +35 -31
  75. data_management/databases/integrity_check_json_db.py +62 -24
  76. data_management/databases/subset_json_db.py +24 -15
  77. data_management/generate_crops_from_cct.py +27 -45
  78. data_management/get_image_sizes.py +188 -162
  79. data_management/importers/add_nacti_sizes.py +8 -8
  80. data_management/importers/add_timestamps_to_icct.py +78 -78
  81. data_management/importers/animl_results_to_md_results.py +158 -158
  82. data_management/importers/auckland_doc_test_to_json.py +9 -9
  83. data_management/importers/auckland_doc_to_json.py +8 -8
  84. data_management/importers/awc_to_json.py +7 -7
  85. data_management/importers/bellevue_to_json.py +15 -15
  86. data_management/importers/cacophony-thermal-importer.py +13 -13
  87. data_management/importers/carrizo_shrubfree_2018.py +8 -8
  88. data_management/importers/carrizo_trail_cam_2017.py +8 -8
  89. data_management/importers/cct_field_adjustments.py +9 -9
  90. data_management/importers/channel_islands_to_cct.py +10 -10
  91. data_management/importers/eMammal/copy_and_unzip_emammal.py +1 -0
  92. data_management/importers/ena24_to_json.py +7 -7
  93. data_management/importers/filenames_to_json.py +8 -8
  94. data_management/importers/helena_to_cct.py +7 -7
  95. data_management/importers/idaho-camera-traps.py +7 -7
  96. data_management/importers/idfg_iwildcam_lila_prep.py +10 -10
  97. data_management/importers/jb_csv_to_json.py +9 -9
  98. data_management/importers/mcgill_to_json.py +8 -8
  99. data_management/importers/missouri_to_json.py +18 -18
  100. data_management/importers/nacti_fieldname_adjustments.py +10 -10
  101. data_management/importers/noaa_seals_2019.py +7 -7
  102. data_management/importers/pc_to_json.py +7 -7
  103. data_management/importers/plot_wni_giraffes.py +7 -7
  104. data_management/importers/prepare-noaa-fish-data-for-lila.py +359 -359
  105. data_management/importers/prepare_zsl_imerit.py +7 -7
  106. data_management/importers/rspb_to_json.py +8 -8
  107. data_management/importers/save_the_elephants_survey_A.py +8 -8
  108. data_management/importers/save_the_elephants_survey_B.py +9 -9
  109. data_management/importers/snapshot_safari_importer.py +26 -26
  110. data_management/importers/snapshot_safari_importer_reprise.py +665 -665
  111. data_management/importers/snapshot_serengeti_lila.py +14 -14
  112. data_management/importers/sulross_get_exif.py +8 -9
  113. data_management/importers/timelapse_csv_set_to_json.py +11 -11
  114. data_management/importers/ubc_to_json.py +13 -13
  115. data_management/importers/umn_to_json.py +7 -7
  116. data_management/importers/wellington_to_json.py +8 -8
  117. data_management/importers/wi_to_json.py +9 -9
  118. data_management/importers/zamba_results_to_md_results.py +181 -181
  119. data_management/labelme_to_coco.py +65 -24
  120. data_management/labelme_to_yolo.py +8 -8
  121. data_management/lila/__init__.py +0 -0
  122. data_management/lila/add_locations_to_island_camera_traps.py +9 -9
  123. data_management/lila/add_locations_to_nacti.py +147 -147
  124. data_management/lila/create_lila_blank_set.py +13 -13
  125. data_management/lila/create_lila_test_set.py +8 -8
  126. data_management/lila/create_links_to_md_results_files.py +106 -106
  127. data_management/lila/download_lila_subset.py +44 -110
  128. data_management/lila/generate_lila_per_image_labels.py +55 -42
  129. data_management/lila/get_lila_annotation_counts.py +18 -15
  130. data_management/lila/get_lila_image_counts.py +11 -11
  131. data_management/lila/lila_common.py +96 -33
  132. data_management/lila/test_lila_metadata_urls.py +132 -116
  133. data_management/ocr_tools.py +173 -128
  134. data_management/read_exif.py +110 -97
  135. data_management/remap_coco_categories.py +83 -83
  136. data_management/remove_exif.py +58 -62
  137. data_management/resize_coco_dataset.py +30 -23
  138. data_management/wi_download_csv_to_coco.py +246 -239
  139. data_management/yolo_output_to_md_output.py +86 -73
  140. data_management/yolo_to_coco.py +300 -60
  141. detection/__init__.py +0 -0
  142. detection/detector_training/__init__.py +0 -0
  143. detection/process_video.py +85 -33
  144. detection/pytorch_detector.py +43 -25
  145. detection/run_detector.py +157 -72
  146. detection/run_detector_batch.py +179 -113
  147. detection/run_inference_with_yolov5_val.py +108 -48
  148. detection/run_tiled_inference.py +111 -40
  149. detection/tf_detector.py +51 -29
  150. detection/video_utils.py +606 -521
  151. docs/source/conf.py +43 -0
  152. md_utils/__init__.py +0 -0
  153. md_utils/azure_utils.py +9 -9
  154. md_utils/ct_utils.py +228 -68
  155. md_utils/directory_listing.py +59 -64
  156. md_utils/md_tests.py +968 -871
  157. md_utils/path_utils.py +460 -134
  158. md_utils/process_utils.py +157 -133
  159. md_utils/sas_blob_utils.py +20 -20
  160. md_utils/split_locations_into_train_val.py +45 -32
  161. md_utils/string_utils.py +33 -10
  162. md_utils/url_utils.py +176 -60
  163. md_utils/write_html_image_list.py +40 -33
  164. md_visualization/__init__.py +0 -0
  165. md_visualization/plot_utils.py +102 -109
  166. md_visualization/render_images_with_thumbnails.py +34 -34
  167. md_visualization/visualization_utils.py +597 -291
  168. md_visualization/visualize_db.py +76 -48
  169. md_visualization/visualize_detector_output.py +61 -42
  170. {megadetector-5.0.8.dist-info → megadetector-5.0.10.dist-info}/METADATA +13 -7
  171. megadetector-5.0.10.dist-info/RECORD +224 -0
  172. {megadetector-5.0.8.dist-info → megadetector-5.0.10.dist-info}/top_level.txt +1 -0
  173. taxonomy_mapping/__init__.py +0 -0
  174. taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +342 -335
  175. taxonomy_mapping/map_new_lila_datasets.py +154 -154
  176. taxonomy_mapping/prepare_lila_taxonomy_release.py +142 -134
  177. taxonomy_mapping/preview_lila_taxonomy.py +591 -591
  178. taxonomy_mapping/retrieve_sample_image.py +12 -12
  179. taxonomy_mapping/simple_image_download.py +11 -11
  180. taxonomy_mapping/species_lookup.py +10 -10
  181. taxonomy_mapping/taxonomy_csv_checker.py +18 -18
  182. taxonomy_mapping/taxonomy_graph.py +47 -47
  183. taxonomy_mapping/validate_lila_category_mappings.py +83 -76
  184. data_management/cct_json_to_filename_json.py +0 -89
  185. data_management/cct_to_csv.py +0 -140
  186. data_management/databases/remove_corrupted_images_from_db.py +0 -191
  187. detection/detector_training/copy_checkpoints.py +0 -43
  188. megadetector-5.0.8.dist-info/RECORD +0 -205
  189. {megadetector-5.0.8.dist-info → megadetector-5.0.10.dist-info}/LICENSE +0 -0
  190. {megadetector-5.0.8.dist-info → megadetector-5.0.10.dist-info}/WHEEL +0 -0
@@ -1,56 +1,53 @@
1
- ########
2
- #
3
- # plot_utils.py
4
- #
5
- # Utility functions for plotting.
6
- #
7
- # NOTE: Do NOT import matplotlib.pyplot here to avoid the interactive backend.
8
- # Thus, the matplotlib.figure.Figure objects returned by the functions here do not
9
- # need to be "closed" with `plt.close(fig)`.
10
- #
11
- ########
1
+ """
12
2
 
13
- #%% Imports
3
+ plot_utils.py
4
+
5
+ Utility functions for plotting, particularly for plotting confusion matrices
6
+ and precision-recall curves.
14
7
 
15
- from typing import Any, Optional, Sequence, Tuple, Union
8
+ """
9
+
10
+ #%% Imports
16
11
 
17
12
  import numpy as np
18
- import matplotlib.figure # this also imports mpl.{cm, axes, colors}
13
+
14
+ # This also imports mpl.{cm, axes, colors}
15
+ import matplotlib.figure
19
16
 
20
17
 
21
18
  #%% Plotting functions
22
19
 
23
- def plot_confusion_matrix(
24
- matrix: np.ndarray,
25
- classes: Sequence[str],
26
- normalize: bool = False,
27
- title: str = 'Confusion matrix',
28
- cmap: Union[str, matplotlib.colors.Colormap] = matplotlib.cm.Blues,
29
- vmax: Optional[float] = None,
30
- use_colorbar: bool = True,
31
- y_label: bool = True,
32
- fmt: str = '{:.0f}',
33
- fig=None
34
- ) -> matplotlib.figure.Figure:
20
+ def plot_confusion_matrix(matrix,
21
+ classes,
22
+ normalize=False,
23
+ title='Confusion matrix',
24
+ cmap=matplotlib.cm.Blues,
25
+ vmax=None,
26
+ use_colorbar=True,
27
+ y_label=True,
28
+ fmt= '{:.0f}',
29
+ fig=None):
35
30
  """
36
- Plot a confusion matrix. By default, assumes values in the given matrix
37
- are percentages. If the matrix contains counts, normalization can be applied
38
- by setting `normalize=True`.
31
+ Plots a confusion matrix.
39
32
 
40
33
  Args:
41
- matrix: np.ndarray, shape [num_classes, num_classes], confusion matrix
42
- where rows are ground-truth classes and cols are predicted classes.
43
- classes: list of str, class names for each row/column
44
- normalize: bool, whether to perform row-wise normalization to sum 1
45
- title: str, figure title
46
- cmap: colormap, default: matplotlib.cm.Blues
47
- vmax: float, value corresponding s to the largest value of the colormap.
48
- If None, the maximum value in *matrix* will be used. Default: None
49
- use_colorbar: bool, whether to show colorbar
50
- y_label: bool, whether to show class names on the y-axis
51
- fmt: str, format string
52
-
53
- Returns: matplotlib.figure.Figure, a reference to the figure
34
+ matrix (np.ndarray): shape [num_classes, num_classes], confusion matrix
35
+ where rows are ground-truth classes and columns are predicted classes
36
+ classes (list of str): class names for each row/column
37
+ normalize (bool, optional): whether to perform row-wise normalization;
38
+ by default, assumes values in the confusion matrix are percentages
39
+ title (str, optional): figure title
40
+ cmap (matplotlib.colors.colormap): colormap for cell backgrounds
41
+ vmax (float, optional), value corresponding to the largest value of the colormap;
42
+ if None, the maximum value in [matrix] will be used
43
+ use_colorbar (bool, optional): whether to show colorbar
44
+ y_label (bool, optional): whether to show class names on the y axis
45
+ fmt (str): format string for rendering numeric values
46
+ fig (Figure): existing figure to which we should render, otherwise creates
47
+ a new figure
48
+
49
+ Returns:
50
+ matplotlib.figure.Figure: the figure we rendered to or created
54
51
  """
55
52
 
56
53
  num_classes = matrix.shape[0]
@@ -97,24 +94,29 @@ def plot_confusion_matrix(
97
94
 
98
95
  return fig
99
96
 
97
+ # ...def plot_confusion_matrix(...)
100
98
 
101
- def plot_precision_recall_curve(
102
- precisions: Sequence[float], recalls: Sequence[float],
103
- title: str = 'Precision/recall curve',
104
- xlim=(0.0,1.05),ylim=(0.0,1.05)
105
- ) -> matplotlib.figure.Figure:
99
+
100
+ def plot_precision_recall_curve(precisions,
101
+ recalls,
102
+ title='Precision/recall curve',
103
+ xlim=(0.0,1.05),
104
+ ylim=(0.0,1.05)):
106
105
  """
107
- Plots the precision recall curve given lists of (ordered) precision
106
+ Plots a precision/recall curve given lists of (ordered) precision
108
107
  and recall values.
109
108
 
110
109
  Args:
111
- precisions: list of float, precision for corresponding recall values,
112
- should have same length as *recalls*.
113
- recalls: list of float, recall for corresponding precision values,
114
- should have same length as *precisions*.
115
- title: str, plot title
116
-
117
- Returns: matplotlib.figure.Figure, reference to the figure
110
+ precisions (list of float): precision for corresponding recall values,
111
+ should have same length as [recalls].
112
+ recalls (list of float): recall for corresponding precision values,
113
+ should have same length as [precisions].
114
+ title (str, optional): plot title
115
+ xlim (tuple, optional): x-axis limits as a length-2 tuple
116
+ ylim (tuple, optional): y-axis limits as a length-2 tuple
117
+
118
+ Returns:
119
+ matplotlib.figure.Figure: the (new) figure
118
120
  """
119
121
 
120
122
  assert len(precisions) == len(recalls)
@@ -138,27 +140,24 @@ def plot_precision_recall_curve(
138
140
  return fig
139
141
 
140
142
 
141
- def plot_stacked_bar_chart(data: np.ndarray,
142
- series_labels: Sequence[str],
143
- col_labels: Optional[Sequence[str]] = None,
144
- x_label: Optional[str] = None,
145
- y_label: Optional[str] = None,
146
- log_scale: bool = False
147
- ) -> matplotlib.figure.Figure:
143
+ def plot_stacked_bar_chart(data, series_labels=None, col_labels=None,
144
+ x_label=None, y_label=None, log_scale=False):
148
145
  """
149
- For plotting e.g. species distribution across locations.
146
+ Plot a stacked bar chart, for plotting e.g. species distribution across locations.
147
+
150
148
  Reference: https://stackoverflow.com/q/44309507
151
149
 
152
150
  Args:
153
- data: 2-D np.ndarray or nested list, rows (series) are species, columns
151
+ data (np.ndarray or list of list): data to plot; rows (series) are species, columns
154
152
  are locations
155
- series_labels: list of str, e.g., species names
156
- col_labels: list of str, e.g., location names
157
- x_label: str
158
- y_label: str
159
- log_scale: bool, whether to plot y-axis in log-scale
160
-
161
- Returns: matplotlib.figure.Figure, reference to figure
153
+ series_labels (list of str, optional): series labels, typically species names
154
+ col_labels (list of str, optional): column labels, typically location names
155
+ x_label (str, optional): x-axis label
156
+ y_label (str, optional): y-axis label
157
+ log_scale (bool, optional) whether to plot the y axis in log-scale
158
+
159
+ Returns:
160
+ matplotlib.figure.Figure: the (new) figure
162
161
  """
163
162
 
164
163
  data = np.asarray(data)
@@ -200,28 +199,29 @@ def plot_stacked_bar_chart(data: np.ndarray,
200
199
  return fig
201
200
 
202
201
 
203
- def calibration_ece(true_scores: Sequence[int], pred_scores: Sequence[float],
204
- num_bins: int) -> Tuple[np.ndarray, np.ndarray, float]:
205
- """
202
+ def calibration_ece(true_scores, pred_scores, num_bins):
203
+ r"""
206
204
  Expected calibration error (ECE) as defined in equation (3) of
207
- Guo et al. "On Calibration of Modern Neural Networks." (2017).
205
+ Guo et al. "On Calibration of Modern Neural Networks." (2017).
208
206
 
209
207
  Implementation modified from sklearn.calibration.calibration_curve()
210
- in order to implement ECE calculation. See
211
- https://github.com/scikit-learn/scikit-learn/issues/18268
208
+ in order to implement ECE calculation. See:
209
+
210
+ https://github.com/scikit-learn/scikit-learn/issues/18268
212
211
 
213
212
  Args:
214
- pred_scores: list of float, length N, pred_scores[i] is the predicted
215
- confidence that example i is positive
216
- true_scores: list of int, length N, binary-valued (0 = neg, 1 = pos)
217
- num_bins: int, number of bins to use (`M` in eq. (3) of Guo 2017)
213
+ true_scores (list of int): true values, length N, binary-valued (0 = neg, 1 = pos)
214
+ pred_scores (list of float): predicted confidence values, length N, pred_scores[i] is the
215
+ predicted confidence that example i is positive
216
+ num_bins (int): number of bins to use (`M` in eq. (3) of Guo 2017)
218
217
 
219
218
  Returns:
220
- accs: np.ndarray, shape [M], type float64, accuracy in each bin,
221
- M <= num_bins because bins with no samples are not returned
222
- confs: np.ndarray, shape [M], type float64, mean model confidence in
223
- each bin
224
- ece: float, expected calibration error
219
+ tuple: a length-three tuple containing:
220
+ - accs: np.ndarray, shape [M], type float64, accuracy in each bin,
221
+ M <= num_bins because bins with no samples are not returned
222
+ - confs: np.ndarray, shape [M], type float64, mean model confidence in
223
+ each bin
224
+ - ece: float, expected calibration error
225
225
  """
226
226
 
227
227
  assert len(true_scores) == len(pred_scores)
@@ -242,32 +242,25 @@ def calibration_ece(true_scores: Sequence[int], pred_scores: Sequence[float],
242
242
  return accs, confs, ece
243
243
 
244
244
 
245
- def plot_calibration_curve(true_scores: Sequence[int],
246
- pred_scores: Sequence[float],
247
- num_bins: int,
248
- name: str = 'calibration',
249
- plot_perf: bool = True,
250
- plot_hist: bool = True,
251
- ax: Optional[matplotlib.axes.Axes] = None,
252
- **fig_kwargs: Any
253
- ) -> matplotlib.figure.Figure:
245
+ def plot_calibration_curve(true_scores, pred_scores, num_bins,
246
+ name='calibration', plot_perf=True, plot_hist=True,
247
+ ax=None, **fig_kwargs):
254
248
  """
255
- Plot a calibration curve.
256
-
257
- Consider rewriting / removing this function if
258
- https://github.com/scikit-learn/scikit-learn/pull/17443
259
- is merged into an actual scikit-learn release.
249
+ Plots a calibration curve.
260
250
 
261
251
  Args:
262
- see calibration_ece() for args
263
- name: str, label in legend for the calibration curve
264
- plot_perf: bool, whether to plot y=x line indicating perfect calibration
265
- plot_hist: bool, whether to plot histogram of counts
266
- ax: optional matplotlib Axes, if given then no legend is drawn, and
267
- fig_kwargs are ignored
268
- fig_kwargs: only used if ax is None
269
-
270
- Returns: matplotlib Figure
252
+ true_scores (list of int): true values, length N, binary-valued (0 = neg, 1 = pos)
253
+ pred_scores (list of float): predicted confidence values, length N, pred_scores[i] is the
254
+ predicted confidence that example i is positive
255
+ num_bins (int): number of bins to use (`M` in eq. (3) of Guo 2017)
256
+ name (str, optional): label in legend for the calibration curve
257
+ plot_perf (bool, optional): whether to plot y=x line indicating perfect calibration
258
+ plot_hist (bool, optional): whether to plot histogram of counts
259
+ ax (Axes, optional): if given then no legend is drawn, and fig_kwargs are ignored
260
+ fig_kwargs (dict, optional): only used if [ax] is None
261
+
262
+ Returns:
263
+ matplotlib.figure.Figure: the (new) figure
271
264
  """
272
265
 
273
266
  accs, confs, ece = calibration_ece(true_scores, pred_scores, num_bins)
@@ -1,21 +1,23 @@
1
- ########
2
- #
3
- # render_images_with_thumbnails.py
4
- #
5
- # Render an output image with one primary and crops from many secondary images,
6
- # used to check whether suspicious detections are actually false positives or not.
7
- #
8
- ########
1
+ """
9
2
 
10
- #%% Constants
3
+ render_images_with_thumbnails.py
4
+
5
+ Renders an output image with one primary image and crops from many secondary images,
6
+ used primarily to check whether candidate repeat detections are actually false positives or not.
7
+
8
+ """
9
+
10
+ #%% Imports
11
11
 
12
12
  import math
13
13
  import os
14
14
  import random
15
15
 
16
- from md_visualization import visualization_utils as vis_utils
17
16
  from PIL import Image
18
17
 
18
+ from md_visualization import visualization_utils as vis_utils
19
+ from md_utils import path_utils
20
+
19
21
 
20
22
  #%% Support functions
21
23
 
@@ -24,10 +26,13 @@ def crop_image_with_normalized_coordinates(
24
26
  bounding_box):
25
27
  """
26
28
  Args:
27
- image: image to crop
28
- bounding_box: tuple formatted as (x,y,w,h), where (0,0) is the
29
- upper-left of the image, and coordinates are normalized
30
- (so (0,0,1,1) is a box containing the entire image).
29
+ image (PIL.Image): image to crop
30
+ bounding_box (tuple): tuple formatted as (x,y,w,h), where (0,0) is the
31
+ upper-left of the image, and coordinates are normalized
32
+ (so (0,0,1,1) is a box containing the entire image).
33
+
34
+ Returns:
35
+ PIL.Image: cropped image
31
36
  """
32
37
 
33
38
  im_width, im_height = image.size
@@ -39,7 +44,6 @@ def crop_image_with_normalized_coordinates(
39
44
  return image.crop((x, y, x+w, y+h))
40
45
 
41
46
 
42
-
43
47
  #%% Main function
44
48
 
45
49
  def render_images_with_thumbnails(
@@ -64,20 +68,19 @@ def render_images_with_thumbnails(
64
68
  ratio of the primary image.
65
69
 
66
70
  Args:
67
- primary_image_filename: filename of the primary image to load as str
68
- primary_image_width: width at which to render the primary image; if this is
69
- None, will render at the original image width.
70
- secondary_image_filename_list: list of strs that are the filenames of
71
- the secondary images.
72
- secondary_image_bounding_box_list: list of tuples, one per secondary
71
+ primary_image_filename (str): filename of the primary image to load as str
72
+ primary_image_width (int): width at which to render the primary image; if this is
73
+ None, will render at the original image width
74
+ secondary_image_filename_list (list): list of filenames of the secondary images
75
+ secondary_image_bounding_box_list (list): list of tuples, one per secondary
73
76
  image. Each tuple is a bounding box of the secondary image,
74
77
  formatted as (x,y,w,h), where (0,0) is the upper-left of the image,
75
78
  and coordinates are normalized (so (0,0,1,1) is a box containing
76
79
  the entire image.
77
- cropped_grid_width: width of all the cropped images
78
- output_image_filename: str of the filename to write the output image
79
- primary_image_location: 'right' or left'; reserving 'top', 'bottom', etc.
80
- for future use.
80
+ cropped_grid_width (int): width of the cropped-image area
81
+ output_image_filename (str): filename to write the output image
82
+ primary_image_location (str, optional): 'right' or left'; reserving 'top', 'bottom', etc.
83
+ for future use
81
84
  """
82
85
 
83
86
  # Check to make sure the arguments are reasonable
@@ -183,6 +186,8 @@ def render_images_with_thumbnails(
183
186
  # Write output image to disk
184
187
  output_image.save(output_image_filename)
185
188
 
189
+ # ...def render_images_with_thumbnails(...)
190
+
186
191
 
187
192
  #%% Interactive driver
188
193
 
@@ -216,18 +221,15 @@ if False:
216
221
  output_image_filename,
217
222
  primary_image_location='right')
218
223
 
219
- from md_utils import path_utils
220
224
  path_utils.open_file(output_image_filename)
221
225
 
222
226
 
223
227
  #%% Command-line driver
224
228
 
229
+ # This is just a test driver, this module is not meant to be run from the command line.
230
+
225
231
  def main():
226
-
227
- #%%
228
-
229
- from md_utils import path_utils
230
-
232
+
231
233
  # Load images from a test directory.
232
234
  #
233
235
  # Make the first image in the directory the primary image,
@@ -268,8 +270,6 @@ def main():
268
270
 
269
271
  from md_utils import path_utils
270
272
  path_utils.open_file(output_image_filename)
271
-
272
- #%%
273
-
273
+
274
274
  if __name__ == '__main__':
275
275
  main()