coralnet-toolbox 0.0.73__py2.py3-none-any.whl → 0.0.75__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.
- coralnet_toolbox/Annotations/QtAnnotation.py +28 -69
- coralnet_toolbox/Annotations/QtMaskAnnotation.py +408 -0
- coralnet_toolbox/Annotations/QtMultiPolygonAnnotation.py +72 -56
- coralnet_toolbox/Annotations/QtPatchAnnotation.py +165 -216
- coralnet_toolbox/Annotations/QtPolygonAnnotation.py +497 -353
- coralnet_toolbox/Annotations/QtRectangleAnnotation.py +126 -116
- coralnet_toolbox/CoralNet/QtDownload.py +2 -1
- coralnet_toolbox/Explorer/QtDataItem.py +52 -22
- coralnet_toolbox/Explorer/QtExplorer.py +293 -1614
- coralnet_toolbox/Explorer/QtSettingsWidgets.py +203 -85
- coralnet_toolbox/Explorer/QtViewers.py +1568 -0
- coralnet_toolbox/Explorer/transformer_models.py +59 -0
- coralnet_toolbox/Explorer/yolo_models.py +112 -0
- coralnet_toolbox/IO/QtExportTagLabAnnotations.py +30 -10
- coralnet_toolbox/IO/QtImportTagLabAnnotations.py +21 -15
- coralnet_toolbox/IO/QtOpenProject.py +46 -78
- coralnet_toolbox/IO/QtSaveProject.py +18 -43
- coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py +1 -1
- coralnet_toolbox/MachineLearning/ImportDataset/QtBase.py +253 -141
- coralnet_toolbox/MachineLearning/VideoInference/QtBase.py +0 -4
- coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/run.py +102 -16
- coralnet_toolbox/QtAnnotationWindow.py +16 -10
- coralnet_toolbox/QtEventFilter.py +11 -0
- coralnet_toolbox/QtImageWindow.py +120 -75
- coralnet_toolbox/QtLabelWindow.py +13 -1
- coralnet_toolbox/QtMainWindow.py +5 -27
- coralnet_toolbox/QtProgressBar.py +52 -27
- coralnet_toolbox/Rasters/RasterTableModel.py +28 -8
- coralnet_toolbox/SAM/QtDeployGenerator.py +1 -4
- coralnet_toolbox/SAM/QtDeployPredictor.py +11 -3
- coralnet_toolbox/SeeAnything/QtDeployGenerator.py +805 -162
- coralnet_toolbox/SeeAnything/QtDeployPredictor.py +130 -151
- coralnet_toolbox/Tools/QtCutSubTool.py +18 -2
- coralnet_toolbox/Tools/QtPolygonTool.py +42 -3
- coralnet_toolbox/Tools/QtRectangleTool.py +30 -0
- coralnet_toolbox/Tools/QtResizeSubTool.py +19 -2
- coralnet_toolbox/Tools/QtSAMTool.py +72 -50
- coralnet_toolbox/Tools/QtSeeAnythingTool.py +8 -5
- coralnet_toolbox/Tools/QtSelectTool.py +27 -3
- coralnet_toolbox/Tools/QtSubtractSubTool.py +66 -0
- coralnet_toolbox/Tools/__init__.py +2 -0
- coralnet_toolbox/__init__.py +1 -1
- coralnet_toolbox/utilities.py +158 -47
- coralnet_toolbox-0.0.75.dist-info/METADATA +378 -0
- {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/RECORD +49 -44
- coralnet_toolbox-0.0.73.dist-info/METADATA +0 -341
- {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/WHEEL +0 -0
- {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/entry_points.txt +0 -0
- {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/licenses/LICENSE.txt +0 -0
- {coralnet_toolbox-0.0.73.dist-info → coralnet_toolbox-0.0.75.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,6 @@
|
|
1
1
|
import warnings
|
2
2
|
|
3
|
-
import
|
4
|
-
|
5
|
-
from PyQt5.QtCore import pyqtSignal
|
3
|
+
from PyQt5.QtCore import pyqtSignal, QPropertyAnimation, QEventLoop
|
6
4
|
from PyQt5.QtWidgets import QProgressBar, QVBoxLayout, QDialog, QPushButton, QApplication
|
7
5
|
|
8
6
|
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
@@ -112,16 +110,35 @@ class ProgressBar(QDialog):
|
|
112
110
|
def update_progress(self, new_title=None):
|
113
111
|
"""
|
114
112
|
Increment the progress by one step.
|
115
|
-
Updates the UI and checks if progress is complete.
|
113
|
+
Updates the UI intermittently to improve performance and checks if progress is complete.
|
116
114
|
"""
|
117
115
|
if new_title is not None:
|
118
116
|
self.setWindowTitle(new_title)
|
119
117
|
|
120
|
-
if
|
121
|
-
|
118
|
+
if self.canceled:
|
119
|
+
return
|
120
|
+
|
121
|
+
self.value += 1
|
122
|
+
|
123
|
+
# --- Performance Improvement ---
|
124
|
+
# To avoid excessive UI repaints that slow down the process, we only update
|
125
|
+
# the visual progress bar periodically. This aims for about 100 updates
|
126
|
+
# over the entire range, ensuring a smooth look without bogging down the main task.
|
127
|
+
# 'max(1, ...)' ensures we always have an interval of at least 1.
|
128
|
+
update_interval = max(1, self.max_value // 100)
|
129
|
+
|
130
|
+
# We update the bar visually only under two conditions:
|
131
|
+
# 1. It's the very last step, to ensure it always finishes at 100%.
|
132
|
+
# 2. The current value is a multiple of our calculated interval.
|
133
|
+
is_last_step = self.value >= self.max_value
|
134
|
+
is_update_step = self.value % update_interval == 0
|
135
|
+
|
136
|
+
if is_update_step or is_last_step:
|
122
137
|
self.progress_bar.setValue(self.value)
|
123
|
-
|
124
|
-
|
138
|
+
|
139
|
+
# This is crucial. It processes pending events, allowing the GUI to
|
140
|
+
# redraw with the new progress value and to respond to user input,
|
141
|
+
# like clicking the 'Cancel' button.
|
125
142
|
QApplication.processEvents()
|
126
143
|
|
127
144
|
def update_progress_percentage(self, percentage):
|
@@ -141,30 +158,38 @@ class ProgressBar(QDialog):
|
|
141
158
|
|
142
159
|
def finish_progress(self, duration_ms=500):
|
143
160
|
"""
|
144
|
-
Animate the progress bar to its maximum value
|
145
|
-
This creates a visual effect of
|
161
|
+
Animate the progress bar to its maximum value using a non-blocking animation.
|
162
|
+
This creates a smooth visual effect of completion without freezing the UI.
|
146
163
|
|
147
164
|
Args:
|
148
165
|
duration_ms: The duration in milliseconds for the animation (default: 500)
|
149
166
|
"""
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
steps_needed = self.max_value - start_value
|
154
|
-
if steps_needed <= 0:
|
155
|
-
self.progress_bar.setValue(self.max_value)
|
156
|
-
QApplication.processEvents()
|
167
|
+
# If the progress is already complete, just set the final value and exit.
|
168
|
+
if self.value >= self.max_value:
|
169
|
+
self.stop_progress()
|
157
170
|
return
|
158
|
-
|
159
|
-
#
|
160
|
-
|
161
|
-
|
162
|
-
#
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
171
|
+
|
172
|
+
# --- Non-Blocking Animation using QPropertyAnimation ---
|
173
|
+
# QPropertyAnimation is the standard Qt way to animate widget properties.
|
174
|
+
# It runs on the main event loop, so it does not freeze the application
|
175
|
+
# like the previous time.sleep() implementation. The property name "value"
|
176
|
+
# is passed as a bytes object (b"value").
|
177
|
+
self.animation = QPropertyAnimation(self.progress_bar, b"value")
|
178
|
+
self.animation.setDuration(duration_ms)
|
179
|
+
self.animation.setStartValue(self.value)
|
180
|
+
self.animation.setEndValue(self.max_value)
|
181
|
+
self.animation.start()
|
182
|
+
|
183
|
+
# We run a local event loop that waits for the animation's 'finished'
|
184
|
+
# signal. This ensures that the animation completes visually before
|
185
|
+
# this method returns control to the calling code, which is often
|
186
|
+
# the desired behavior for a "finishing" step.
|
187
|
+
loop = QEventLoop()
|
188
|
+
self.animation.finished.connect(loop.quit)
|
189
|
+
loop.exec_()
|
190
|
+
|
191
|
+
# Finally, update our internal state variable to match the final progress.
|
192
|
+
self.value = self.max_value
|
168
193
|
|
169
194
|
def stop_progress(self):
|
170
195
|
"""
|
@@ -20,8 +20,9 @@ class RasterTableModel(QAbstractTableModel):
|
|
20
20
|
Custom table model for displaying a list of Raster objects.
|
21
21
|
"""
|
22
22
|
# Column indices
|
23
|
-
|
24
|
-
|
23
|
+
CHECKBOX_COL = 0
|
24
|
+
FILENAME_COL = 1
|
25
|
+
ANNOTATION_COUNT_COL = 2
|
25
26
|
|
26
27
|
# Row colors
|
27
28
|
HIGHLIGHTED_COLOR = QColor(173, 216, 230) # Light blue
|
@@ -39,13 +40,10 @@ class RasterTableModel(QAbstractTableModel):
|
|
39
40
|
self.raster_manager = raster_manager
|
40
41
|
self.filtered_paths: List[str] = []
|
41
42
|
|
42
|
-
|
43
|
-
# self.highlighted_paths: Set[str] = set()
|
44
|
-
|
45
|
-
self.column_headers = ["Image Name", "Annotations"]
|
43
|
+
self.column_headers = ["\u2713", "Image Name", "Annotations"]
|
46
44
|
|
47
45
|
# Column widths
|
48
|
-
self.column_widths = [-1, 120] # -1 means stretch
|
46
|
+
self.column_widths = [30, -1, 120] # -1 means stretch
|
49
47
|
|
50
48
|
# Connect to manager signals
|
51
49
|
self.raster_manager.rasterAdded.connect(self.on_raster_added)
|
@@ -82,7 +80,9 @@ class RasterTableModel(QAbstractTableModel):
|
|
82
80
|
raster.set_display_name(max_length=25)
|
83
81
|
|
84
82
|
if role == Qt.DisplayRole:
|
85
|
-
if index.column() == self.
|
83
|
+
if index.column() == self.CHECKBOX_COL:
|
84
|
+
return "\u2713" if raster.checkbox_state else ""
|
85
|
+
elif index.column() == self.FILENAME_COL:
|
86
86
|
return raster.display_name
|
87
87
|
elif index.column() == self.ANNOTATION_COUNT_COL:
|
88
88
|
return str(raster.annotation_count)
|
@@ -149,6 +149,26 @@ class RasterTableModel(QAbstractTableModel):
|
|
149
149
|
return Qt.NoItemFlags
|
150
150
|
|
151
151
|
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
|
152
|
+
|
153
|
+
def add_path(self, path: str):
|
154
|
+
"""
|
155
|
+
Efficiently add a single path by signaling a row insertion.
|
156
|
+
|
157
|
+
Args:
|
158
|
+
path (str): The image path to add.
|
159
|
+
"""
|
160
|
+
if path in self.raster_manager.image_paths and path not in self.filtered_paths:
|
161
|
+
# The position for the new row is at the end of the current list
|
162
|
+
row_position = len(self.filtered_paths)
|
163
|
+
|
164
|
+
# Signal that we are about to insert one row at this position
|
165
|
+
self.beginInsertRows(QModelIndex(), row_position, row_position)
|
166
|
+
|
167
|
+
# Add the data
|
168
|
+
self.filtered_paths.append(path)
|
169
|
+
|
170
|
+
# Signal that the insertion is complete
|
171
|
+
self.endInsertRows()
|
152
172
|
|
153
173
|
def highlight_path(self, path: str, highlighted: bool = True):
|
154
174
|
"""
|
@@ -168,7 +168,7 @@ class DeployGeneratorDialog(QDialog):
|
|
168
168
|
|
169
169
|
# Image size control
|
170
170
|
self.imgsz_spinbox = QSpinBox()
|
171
|
-
self.imgsz_spinbox.setRange(
|
171
|
+
self.imgsz_spinbox.setRange(1024, 65536)
|
172
172
|
self.imgsz_spinbox.setSingleStep(1024)
|
173
173
|
self.imgsz_spinbox.setValue(self.imgsz)
|
174
174
|
layout.addRow("Image Size (imgsz):", self.imgsz_spinbox)
|
@@ -460,9 +460,6 @@ class DeployGeneratorDialog(QDialog):
|
|
460
460
|
progress_bar.stop_progress()
|
461
461
|
progress_bar.close()
|
462
462
|
|
463
|
-
# Exit the dialog box
|
464
|
-
self.accept()
|
465
|
-
|
466
463
|
def get_imgsz(self):
|
467
464
|
"""Get the image size for the model."""
|
468
465
|
self.imgsz = self.imgsz_spinbox.value()
|
@@ -142,6 +142,12 @@ class DeployPredictorDialog(QDialog):
|
|
142
142
|
"""
|
143
143
|
group_box = QGroupBox("Parameters")
|
144
144
|
layout = QFormLayout()
|
145
|
+
|
146
|
+
# Allow holes dropdown
|
147
|
+
self.allow_holes_dropdown = QComboBox()
|
148
|
+
self.allow_holes_dropdown.addItems(["True", "False"])
|
149
|
+
self.allow_holes_dropdown.setCurrentIndex(1) # Default to False
|
150
|
+
layout.addRow("Allow Holes:", self.allow_holes_dropdown)
|
145
151
|
|
146
152
|
# Resize image dropdown
|
147
153
|
self.resize_image_dropdown = QComboBox()
|
@@ -152,7 +158,7 @@ class DeployPredictorDialog(QDialog):
|
|
152
158
|
|
153
159
|
# Image size control
|
154
160
|
self.imgsz_spinbox = QSpinBox()
|
155
|
-
self.imgsz_spinbox.setRange(
|
161
|
+
self.imgsz_spinbox.setRange(1024, 65536)
|
156
162
|
self.imgsz_spinbox.setSingleStep(1024)
|
157
163
|
self.imgsz_spinbox.setValue(self.imgsz)
|
158
164
|
layout.addRow("Image Size (imgsz):", self.imgsz_spinbox)
|
@@ -236,6 +242,10 @@ class DeployPredictorDialog(QDialog):
|
|
236
242
|
group_box.setLayout(layout)
|
237
243
|
self.layout.addWidget(group_box)
|
238
244
|
|
245
|
+
def get_allow_holes(self):
|
246
|
+
"""Return the current setting for allowing holes."""
|
247
|
+
return self.allow_holes_dropdown.currentText() == "True"
|
248
|
+
|
239
249
|
def initialize_uncertainty_threshold(self):
|
240
250
|
"""Initialize the uncertainty threshold slider with the current value"""
|
241
251
|
current_value = self.main_window.get_uncertainty_thresh()
|
@@ -348,8 +358,6 @@ class DeployPredictorDialog(QDialog):
|
|
348
358
|
progress_bar.stop_progress()
|
349
359
|
progress_bar.close()
|
350
360
|
|
351
|
-
self.accept()
|
352
|
-
|
353
361
|
def resize_image(self, image):
|
354
362
|
"""
|
355
363
|
Resize the image to the specified size.
|