coralnet-toolbox 0.0.72__py2.py3-none-any.whl → 0.0.74__py2.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.
Files changed (57) hide show
  1. coralnet_toolbox/Annotations/QtAnnotation.py +28 -69
  2. coralnet_toolbox/Annotations/QtMaskAnnotation.py +408 -0
  3. coralnet_toolbox/Annotations/QtMultiPolygonAnnotation.py +72 -56
  4. coralnet_toolbox/Annotations/QtPatchAnnotation.py +165 -216
  5. coralnet_toolbox/Annotations/QtPolygonAnnotation.py +497 -353
  6. coralnet_toolbox/Annotations/QtRectangleAnnotation.py +126 -116
  7. coralnet_toolbox/AutoDistill/QtDeployModel.py +23 -12
  8. coralnet_toolbox/CoralNet/QtDownload.py +2 -1
  9. coralnet_toolbox/Explorer/QtDataItem.py +1 -1
  10. coralnet_toolbox/Explorer/QtExplorer.py +159 -17
  11. coralnet_toolbox/Explorer/QtSettingsWidgets.py +160 -86
  12. coralnet_toolbox/IO/QtExportTagLabAnnotations.py +30 -10
  13. coralnet_toolbox/IO/QtImportTagLabAnnotations.py +21 -15
  14. coralnet_toolbox/IO/QtOpenProject.py +46 -78
  15. coralnet_toolbox/IO/QtSaveProject.py +18 -43
  16. coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py +22 -11
  17. coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py +22 -10
  18. coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py +61 -24
  19. coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py +5 -1
  20. coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py +19 -6
  21. coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py +21 -8
  22. coralnet_toolbox/MachineLearning/ImportDataset/QtBase.py +42 -22
  23. coralnet_toolbox/MachineLearning/VideoInference/QtBase.py +0 -4
  24. coralnet_toolbox/QtAnnotationWindow.py +42 -14
  25. coralnet_toolbox/QtEventFilter.py +19 -2
  26. coralnet_toolbox/QtImageWindow.py +134 -86
  27. coralnet_toolbox/QtLabelWindow.py +14 -2
  28. coralnet_toolbox/QtMainWindow.py +122 -9
  29. coralnet_toolbox/QtProgressBar.py +52 -27
  30. coralnet_toolbox/Rasters/QtRaster.py +59 -7
  31. coralnet_toolbox/Rasters/RasterTableModel.py +42 -14
  32. coralnet_toolbox/SAM/QtBatchInference.py +0 -2
  33. coralnet_toolbox/SAM/QtDeployGenerator.py +22 -11
  34. coralnet_toolbox/SAM/QtDeployPredictor.py +10 -0
  35. coralnet_toolbox/SeeAnything/QtBatchInference.py +19 -221
  36. coralnet_toolbox/SeeAnything/QtDeployGenerator.py +1634 -0
  37. coralnet_toolbox/SeeAnything/QtDeployPredictor.py +107 -154
  38. coralnet_toolbox/SeeAnything/QtTrainModel.py +115 -45
  39. coralnet_toolbox/SeeAnything/__init__.py +2 -0
  40. coralnet_toolbox/Tools/QtCutSubTool.py +18 -2
  41. coralnet_toolbox/Tools/QtResizeSubTool.py +19 -2
  42. coralnet_toolbox/Tools/QtSAMTool.py +222 -57
  43. coralnet_toolbox/Tools/QtSeeAnythingTool.py +223 -55
  44. coralnet_toolbox/Tools/QtSelectSubTool.py +6 -4
  45. coralnet_toolbox/Tools/QtSelectTool.py +27 -3
  46. coralnet_toolbox/Tools/QtSubtractSubTool.py +66 -0
  47. coralnet_toolbox/Tools/QtWorkAreaTool.py +25 -13
  48. coralnet_toolbox/Tools/__init__.py +2 -0
  49. coralnet_toolbox/__init__.py +1 -1
  50. coralnet_toolbox/utilities.py +137 -47
  51. coralnet_toolbox-0.0.74.dist-info/METADATA +375 -0
  52. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.74.dist-info}/RECORD +56 -53
  53. coralnet_toolbox-0.0.72.dist-info/METADATA +0 -341
  54. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.74.dist-info}/WHEEL +0 -0
  55. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.74.dist-info}/entry_points.txt +0 -0
  56. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.74.dist-info}/licenses/LICENSE.txt +0 -0
  57. {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.74.dist-info}/top_level.txt +0 -0
@@ -40,23 +40,17 @@ class BatchInferenceDialog(QDialog):
40
40
 
41
41
  self.setWindowIcon(get_icon("eye.png"))
42
42
  self.setWindowTitle("Batch Inference")
43
- self.resize(600, 100)
43
+ self.resize(400, 100)
44
44
 
45
- self.deploy_model_dialog = None
45
+ self.deploy_generator_dialog = None
46
46
  self.loaded_model = None
47
47
 
48
- # Reference image and label
49
- self.source_image_path = None
50
- self.source_label = None
51
- # Target images
52
- self.target_images = []
48
+ self.image_paths = []
53
49
 
54
50
  self.layout = QVBoxLayout(self)
55
51
 
56
52
  # Setup the info layout
57
53
  self.setup_info_layout()
58
- # Setup the source layout
59
- self.setup_source_layout()
60
54
  # Setup the image options layout
61
55
  self.setup_options_layout()
62
56
  # Setup the buttons layout
@@ -69,11 +63,8 @@ class BatchInferenceDialog(QDialog):
69
63
  :param event: Show event
70
64
  """
71
65
  super().showEvent(event)
72
- self.deploy_model_dialog = self.main_window.see_anything_deploy_predictor_dialog
73
- self.loaded_model = self.deploy_model_dialog.loaded_model
74
-
75
- # Update the source images (now assuming sources are valid)
76
- self.update_source_images()
66
+ self.deploy_generator_dialog = self.main_window.see_anything_deploy_generator_dialog
67
+ self.loaded_model = self.deploy_generator_dialog.loaded_model
77
68
 
78
69
  def setup_info_layout(self):
79
70
  """
@@ -92,26 +83,6 @@ class BatchInferenceDialog(QDialog):
92
83
  group_box.setLayout(layout)
93
84
  self.layout.addWidget(group_box)
94
85
 
95
- def setup_source_layout(self):
96
- """
97
- Set up the layout with source image and label selection.
98
- Contains dropdown combo boxes for selecting the source image and label.
99
- """
100
- group_box = QGroupBox("Source Selection")
101
- layout = QFormLayout()
102
-
103
- # Create the source image combo box
104
- self.source_image_combo_box = QComboBox()
105
- self.source_image_combo_box.currentIndexChanged.connect(self.update_source_labels)
106
- layout.addRow("Source Image:", self.source_image_combo_box)
107
-
108
- # Create the source label combo box
109
- self.source_label_combo_box = QComboBox()
110
- layout.addRow("Source Label:", self.source_label_combo_box)
111
-
112
- group_box.setLayout(layout)
113
- self.layout.addWidget(group_box)
114
-
115
86
  def setup_options_layout(self):
116
87
  """
117
88
  Set up the layout with image options.
@@ -159,202 +130,37 @@ class BatchInferenceDialog(QDialog):
159
130
 
160
131
  self.layout.addWidget(button_box)
161
132
 
162
- def has_valid_sources(self):
163
- """
164
- Check if there are any valid source images with polygon or rectangle annotations.
165
-
166
- :return: True if valid sources exist, False otherwise
167
- """
168
- # Check if there are any images
169
- if not self.image_window.raster_manager.image_paths:
170
- QMessageBox.information(None,
171
- "No Images",
172
- "No images available for batch inference.")
173
- return False
174
-
175
- # Check for images with valid annotations
176
- for image_path in self.image_window.raster_manager.image_paths:
177
- # Get annotations for this image
178
- annotations = self.annotation_window.get_image_annotations(image_path)
179
-
180
- # Check if there's at least one valid polygon/rectangle annotation
181
- for annotation in annotations:
182
- if isinstance(annotation, PolygonAnnotation) or isinstance(annotation, RectangleAnnotation):
183
- return True
184
-
185
- QMessageBox.information(None,
186
- "No Valid Annotations",
187
- "No images have polygon or rectangle annotations for batch inference.")
188
- return False
189
-
190
- def check_valid_sources(self):
191
- """
192
- Check if there are any valid source images with polygon or rectangle annotations.
193
-
194
- :return: True if valid sources exist, False otherwise
195
- """
196
- # Check if there are any images
197
- if not self.image_window.raster_manager.image_paths:
198
- QMessageBox.information(self,
199
- "No Images",
200
- "No images available for batch inference.")
201
- return False
202
-
203
- # Check for images with valid annotations
204
- for image_path in self.image_window.raster_manager.image_paths:
205
- # Get annotations for this image
206
- annotations = self.annotation_window.get_image_annotations(image_path)
207
-
208
- # Check if there's at least one valid polygon/rectangle annotation
209
- for annotation in annotations:
210
- if isinstance(annotation, PolygonAnnotation) or isinstance(annotation, RectangleAnnotation):
211
- return True
212
-
213
- QMessageBox.information(self,
214
- "No Valid Annotations",
215
- "No images have polygon or rectangle annotations for batch inference.")
216
- return False
217
-
218
- def update_source_images(self):
219
- """
220
- Updates the source image combo box with images that have at least one label
221
- with a valid polygon or rectangle annotation.
222
-
223
- :return: True if valid source images were found, False otherwise
224
- """
225
- self.source_image_combo_box.clear()
226
- valid_images_found = False
227
-
228
- # Get all image paths from the raster_manager
229
- for image_path in self.image_window.raster_manager.image_paths:
230
- # Get annotations for this image
231
- annotations = self.annotation_window.get_image_annotations(image_path)
232
-
233
- # Check if there's at least one valid polygon/rectangle annotation
234
- valid_annotation_found = False
235
- for annotation in annotations:
236
- if isinstance(annotation, PolygonAnnotation) or isinstance(annotation, RectangleAnnotation):
237
- valid_annotation_found = True
238
- break
239
-
240
- if valid_annotation_found:
241
- # Get the basename (filename)
242
- basename = os.path.basename(image_path)
243
- # Add item to combo box with full path as data
244
- self.source_image_combo_box.addItem(basename, image_path)
245
- valid_images_found = True
246
-
247
- if not valid_images_found:
248
- QMessageBox.information(self,
249
- "No Source Images",
250
- "No images available for batch inference.")
251
- # Close the dialog since batch inference can't proceed
252
- QApplication.processEvents() # Process pending events
253
- self.reject()
254
- return False
255
-
256
- # Update the combo box to have the selected image first
257
- if self.annotation_window.current_image_path in self.image_window.raster_manager.image_paths:
258
- self.source_image_combo_box.setCurrentText(os.path.basename(self.annotation_window.current_image_path))
259
-
260
- # Update the source labels given changes in the source images
261
- return self.update_source_labels()
262
-
263
- def update_source_labels(self):
264
- """
265
- Updates the source label combo box with labels that have at least one
266
- polygon or rectangle annotation from the current image.
267
-
268
- :return: True if valid source labels were found, False otherwise
269
- """
270
- self.source_label_combo_box.clear()
271
-
272
- source_image_path = self.source_image_combo_box.currentData()
273
- if not source_image_path:
274
- return False
275
-
276
- # Get annotations for this image
277
- annotations = self.annotation_window.get_image_annotations(source_image_path)
278
-
279
- # Create a dict of labels with valid annotations
280
- valid_labels = {}
281
- for annotation in annotations:
282
- if isinstance(annotation, PolygonAnnotation) or isinstance(annotation, RectangleAnnotation):
283
- valid_labels[annotation.label.short_label_code] = annotation.label
284
-
285
- # Add valid labels to combo box
286
- for label_code, label_obj in valid_labels.items():
287
- self.source_label_combo_box.addItem(label_code, label_obj)
288
-
289
- if not valid_labels:
290
- QMessageBox.information(self,
291
- "No Valid Labels",
292
- "No labels with polygon or rectangle annotations available for batch inference.")
293
- # Close the dialog since batch inference can't proceed
294
- QApplication.processEvents() # Process pending events
295
- self.reject()
296
- return False
297
-
298
- return True
299
-
300
- def get_source_annotations(self):
301
- """Return a list of polygon and rectangle annotations for the
302
- source image belonging to the selected label."""
303
- source_image_path = self.source_image_combo_box.currentData()
304
- source_label = self.source_label_combo_box.currentData()
305
-
306
- # Get annotations for this image
307
- annotations = self.annotation_window.get_image_annotations(source_image_path)
308
-
309
- # Filter annotations by label
310
- source_annotations = []
311
- for annotation in annotations:
312
- if annotation.label.short_label_code == source_label.short_label_code:
313
- source_annotations.append(annotation.cropped_bbox)
314
-
315
- return np.array(source_annotations)
316
-
317
133
  def get_selected_image_paths(self):
318
134
  """
319
135
  Get the selected image paths based on the options.
320
- Excludes the source image path if present.
321
-
136
+
322
137
  :return: List of selected image paths
323
138
  """
324
- # Get the source image path to exclude
325
- source_image_path = self.source_image_combo_box.currentData()
326
-
327
139
  # Current image path showing
328
140
  current_image_path = self.annotation_window.current_image_path
329
141
  if not current_image_path:
330
142
  return []
331
-
143
+
332
144
  # Determine which images to export annotations for
333
145
  if self.apply_filtered_checkbox.isChecked():
334
- selected_paths = self.image_window.table_model.filtered_paths.copy()
146
+ return self.image_window.table_model.filtered_paths
335
147
  elif self.apply_prev_checkbox.isChecked():
336
148
  if current_image_path in self.image_window.table_model.filtered_paths:
337
149
  current_index = self.image_window.table_model.get_row_for_path(current_image_path)
338
- selected_paths = self.image_window.table_model.filtered_paths[:current_index + 1].copy()
150
+ return self.image_window.table_model.filtered_paths[:current_index + 1]
339
151
  else:
340
- selected_paths = [current_image_path]
152
+ return [current_image_path]
341
153
  elif self.apply_next_checkbox.isChecked():
342
154
  if current_image_path in self.image_window.table_model.filtered_paths:
343
155
  current_index = self.image_window.table_model.get_row_for_path(current_image_path)
344
- selected_paths = self.image_window.table_model.filtered_paths[current_index:].copy()
156
+ return self.image_window.table_model.filtered_paths[current_index:]
345
157
  else:
346
- selected_paths = [current_image_path]
158
+ return [current_image_path]
347
159
  elif self.apply_all_checkbox.isChecked():
348
- selected_paths = self.image_window.raster_manager.image_paths.copy()
160
+ return self.image_window.raster_manager.image_paths
349
161
  else:
350
162
  # Only apply to the current image
351
- selected_paths = [current_image_path]
352
-
353
- # Remove the source image path if it's in the selected paths
354
- if source_image_path and source_image_path in selected_paths:
355
- selected_paths.remove(source_image_path)
356
-
357
- return selected_paths
163
+ return [current_image_path]
358
164
 
359
165
  def apply(self):
360
166
  """
@@ -364,14 +170,8 @@ class BatchInferenceDialog(QDialog):
364
170
  QApplication.setOverrideCursor(Qt.WaitCursor)
365
171
 
366
172
  try:
367
- # Get the source image path and label
368
- self.source_image_path = self.source_image_combo_box.currentData()
369
- self.source_label = self.source_label_combo_box.currentData()
370
- # Get the source annotations
371
- self.source_annotations = self.get_source_annotations()
372
173
  # Get the selected image paths
373
- self.target_images = self.get_selected_image_paths()
374
- # Perform batch inference
174
+ self.image_paths = self.get_selected_image_paths()
375
175
  self.batch_inference()
376
176
 
377
177
  except Exception as e:
@@ -385,17 +185,15 @@ class BatchInferenceDialog(QDialog):
385
185
  def batch_inference(self):
386
186
  """
387
187
  Perform batch inference on the selected images.
388
-
389
188
  """
390
189
  # Make predictions on each image's annotations
391
190
  progress_bar = ProgressBar(self, title="Batch Inference")
392
191
  progress_bar.show()
393
- progress_bar.start_progress(len(self.target_images))
192
+ progress_bar.start_progress(len(self.image_paths))
394
193
 
395
194
  if self.loaded_model is not None:
396
- self.deploy_model_dialog.predict_from_annotations(refer_image=self.source_image_path,
397
- refer_label=self.source_label,
398
- refer_annotations=self.source_annotations,
399
- target_images=self.target_images)
195
+ self.deploy_generator_dialog.predict(image_paths=self.image_paths)
196
+
400
197
  progress_bar.stop_progress()
401
198
  progress_bar.close()
199
+