coralnet-toolbox 0.0.72__py2.py3-none-any.whl → 0.0.73__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/AutoDistill/QtDeployModel.py +23 -12
- coralnet_toolbox/Explorer/QtDataItem.py +1 -1
- coralnet_toolbox/Explorer/QtExplorer.py +143 -3
- coralnet_toolbox/Explorer/QtSettingsWidgets.py +46 -4
- coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py +22 -11
- coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py +22 -10
- coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py +61 -24
- coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py +5 -1
- coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py +19 -6
- coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py +21 -8
- coralnet_toolbox/QtAnnotationWindow.py +42 -14
- coralnet_toolbox/QtEventFilter.py +8 -2
- coralnet_toolbox/QtImageWindow.py +17 -18
- coralnet_toolbox/QtLabelWindow.py +1 -1
- coralnet_toolbox/QtMainWindow.py +143 -8
- coralnet_toolbox/Rasters/QtRaster.py +59 -7
- coralnet_toolbox/Rasters/RasterTableModel.py +34 -6
- coralnet_toolbox/SAM/QtBatchInference.py +0 -2
- coralnet_toolbox/SAM/QtDeployGenerator.py +22 -11
- coralnet_toolbox/SeeAnything/QtBatchInference.py +19 -221
- coralnet_toolbox/SeeAnything/QtDeployGenerator.py +1016 -0
- coralnet_toolbox/SeeAnything/QtDeployPredictor.py +69 -53
- coralnet_toolbox/SeeAnything/QtTrainModel.py +115 -45
- coralnet_toolbox/SeeAnything/__init__.py +2 -0
- coralnet_toolbox/Tools/QtSAMTool.py +150 -7
- coralnet_toolbox/Tools/QtSeeAnythingTool.py +220 -55
- coralnet_toolbox/Tools/QtSelectSubTool.py +6 -4
- coralnet_toolbox/Tools/QtWorkAreaTool.py +25 -13
- coralnet_toolbox/__init__.py +1 -1
- {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/METADATA +1 -1
- {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/RECORD +35 -34
- {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/WHEEL +0 -0
- {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/entry_points.txt +0 -0
- {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/licenses/LICENSE.txt +0 -0
- {coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/top_level.txt +0 -0
@@ -71,9 +71,17 @@ class SeeAnythingTool(Tool):
|
|
71
71
|
self.current_rect_graphics = None # For the rectangle currently being drawn
|
72
72
|
self.rectangles_processed = False # Track if rectangles have been processed
|
73
73
|
|
74
|
+
# Add state variables for custom working area creation
|
75
|
+
self.creating_working_area = False
|
76
|
+
self.working_area_start = None
|
77
|
+
self.working_area_temp_graphics = None
|
78
|
+
|
79
|
+
# Add hover position tracking
|
80
|
+
self.hover_pos = None
|
81
|
+
|
74
82
|
self.annotations = []
|
75
83
|
self.results = None
|
76
|
-
|
84
|
+
|
77
85
|
def activate(self):
|
78
86
|
"""
|
79
87
|
Activates the tool.
|
@@ -98,6 +106,9 @@ class SeeAnythingTool(Tool):
|
|
98
106
|
|
99
107
|
# Clean up working area and shadow
|
100
108
|
self.cancel_working_area()
|
109
|
+
|
110
|
+
# Cancel working area creation if in progress
|
111
|
+
self.cancel_working_area_creation()
|
101
112
|
|
102
113
|
# Clear detection data
|
103
114
|
self.results = None
|
@@ -165,6 +176,117 @@ class SeeAnythingTool(Tool):
|
|
165
176
|
|
166
177
|
self.annotation_window.setCursor(Qt.CrossCursor)
|
167
178
|
self.annotation_window.scene.update()
|
179
|
+
|
180
|
+
def set_custom_working_area(self, start_point, end_point):
|
181
|
+
"""
|
182
|
+
Create a working area from custom points selected by the user.
|
183
|
+
|
184
|
+
Args:
|
185
|
+
start_point (QPointF): First corner of the working area
|
186
|
+
end_point (QPointF): Opposite corner of the working area
|
187
|
+
"""
|
188
|
+
self.annotation_window.setCursor(Qt.WaitCursor)
|
189
|
+
|
190
|
+
# Cancel any existing working area
|
191
|
+
self.cancel_working_area()
|
192
|
+
|
193
|
+
# Calculate the rectangle bounds
|
194
|
+
left = max(0, int(min(start_point.x(), end_point.x())))
|
195
|
+
top = max(0, int(min(start_point.y(), end_point.y())))
|
196
|
+
right = min(int(self.annotation_window.pixmap_image.size().width()),
|
197
|
+
int(max(start_point.x(), end_point.x())))
|
198
|
+
bottom = min(int(self.annotation_window.pixmap_image.size().height()),
|
199
|
+
int(max(start_point.y(), end_point.y())))
|
200
|
+
|
201
|
+
# Ensure minimum size (at least 10x10 pixels)
|
202
|
+
if right - left < 10:
|
203
|
+
right = min(left + 10, int(self.annotation_window.pixmap_image.size().width()))
|
204
|
+
if bottom - top < 10:
|
205
|
+
bottom = min(top + 10, int(self.annotation_window.pixmap_image.size().height()))
|
206
|
+
|
207
|
+
# Original image information
|
208
|
+
self.image_path = self.annotation_window.current_image_path
|
209
|
+
self.original_image = pixmap_to_numpy(self.annotation_window.pixmap_image)
|
210
|
+
self.original_width = self.annotation_window.pixmap_image.size().width()
|
211
|
+
self.original_height = self.annotation_window.pixmap_image.size().height()
|
212
|
+
|
213
|
+
# Create the WorkArea instance
|
214
|
+
self.working_area = WorkArea(left, top, right - left, bottom - top, self.image_path)
|
215
|
+
|
216
|
+
# Get the thickness for the working area graphics
|
217
|
+
pen_width = self.graphics_utility.get_workarea_thickness(self.annotation_window)
|
218
|
+
|
219
|
+
# Create and add the working area graphics
|
220
|
+
self.working_area.create_graphics(self.annotation_window.scene, pen_width)
|
221
|
+
self.working_area.set_remove_button_visibility(False)
|
222
|
+
self.working_area.removed.connect(self.on_working_area_removed)
|
223
|
+
|
224
|
+
# Create shadow overlay
|
225
|
+
shadow_brush = QBrush(QColor(0, 0, 0, 150))
|
226
|
+
shadow_path = QPainterPath()
|
227
|
+
shadow_path.addRect(self.annotation_window.scene.sceneRect())
|
228
|
+
shadow_path.addRect(self.working_area.rect)
|
229
|
+
shadow_path = shadow_path.simplified()
|
230
|
+
|
231
|
+
self.shadow_area = QGraphicsPathItem(shadow_path)
|
232
|
+
self.shadow_area.setBrush(shadow_brush)
|
233
|
+
self.shadow_area.setPen(QPen(Qt.NoPen))
|
234
|
+
self.annotation_window.scene.addItem(self.shadow_area)
|
235
|
+
|
236
|
+
# Crop the image based on the working area
|
237
|
+
self.work_area_image = self.original_image[top:bottom, left:right]
|
238
|
+
|
239
|
+
# Set the image in the SeeAnything dialog
|
240
|
+
self.see_anything_dialog.set_image(self.work_area_image, self.image_path)
|
241
|
+
|
242
|
+
self.annotation_window.setCursor(Qt.CrossCursor)
|
243
|
+
self.annotation_window.scene.update()
|
244
|
+
|
245
|
+
def display_working_area_preview(self, current_pos):
|
246
|
+
"""
|
247
|
+
Display a preview rectangle for the working area being created.
|
248
|
+
|
249
|
+
Args:
|
250
|
+
current_pos (QPointF): Current mouse position
|
251
|
+
"""
|
252
|
+
if not self.working_area_start:
|
253
|
+
return
|
254
|
+
|
255
|
+
# Remove previous preview if it exists
|
256
|
+
if self.working_area_temp_graphics:
|
257
|
+
self.annotation_window.scene.removeItem(self.working_area_temp_graphics)
|
258
|
+
self.working_area_temp_graphics = None
|
259
|
+
|
260
|
+
# Create preview rectangle
|
261
|
+
rect = QRectF(
|
262
|
+
min(self.working_area_start.x(), current_pos.x()),
|
263
|
+
min(self.working_area_start.y(), current_pos.y()),
|
264
|
+
abs(current_pos.x() - self.working_area_start.x()),
|
265
|
+
abs(current_pos.y() - self.working_area_start.y())
|
266
|
+
)
|
267
|
+
|
268
|
+
# Create a dashed blue pen for the working area preview
|
269
|
+
pen = QPen(QColor(0, 120, 215))
|
270
|
+
pen.setStyle(Qt.DashLine)
|
271
|
+
pen.setWidth(2)
|
272
|
+
|
273
|
+
self.working_area_temp_graphics = QGraphicsRectItem(rect)
|
274
|
+
self.working_area_temp_graphics.setPen(pen)
|
275
|
+
self.working_area_temp_graphics.setBrush(QBrush(QColor(0, 120, 215, 30))) # Light blue transparent fill
|
276
|
+
self.annotation_window.scene.addItem(self.working_area_temp_graphics)
|
277
|
+
|
278
|
+
def cancel_working_area_creation(self):
|
279
|
+
"""
|
280
|
+
Cancel the process of creating a working area.
|
281
|
+
"""
|
282
|
+
self.creating_working_area = False
|
283
|
+
self.working_area_start = None
|
284
|
+
|
285
|
+
if self.working_area_temp_graphics:
|
286
|
+
self.annotation_window.scene.removeItem(self.working_area_temp_graphics)
|
287
|
+
self.working_area_temp_graphics = None
|
288
|
+
|
289
|
+
self.annotation_window.scene.update()
|
168
290
|
|
169
291
|
def on_working_area_removed(self, work_area):
|
170
292
|
"""
|
@@ -277,12 +399,25 @@ class SeeAnythingTool(Tool):
|
|
277
399
|
"A label must be selected before adding an annotation.")
|
278
400
|
return None
|
279
401
|
|
402
|
+
# Get position in scene coordinates
|
403
|
+
scene_pos = self.annotation_window.mapToScene(event.pos())
|
404
|
+
|
405
|
+
# Handle working area creation mode
|
406
|
+
if not self.working_area and event.button() == Qt.LeftButton:
|
407
|
+
if not self.creating_working_area:
|
408
|
+
# Start working area creation
|
409
|
+
self.creating_working_area = True
|
410
|
+
self.working_area_start = scene_pos
|
411
|
+
return
|
412
|
+
elif self.creating_working_area and self.working_area_start:
|
413
|
+
# Finish working area creation
|
414
|
+
self.set_custom_working_area(self.working_area_start, scene_pos)
|
415
|
+
self.cancel_working_area_creation()
|
416
|
+
return
|
417
|
+
|
280
418
|
if not self.working_area:
|
281
419
|
return
|
282
420
|
|
283
|
-
# Position in the scene
|
284
|
-
scene_pos = self.annotation_window.mapToScene(event.pos())
|
285
|
-
|
286
421
|
# Check if the position is within the working area
|
287
422
|
if not self.working_area.contains_point(scene_pos):
|
288
423
|
return
|
@@ -319,6 +454,14 @@ class SeeAnythingTool(Tool):
|
|
319
454
|
Args:
|
320
455
|
event (QMouseEvent): The mouse move event.
|
321
456
|
"""
|
457
|
+
scene_pos = self.annotation_window.mapToScene(event.pos())
|
458
|
+
self.hover_pos = scene_pos
|
459
|
+
|
460
|
+
# Update working area preview during creation
|
461
|
+
if self.creating_working_area and self.working_area_start:
|
462
|
+
self.display_working_area_preview(scene_pos)
|
463
|
+
return
|
464
|
+
|
322
465
|
if self.working_area and self.drawing_rectangle:
|
323
466
|
# Update the end point while drawing the rectangle
|
324
467
|
self.end_point = self.annotation_window.mapToScene(event.pos())
|
@@ -334,6 +477,12 @@ class SeeAnythingTool(Tool):
|
|
334
477
|
event (QKeyEvent): The key press event
|
335
478
|
"""
|
336
479
|
if event.key() == Qt.Key_Space:
|
480
|
+
# If creating working area, confirm it
|
481
|
+
if self.creating_working_area and self.working_area_start and self.hover_pos:
|
482
|
+
self.set_custom_working_area(self.working_area_start, self.hover_pos)
|
483
|
+
self.cancel_working_area_creation()
|
484
|
+
return
|
485
|
+
|
337
486
|
# If there is no working area, set it
|
338
487
|
if not self.working_area:
|
339
488
|
self.set_working_area()
|
@@ -359,6 +508,11 @@ class SeeAnythingTool(Tool):
|
|
359
508
|
self.cancel_working_area()
|
360
509
|
|
361
510
|
elif event.key() == Qt.Key_Backspace:
|
511
|
+
# If creating working area, cancel it
|
512
|
+
if self.creating_working_area:
|
513
|
+
self.cancel_working_area_creation()
|
514
|
+
return
|
515
|
+
|
362
516
|
# Cancel current rectangle being drawn
|
363
517
|
if self.drawing_rectangle:
|
364
518
|
self.drawing_rectangle = False
|
@@ -398,8 +552,16 @@ class SeeAnythingTool(Tool):
|
|
398
552
|
# Move the points back to the original image space
|
399
553
|
working_area_top_left = self.working_area.rect.topLeft()
|
400
554
|
|
401
|
-
|
402
|
-
|
555
|
+
task = self.see_anything_dialog.task_dropdown.currentText()
|
556
|
+
masks = None
|
557
|
+
if task == 'segment':
|
558
|
+
masks = []
|
559
|
+
for r in self.rectangles:
|
560
|
+
x1, y1, x2, y2 = r
|
561
|
+
masks.append(np.array([[x1, y1], [x2, y1], [x2, y2], [x1, y2]]))
|
562
|
+
|
563
|
+
# Predict from prompts, providing masks if the task is segmentation
|
564
|
+
results = self.see_anything_dialog.predict_from_prompts(self.rectangles, masks=masks)[0]
|
403
565
|
|
404
566
|
if not results:
|
405
567
|
# Make cursor normal
|
@@ -425,54 +587,58 @@ class SeeAnythingTool(Tool):
|
|
425
587
|
# Clear previous annotations if any
|
426
588
|
self.clear_annotations()
|
427
589
|
|
428
|
-
#
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
if
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
590
|
+
# Process results based on the task type
|
591
|
+
if self.see_anything_dialog.task == "segment":
|
592
|
+
if self.results.masks:
|
593
|
+
for i, polygon in enumerate(self.results.masks.xyn):
|
594
|
+
confidence = self.results.boxes.conf[i].item()
|
595
|
+
if confidence < self.main_window.get_uncertainty_thresh():
|
596
|
+
continue
|
597
|
+
|
598
|
+
# Get absolute bounding box for area check (relative to work area)
|
599
|
+
box_work_area = self.results.boxes.xyxy[i].detach().cpu().numpy()
|
600
|
+
box_area = (box_work_area[2] - box_work_area[0]) * (box_work_area[3] - box_work_area[1])
|
601
|
+
|
602
|
+
# Area filtering
|
603
|
+
min_area = self.main_window.get_area_thresh_min() * image_area
|
604
|
+
max_area = self.main_window.get_area_thresh_max() * image_area
|
605
|
+
if not (min_area <= box_area <= max_area):
|
606
|
+
continue
|
607
|
+
|
608
|
+
# Convert normalized polygon points to absolute coordinates in the whole image
|
609
|
+
polygon_abs = polygon.copy()
|
610
|
+
polygon_abs[:, 0] = polygon_abs[:, 0] * self.work_area_image.shape[1] + working_area_top_left.x()
|
611
|
+
polygon_abs[:, 1] = polygon_abs[:, 1] * self.work_area_image.shape[0] + working_area_top_left.y()
|
612
|
+
|
613
|
+
polygon_abs = simplify_polygon(polygon_abs, 0.1)
|
614
|
+
self.create_polygon_annotation(polygon_abs, confidence)
|
615
|
+
|
616
|
+
else: # Task is 'detect'
|
617
|
+
if self.results.boxes:
|
618
|
+
for i, box_norm in enumerate(self.results.boxes.xyxyn):
|
619
|
+
confidence = self.results.boxes.conf[i].item()
|
620
|
+
if confidence < self.main_window.get_uncertainty_thresh():
|
621
|
+
continue
|
622
|
+
|
623
|
+
# Convert normalized box to absolute coordinates in the work area
|
624
|
+
box_abs_work_area = box_norm.detach().cpu().numpy() * np.array(
|
625
|
+
[self.work_area_image.shape[1], self.work_area_image.shape[0],
|
626
|
+
self.work_area_image.shape[1], self.work_area_image.shape[0]])
|
627
|
+
box_area = (box_abs_work_area[2] - box_abs_work_area[0]) * (box_abs_work_area[3] - box_abs_work_area[1])
|
628
|
+
|
629
|
+
# Area filtering
|
630
|
+
min_area = self.main_window.get_area_thresh_min() * image_area
|
631
|
+
max_area = self.main_window.get_area_thresh_max() * image_area
|
632
|
+
if not (min_area <= box_area <= max_area):
|
633
|
+
continue
|
634
|
+
|
635
|
+
# Add working area offset to get coordinates in the whole image
|
636
|
+
box_abs_full = box_abs_work_area.copy()
|
637
|
+
box_abs_full[0] += working_area_top_left.x()
|
638
|
+
box_abs_full[1] += working_area_top_left.y()
|
639
|
+
box_abs_full[2] += working_area_top_left.x()
|
640
|
+
box_abs_full[3] += working_area_top_left.y()
|
641
|
+
self.create_rectangle_annotation(box_abs_full, confidence)
|
476
642
|
|
477
643
|
self.annotation_window.scene.update()
|
478
644
|
|
@@ -750,4 +916,3 @@ class SeeAnythingTool(Tool):
|
|
750
916
|
|
751
917
|
# Force update to ensure graphics are removed visually
|
752
918
|
self.annotation_window.scene.update()
|
753
|
-
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from PyQt5.QtCore import Qt, QRectF
|
2
|
-
from PyQt5.QtGui import QPen, QColor
|
2
|
+
from PyQt5.QtGui import QPen, QColor, QBrush
|
3
3
|
from PyQt5.QtWidgets import QGraphicsRectItem
|
4
4
|
|
5
5
|
from coralnet_toolbox.Tools.QtSubTool import SubTool
|
@@ -22,15 +22,17 @@ class SelectSubTool(SubTool):
|
|
22
22
|
super().activate(event)
|
23
23
|
self.selection_start_pos = self.annotation_window.mapToScene(event.pos())
|
24
24
|
|
25
|
-
# Create and style the selection rectangle
|
25
|
+
# Create and style the selection rectangle (dashed blue, light blue fill)
|
26
26
|
self.selection_rectangle = QGraphicsRectItem()
|
27
27
|
width = self.parent_tool.graphics_utility.get_rectangle_graphic_thickness(self.annotation_window)
|
28
|
-
pen = QPen(QColor(
|
28
|
+
pen = QPen(QColor(0, 120, 215))
|
29
|
+
pen.setStyle(Qt.DashLine)
|
29
30
|
pen.setWidth(width)
|
30
31
|
self.selection_rectangle.setPen(pen)
|
32
|
+
self.selection_rectangle.setBrush(QBrush(QColor(0, 120, 215, 30))) # Light blue transparent fill
|
31
33
|
self.selection_rectangle.setRect(QRectF(self.selection_start_pos, self.selection_start_pos))
|
32
34
|
self.annotation_window.scene.addItem(self.selection_rectangle)
|
33
|
-
|
35
|
+
|
34
36
|
def deactivate(self):
|
35
37
|
super().deactivate()
|
36
38
|
if self.selection_rectangle:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import warnings
|
2
2
|
|
3
|
-
from PyQt5.QtCore import Qt,
|
4
|
-
from PyQt5.QtGui import QMouseEvent, QPen, QColor
|
3
|
+
from PyQt5.QtCore import Qt, QRectF
|
4
|
+
from PyQt5.QtGui import QMouseEvent, QPen, QColor, QBrush
|
5
5
|
from PyQt5.QtWidgets import (QGraphicsRectItem, QMessageBox, QGraphicsPixmapItem)
|
6
6
|
|
7
7
|
from coralnet_toolbox.Tools.QtTool import Tool
|
@@ -30,8 +30,8 @@ class WorkAreaTool(Tool):
|
|
30
30
|
self.current_rect = None
|
31
31
|
self.work_areas = [] # List to store WorkArea objects for the current image
|
32
32
|
|
33
|
-
# Style settings for drawing the work area rectangle
|
34
|
-
self.work_area_pen = QPen(QColor(
|
33
|
+
# Style settings for drawing the work area rectangle - update to use blue dashed line
|
34
|
+
self.work_area_pen = QPen(QColor(0, 120, 215), 2, Qt.DashLine)
|
35
35
|
|
36
36
|
# Track if Ctrl key is pressed
|
37
37
|
self.ctrl_pressed = False
|
@@ -43,6 +43,9 @@ class WorkAreaTool(Tool):
|
|
43
43
|
# Track current image path to detect image changes
|
44
44
|
self.current_image_path = None
|
45
45
|
|
46
|
+
# Add hover position tracking for preview
|
47
|
+
self.hover_pos = None
|
48
|
+
|
46
49
|
def activate(self):
|
47
50
|
"""Activate the work area tool and set the appropriate cursor."""
|
48
51
|
self.active = True
|
@@ -100,10 +103,12 @@ class WorkAreaTool(Tool):
|
|
100
103
|
|
101
104
|
def mouseMoveEvent(self, event: QMouseEvent):
|
102
105
|
"""Handle mouse move events to update the work area while drawing."""
|
106
|
+
scene_pos = self.annotation_window.mapToScene(event.pos())
|
107
|
+
self.hover_pos = scene_pos # Track hover position for spacebar confirmation
|
108
|
+
|
103
109
|
if not self.drawing or not self.annotation_window.active_image:
|
104
110
|
return
|
105
111
|
|
106
|
-
scene_pos = self.annotation_window.mapToScene(event.pos())
|
107
112
|
self.update_drawing(scene_pos)
|
108
113
|
|
109
114
|
def mouseReleaseEvent(self, event: QMouseEvent):
|
@@ -116,6 +121,11 @@ class WorkAreaTool(Tool):
|
|
116
121
|
modifiers = event.modifiers()
|
117
122
|
key = event.key()
|
118
123
|
|
124
|
+
# Confirm current drawing with spacebar
|
125
|
+
if key == Qt.Key_Space and self.drawing and self.hover_pos:
|
126
|
+
self.finish_drawing(self.hover_pos)
|
127
|
+
return
|
128
|
+
|
119
129
|
# Ctrl+Alt for temporary work area
|
120
130
|
if (modifiers & Qt.ControlModifier) and (modifiers & Qt.AltModifier):
|
121
131
|
if not self.temporary_work_area:
|
@@ -139,12 +149,12 @@ class WorkAreaTool(Tool):
|
|
139
149
|
return
|
140
150
|
|
141
151
|
# Ctrl+Space to create a work area from current view
|
142
|
-
if key == Qt.Key_Space and self.annotation_window.active_image:
|
152
|
+
if key == Qt.Key_Space and self.annotation_window.active_image and not self.drawing:
|
143
153
|
self.create_work_area_from_current_view()
|
144
154
|
return
|
145
155
|
|
146
|
-
# Cancel current drawing (Backspace - without modifiers)
|
147
|
-
if key == Qt.Key_Backspace and self.drawing and not (modifiers & Qt.ControlModifier):
|
156
|
+
# Cancel current drawing (Backspace or Escape - without modifiers)
|
157
|
+
if (key == Qt.Key_Backspace or key == Qt.Key_Escape) and self.drawing and not (modifiers & Qt.ControlModifier):
|
148
158
|
self.cancel_drawing()
|
149
159
|
return
|
150
160
|
|
@@ -207,12 +217,13 @@ class WorkAreaTool(Tool):
|
|
207
217
|
# Create an initial rectangle item for visual feedback
|
208
218
|
self.current_rect = QGraphicsRectItem(QRectF(pos.x(), pos.y(), 0, 0))
|
209
219
|
|
210
|
-
#
|
211
|
-
|
220
|
+
# Create a dashed blue pen for the working area preview
|
221
|
+
pen = QPen(QColor(0, 120, 215))
|
222
|
+
pen.setStyle(Qt.DashLine)
|
223
|
+
pen.setWidth(2)
|
212
224
|
|
213
|
-
|
214
|
-
self.
|
215
|
-
self.current_rect.setPen(self.work_area_pen)
|
225
|
+
self.current_rect.setPen(pen)
|
226
|
+
self.current_rect.setBrush(QBrush(QColor(0, 120, 215, 30))) # Light blue transparent fill
|
216
227
|
self.annotation_window.scene.addItem(self.current_rect)
|
217
228
|
|
218
229
|
def update_drawing(self, pos):
|
@@ -227,6 +238,7 @@ class WorkAreaTool(Tool):
|
|
227
238
|
constrained_rect = self.constrain_rect_to_image_bounds(rect)
|
228
239
|
|
229
240
|
self.current_rect.setRect(constrained_rect)
|
241
|
+
self.hover_pos = pos # Update hover position for key events
|
230
242
|
|
231
243
|
def finish_drawing(self, pos):
|
232
244
|
"""Finish drawing the work area and add it to the list."""
|
coralnet_toolbox/__init__.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
coralnet_toolbox/QtAnnotationWindow.py,sha256=
|
1
|
+
coralnet_toolbox/QtAnnotationWindow.py,sha256=WOfi4BhXt3rtH0PnJZ0tDPpjn-wq66n8MoMqKFg-T2M,40727
|
2
2
|
coralnet_toolbox/QtConfidenceWindow.py,sha256=L5hR23uW91GpqnsNS9R1XF3zCTe2aU7w0iDoQMV0oyE,16190
|
3
|
-
coralnet_toolbox/QtEventFilter.py,sha256=
|
4
|
-
coralnet_toolbox/QtImageWindow.py,sha256=
|
5
|
-
coralnet_toolbox/QtLabelWindow.py,sha256
|
6
|
-
coralnet_toolbox/QtMainWindow.py,sha256=
|
3
|
+
coralnet_toolbox/QtEventFilter.py,sha256=KOW8_AdXZJIVsnl7992sacIcexc0QUFlLQ864YIg4e8,7045
|
4
|
+
coralnet_toolbox/QtImageWindow.py,sha256=2xQpdrTQE8PfzflOupEi3u65nLAikeMMH3MUkzTQHU4,49296
|
5
|
+
coralnet_toolbox/QtLabelWindow.py,sha256=XHRSi_Pp6AFnaaEtf3GNzliNxoO_jmSmEVBqP5lqRsw,50884
|
6
|
+
coralnet_toolbox/QtMainWindow.py,sha256=6JxsDeWpPAe3BhIHGwtsfxQegaXhl3NnO4Nws6od92w,123287
|
7
7
|
coralnet_toolbox/QtPatchSampling.py,sha256=Ehj06auBGfQwIruLNYQjF8eFOCpl8G72p42UXXb2mUo,29013
|
8
8
|
coralnet_toolbox/QtProgressBar.py,sha256=pnozUOcVjfO_yTS9z8wOMPcrrrOtG_FeCknTcdI6eyk,6250
|
9
9
|
coralnet_toolbox/QtWorkArea.py,sha256=YXRvHQKpWUtWyv_o9lZ8rmxfm28dUOG9pmMUeimDhQ4,13578
|
10
|
-
coralnet_toolbox/__init__.py,sha256
|
10
|
+
coralnet_toolbox/__init__.py,sha256=W4260-tQetcUaQbpJgZ4EkAlh_TbssOeuntEq4jmtSQ,207
|
11
11
|
coralnet_toolbox/main.py,sha256=6j2B_1reC_KDmqvq1C0fB-UeSEm8eeJOozp2f4XXMLQ,1573
|
12
12
|
coralnet_toolbox/utilities.py,sha256=eUkxXuWaNFH83LSW-KniwujkXKJ2rK04czx3k3OPiAY,27115
|
13
13
|
coralnet_toolbox/Annotations/QtAnnotation.py,sha256=-3ASbjl1dXw9U731vyCgwyiyZT9zOD5Mvp1jt-7bCnA,29242
|
@@ -17,7 +17,7 @@ coralnet_toolbox/Annotations/QtPolygonAnnotation.py,sha256=1EkZEJlO4VZ4so01Sat2T
|
|
17
17
|
coralnet_toolbox/Annotations/QtRectangleAnnotation.py,sha256=TgeawekA3jNBlCmZBRqXYRHoZqch7pWM-NSBBPG6S60,21404
|
18
18
|
coralnet_toolbox/Annotations/__init__.py,sha256=bpMldC70tT_lzMrOdBNDkEhG9dCX3tXEBd48IrcUg3E,419
|
19
19
|
coralnet_toolbox/AutoDistill/QtBatchInference.py,sha256=k871aW3XRX8kc4BDaS1aipbPh9WOZxgmilF2c4KOdVA,5646
|
20
|
-
coralnet_toolbox/AutoDistill/QtDeployModel.py,sha256=
|
20
|
+
coralnet_toolbox/AutoDistill/QtDeployModel.py,sha256=Fycm7wuydUfr1E2CUy00ridiI2JaNDZqAeoVB_HVydY,25923
|
21
21
|
coralnet_toolbox/AutoDistill/__init__.py,sha256=-cJSCr3HSVcybbkvdSZY_zz9EDLESq9A3gisHu3gIgM,206
|
22
22
|
coralnet_toolbox/AutoDistill/Models/GroundingDINO.py,sha256=xG20nLOrKjtzRhZznIIdwFXxBJ7RCeQ7h1z0V0J6trE,2781
|
23
23
|
coralnet_toolbox/AutoDistill/Models/OWLViT.py,sha256=disVxSQ80sS4SVYdwrQocFP_LN6YDQQhzfeORWe4veU,2572
|
@@ -35,10 +35,10 @@ coralnet_toolbox/Common/QtUpdateImagePaths.py,sha256=_hJYx6hXdAOfH_m77f75AQduQ0W
|
|
35
35
|
coralnet_toolbox/CoralNet/QtAuthenticate.py,sha256=Y__iY0Kcosz6AOV7dlJBwiB6Hte40wHahHe-OmRngZA,13267
|
36
36
|
coralnet_toolbox/CoralNet/QtDownload.py,sha256=HBb8TpZRIEFirGIaIAV1v8qg3fL4cP6Bf-hUiqXoiLE,48516
|
37
37
|
coralnet_toolbox/CoralNet/__init__.py,sha256=ILkAZh6mlAK1UaCCZjCB9JZxd-oY4cIgfnIC8UgjjIU,188
|
38
|
-
coralnet_toolbox/Explorer/QtDataItem.py,sha256=
|
39
|
-
coralnet_toolbox/Explorer/QtExplorer.py,sha256=
|
38
|
+
coralnet_toolbox/Explorer/QtDataItem.py,sha256=mRcQ0GlriEjhbFV_khbuFNMEJhIyFxD_uIC5v1L03cw,14885
|
39
|
+
coralnet_toolbox/Explorer/QtExplorer.py,sha256=jKybLHk7sD5C2TIzB5OLeSAkhSNKpGOOkvoNvz9M7NY,138362
|
40
40
|
coralnet_toolbox/Explorer/QtFeatureStore.py,sha256=3VwGezs1stmu65Z4ZQpvY27rGEIJq_prERWkFwMATBo,7378
|
41
|
-
coralnet_toolbox/Explorer/QtSettingsWidgets.py,sha256=
|
41
|
+
coralnet_toolbox/Explorer/QtSettingsWidgets.py,sha256=ltdimQHY1igAOh7OP4gFVuM4SyPJKmA-77wiKYBZo5k,29230
|
42
42
|
coralnet_toolbox/Explorer/__init__.py,sha256=wZPhf2oaUUyIQ2WK48Aj-4q1ENIZG2dGl1HF_mjhI6w,116
|
43
43
|
coralnet_toolbox/IO/QtExportAnnotations.py,sha256=xeaS0BukC3cpkBIGT9DXRqHmvHhp-vOU47h6EoANpNg,4474
|
44
44
|
coralnet_toolbox/IO/QtExportCoralNetAnnotations.py,sha256=4royhF63EmeOlSIBX389EUjjvE-SF44_maW6qm52mdA,2778
|
@@ -126,18 +126,18 @@ coralnet_toolbox/MachineLearning/Community/cfg/segment/yolo11-p2.yaml,sha256=H2P
|
|
126
126
|
coralnet_toolbox/MachineLearning/Community/cfg/segment/yolo11-p6.yaml,sha256=jg2PDDeIPvBG_QXNOMyro7LYLy0HNZ5F4s7fiAg0xys,3283
|
127
127
|
coralnet_toolbox/MachineLearning/DeployModel/QtBase.py,sha256=ZK2p9euv9AM2hhpAYWyVLcIk_8UwMVgeTAEYQbXWJBw,12609
|
128
128
|
coralnet_toolbox/MachineLearning/DeployModel/QtClassify.py,sha256=4YSEENGY2pZpiFqt1tfr-m1oHhP9V4uID8gdOVkZwwI,6331
|
129
|
-
coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py,sha256=
|
130
|
-
coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py,sha256=
|
129
|
+
coralnet_toolbox/MachineLearning/DeployModel/QtDetect.py,sha256=Ccocp-ZAZHnqCxsUYeqBcWgTR0LePKquGC83h8FEUSA,15691
|
130
|
+
coralnet_toolbox/MachineLearning/DeployModel/QtSegment.py,sha256=uwgqvtcCRUSPiafc6_uNw-LDYioYWJwC95joRYl2Ems,15452
|
131
131
|
coralnet_toolbox/MachineLearning/DeployModel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
132
132
|
coralnet_toolbox/MachineLearning/EvaluateModel/QtBase.py,sha256=stOQlB9NP1kZLwfQipA8J8_EzcgKi-9rvxar_AyWwjc,11526
|
133
133
|
coralnet_toolbox/MachineLearning/EvaluateModel/QtClassify.py,sha256=EsUBbSxcoOymO3ezPUI1X0M_g9x7Y2oVU5myflet7pw,2268
|
134
134
|
coralnet_toolbox/MachineLearning/EvaluateModel/QtDetect.py,sha256=i9Xy6564ChWKvHga-VOmzKtbXybt8eq9E8pGgGU69qY,2253
|
135
135
|
coralnet_toolbox/MachineLearning/EvaluateModel/QtSegment.py,sha256=4SYBwo8B83XgYeS29PFB95Lz5xANuBpu-4dWN17jeQA,2250
|
136
136
|
coralnet_toolbox/MachineLearning/EvaluateModel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
|
-
coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py,sha256
|
138
|
-
coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py,sha256=
|
139
|
-
coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py,sha256=
|
140
|
-
coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py,sha256=
|
137
|
+
coralnet_toolbox/MachineLearning/ExportDataset/QtBase.py,sha256=sS5FRSDYzBJOKHcOss3P_gGBKI4ufUDjararVuzhRhQ,29654
|
138
|
+
coralnet_toolbox/MachineLearning/ExportDataset/QtClassify.py,sha256=5LB8m2zJ24hjcvOL3uorGdqoZf2bpPxqB18THQlkh4Q,9669
|
139
|
+
coralnet_toolbox/MachineLearning/ExportDataset/QtDetect.py,sha256=ptZ0rUoZ1Tc0RGjKuXU15ZTM87m3gO8vLu6I7w5PVgs,6669
|
140
|
+
coralnet_toolbox/MachineLearning/ExportDataset/QtSegment.py,sha256=7sDczfciPPbGgMdb6D9pZn27DHs_Spg1bd-bc9_hI7Y,6696
|
141
141
|
coralnet_toolbox/MachineLearning/ExportDataset/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
142
142
|
coralnet_toolbox/MachineLearning/ImportDataset/QtBase.py,sha256=xRYutV3GUHqMLFaw79_x_7ED6el8mzohwDd3L7_h2ao,23950
|
143
143
|
coralnet_toolbox/MachineLearning/ImportDataset/QtDetect.py,sha256=1YQFAgfuPUUZ18fXbvs4GP9Mrp_-9kfeDdmJHEA5e7I,1121
|
@@ -174,9 +174,9 @@ coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/detection_model.py,sha256
|
|
174
174
|
coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/load_camera_params.py,sha256=0eduzfUuT_C852D9LWykMN1tGf962lk6Q2qjiJyxcQA,4430
|
175
175
|
coralnet_toolbox/MachineLearning/VideoInference/YOLO3D/run.py,sha256=Aumo6RkwJ1wzAloCuhNjgyFnb4z5YeRlME8N_6IdfCU,23463
|
176
176
|
coralnet_toolbox/Rasters/ImageFilter.py,sha256=EhH1YoVjC29ER4qU4t9xwybeX9E012fLq04iPFfbaz4,7928
|
177
|
-
coralnet_toolbox/Rasters/QtRaster.py,sha256=
|
177
|
+
coralnet_toolbox/Rasters/QtRaster.py,sha256=qWqhKiZbBnv0JnCQvPXx6fQYENgSA7sp3vBUj4fdnhA,18435
|
178
178
|
coralnet_toolbox/Rasters/RasterManager.py,sha256=GuTeuty3x4k8DWZ34FQ4BTNwRfjWu0lEhv3NfF2t5u4,6534
|
179
|
-
coralnet_toolbox/Rasters/RasterTableModel.py,sha256=
|
179
|
+
coralnet_toolbox/Rasters/RasterTableModel.py,sha256=91ZVBbHdrer6EznmtT9fVRsof0nlfmATtLIaTB-DKgA,14531
|
180
180
|
coralnet_toolbox/Rasters/__init__.py,sha256=Pi88uDQbtWxwHfJFdlsvbkwGNhtlyM_013l8bbJlFfw,428
|
181
181
|
coralnet_toolbox/Results/CombineResults.py,sha256=QrHyKhMrjNDtQ98PQabUflHhyv_8KXTGqU30tw9amV8,4523
|
182
182
|
coralnet_toolbox/Results/ConvertResults.py,sha256=uh7tfJxDiH_cJHxWsr8KQQOcsfzC59-k6PQDVtl3ZaY,6015
|
@@ -184,14 +184,15 @@ coralnet_toolbox/Results/MapResults.py,sha256=sDieekB93RVKvD-9mW1zRsHOs85shYVIQk
|
|
184
184
|
coralnet_toolbox/Results/Masks.py,sha256=C-zoobRaWXP_QdGcL7ZgSxytHOBdHIBUbQuGnoMZthE,5183
|
185
185
|
coralnet_toolbox/Results/ResultsProcessor.py,sha256=q_UZNYggpZyY4_P6RpDLbY1ygNH49GXlP1s9ZFI3yF0,17261
|
186
186
|
coralnet_toolbox/Results/__init__.py,sha256=WPdlq8aXzjrdQo5T3UqFh7jxge33iNEHiSRAmm0eJuw,630
|
187
|
-
coralnet_toolbox/SAM/QtBatchInference.py,sha256=
|
188
|
-
coralnet_toolbox/SAM/QtDeployGenerator.py,sha256=
|
187
|
+
coralnet_toolbox/SAM/QtBatchInference.py,sha256=UyuYLfPF4JrOmmuMOzshbKDEEribV669d9LURmuu6gg,6866
|
188
|
+
coralnet_toolbox/SAM/QtDeployGenerator.py,sha256=1zzzLuN6Dqe0tVoc3KosaFfYh39HeJ1OCOH0GvqRZDg,26550
|
189
189
|
coralnet_toolbox/SAM/QtDeployPredictor.py,sha256=D1DyqjLXQDTNiLp9OVgsiI97fMFftab_goEkQvDH1DU,23516
|
190
190
|
coralnet_toolbox/SAM/__init__.py,sha256=Zxd75pFMrt5DfSmNNVSsQeCucIQ2rVaEiS0hT_OVIMM,293
|
191
|
-
coralnet_toolbox/SeeAnything/QtBatchInference.py,sha256=
|
192
|
-
coralnet_toolbox/SeeAnything/
|
193
|
-
coralnet_toolbox/SeeAnything/
|
194
|
-
coralnet_toolbox/SeeAnything/
|
191
|
+
coralnet_toolbox/SeeAnything/QtBatchInference.py,sha256=k3aftVzva84yATB4Su5DSI0lhkHDggUg3mVAx4AHmjw,7134
|
192
|
+
coralnet_toolbox/SeeAnything/QtDeployGenerator.py,sha256=uuJNf_qNXfJ2C5qBYEliOE1z6ZnXCGnVnxmXxUSgeCs,42537
|
193
|
+
coralnet_toolbox/SeeAnything/QtDeployPredictor.py,sha256=3lKgtm3Wv0ygFFpiyjhAD8tlxji6P8lNtBN_pJ02zV0,26875
|
194
|
+
coralnet_toolbox/SeeAnything/QtTrainModel.py,sha256=dQ6ZkeIr1migU-edGO-gQMENVP4o7WJsIANlSVhFK8k,28031
|
195
|
+
coralnet_toolbox/SeeAnything/__init__.py,sha256=4OgG9-aQ6_RZ942-Ift_q-kkp14kObMT4lDIIx9YSxQ,366
|
195
196
|
coralnet_toolbox/Tile/QtTileBatchInference.py,sha256=chSo-TOwpnAgIQpTetZnbhWQIBzbDJO01xAQ3z0-ubk,10730
|
196
197
|
coralnet_toolbox/Tile/QtTileCreation.py,sha256=Cw6q0ZVXx0hU4uMuXA3OZ3_5bKu6oQgnlMFwaXSZbS0,39963
|
197
198
|
coralnet_toolbox/Tile/__init__.py,sha256=BlV-1bO9u-olfNAIvukUMPRzlw8dx-ayjrjMRQ-bSsk,463
|
@@ -207,18 +208,18 @@ coralnet_toolbox/Tools/QtPatchTool.py,sha256=57vFeR2jQ_VQRlMEIC_mH8NigUqOlVvmhaV
|
|
207
208
|
coralnet_toolbox/Tools/QtPolygonTool.py,sha256=yxnkwK3rb52pWCq7a3iAABhHUSS_a3vkL7G7Ev0uLDA,9174
|
208
209
|
coralnet_toolbox/Tools/QtRectangleTool.py,sha256=gYOOsn1WRHLG0YzkKmmM7OzLpuLNh8GWIZ4MloXoLDc,7218
|
209
210
|
coralnet_toolbox/Tools/QtResizeSubTool.py,sha256=derPy4adRj758-xYtjL-_35yGBOjoSe_DRE48HpdQpA,5836
|
210
|
-
coralnet_toolbox/Tools/QtSAMTool.py,sha256=
|
211
|
-
coralnet_toolbox/Tools/QtSeeAnythingTool.py,sha256=
|
212
|
-
coralnet_toolbox/Tools/QtSelectSubTool.py,sha256=
|
211
|
+
coralnet_toolbox/Tools/QtSAMTool.py,sha256=8jrHAhumOctmKRpJuw7v54Y6wemXnenRGw-5-F8-Kqg,32571
|
212
|
+
coralnet_toolbox/Tools/QtSeeAnythingTool.py,sha256=tIX_D7nOa6wPZeSBQq-qHE2DNKFl5H47wl4H2fHoI5s,38256
|
213
|
+
coralnet_toolbox/Tools/QtSelectSubTool.py,sha256=_FIjLhnEVY19Q87jhRKXGdghNfMBxxy_sECAIUo0BZA,3294
|
213
214
|
coralnet_toolbox/Tools/QtSelectTool.py,sha256=rSzM9s7pMxrLqvcWgIcEnpEQhYHU6TbGUna8ZaamakA,19957
|
214
215
|
coralnet_toolbox/Tools/QtSubTool.py,sha256=H25FoFqywdi6Bl35MfpEXGrr48ZTgdRRvHMxUy1tqN4,1601
|
215
216
|
coralnet_toolbox/Tools/QtTool.py,sha256=2MCjT151gYBN8KbsK0GX4WOrEg1uw3oeSkp7Elw1AUA,2531
|
216
|
-
coralnet_toolbox/Tools/QtWorkAreaTool.py,sha256
|
217
|
+
coralnet_toolbox/Tools/QtWorkAreaTool.py,sha256=ApsIiEbkyWFWKW6qnFPPnL_Wgs2xa_Edif5kZU5_n8M,22733
|
217
218
|
coralnet_toolbox/Tools/QtZoomTool.py,sha256=F9CAoABv1jxcUS7dyIh1FYjgjOXYRI1xtBPNIR1g62o,4041
|
218
219
|
coralnet_toolbox/Tools/__init__.py,sha256=218iQ8IFXIkKXiUDVYtXk9e08UY9-LhHjcryaJAanQ0,797
|
219
|
-
coralnet_toolbox-0.0.
|
220
|
-
coralnet_toolbox-0.0.
|
221
|
-
coralnet_toolbox-0.0.
|
222
|
-
coralnet_toolbox-0.0.
|
223
|
-
coralnet_toolbox-0.0.
|
224
|
-
coralnet_toolbox-0.0.
|
220
|
+
coralnet_toolbox-0.0.73.dist-info/licenses/LICENSE.txt,sha256=AURacZ_G_PZKqqPQ9VB9Sqegblk67RNgWSGAYKwXXMY,521
|
221
|
+
coralnet_toolbox-0.0.73.dist-info/METADATA,sha256=X8IhSWb4kRb_cuC9AxyVn7XsOnZXgHB5kRkv2ca91V4,18152
|
222
|
+
coralnet_toolbox-0.0.73.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
|
223
|
+
coralnet_toolbox-0.0.73.dist-info/entry_points.txt,sha256=oEeMoDlJ_2lq95quOeDHIx9hZpubUlSo80OLtgbcrbM,63
|
224
|
+
coralnet_toolbox-0.0.73.dist-info/top_level.txt,sha256=SMWPh4_9JfB8zVpPOOvjucV2_B_hvWW7bNWmMjG0LsY,17
|
225
|
+
coralnet_toolbox-0.0.73.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{coralnet_toolbox-0.0.72.dist-info → coralnet_toolbox-0.0.73.dist-info}/licenses/LICENSE.txt
RENAMED
File without changes
|
File without changes
|