Skip to content

Commit 896f0d1

Browse files
committed
deselect with brush (currently only works for brush selected points, should work for all)
1 parent 182c4cc commit 896f0d1

File tree

1 file changed

+47
-5
lines changed

1 file changed

+47
-5
lines changed

pyidi/selection/main_window.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def __init__(self, video):
5252
self._paint_mask = None # Same shape as the image
5353
self._paint_radius = 10 # pixels
5454
self.ctrl_held = False
55+
self.brush_deselect_mode = False
5556
self.installEventFilter(self)
5657

5758
self.selected_points = []
@@ -312,6 +313,13 @@ def update_label_and_recompute(val):
312313
self.start_new_line_button.setVisible(False) # Hidden by default
313314
self.manual_layout.addWidget(self.start_new_line_button)
314315

316+
# Brush mode
317+
self.brush_deselect_button = QtWidgets.QPushButton("Deselect painted area")
318+
self.brush_deselect_button.setCheckable(True)
319+
self.brush_deselect_button.setVisible(False) # shown only for Brush mode
320+
self.brush_deselect_button.clicked.connect(self.activate_brush_deselect)
321+
self.manual_layout.addWidget(self.brush_deselect_button)
322+
315323
self.manual_layout.addStretch(1)
316324

317325
# Polygon manager (visible only for "Along the line")
@@ -440,6 +448,8 @@ def method_selected(self, id: int):
440448
self.distance_label.setVisible(show_spacing)
441449
self.distance_slider.setVisible(show_spacing)
442450

451+
self.brush_deselect_button.setVisible(is_brush)
452+
443453
def switch_mode(self, mode: str):
444454
self.mode = mode
445455
if mode == "manual":
@@ -885,7 +895,6 @@ def clear_candidates(self):
885895

886896
# Brush
887897
def handle_brush_start(self, ev):
888-
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.CursorShape.CrossCursor)
889898
if self.image_item.image is None:
890899
return
891900
h, w = self.image_item.image.shape[:2]
@@ -912,21 +921,49 @@ def handle_brush_move(self, ev):
912921
self.update_brush_overlay()
913922

914923
def handle_brush_end(self, ev):
915-
QtWidgets.QApplication.restoreOverrideCursor()
916-
917924
if self._paint_mask is None:
918925
return
919926

920927
subset_size = self.subset_size_spinbox.value()
921928
spacing = self.distance_slider.value()
929+
930+
# Generate (row, col) points inside the painted mask
922931
brush_rois = rois_inside_mask(self._paint_mask, subset_size, spacing)
923-
self.manual_points.extend(brush_rois)
932+
933+
# Convert to set of tuples for fast comparison
934+
roi_set = set((int(round(y)), int(round(x))) for y, x in brush_rois)
935+
936+
if self.brush_deselect_mode:
937+
# Remove from manual points
938+
self.manual_points = [
939+
pt for pt in self.manual_points
940+
if (int(round(pt[0])), int(round(pt[1]))) not in roi_set
941+
]
942+
943+
# Remove from polygon ROI points
944+
for poly in self.drawing_polygons:
945+
poly['roi_points'] = [
946+
pt for pt in poly['roi_points']
947+
if (int(round(pt[0])), int(round(pt[1]))) not in roi_set
948+
]
949+
950+
# Remove from grid ROI points
951+
for grid in self.grid_polygons:
952+
grid['roi_points'] = [
953+
pt for pt in grid['roi_points']
954+
if (int(round(pt[0])), int(round(pt[1]))) not in roi_set
955+
]
956+
957+
self.brush_deselect_mode = False
958+
self.brush_deselect_button.setChecked(False)
959+
960+
else:
961+
self.manual_points.extend(brush_rois)
924962

925963
self._paint_mask = None
926964
self.update_selected_points()
927965
self.update_brush_overlay()
928966

929-
930967
def update_brush_overlay(self):
931968
if not hasattr(self, 'brush_overlay'):
932969
self.brush_overlay = ImageItem()
@@ -939,6 +976,11 @@ def update_brush_overlay(self):
939976
self.brush_overlay.setZValue(2)
940977
else:
941978
self.brush_overlay.clear()
979+
980+
def activate_brush_deselect(self):
981+
if self.brush_deselect_button.isChecked():
982+
self.brush_deselect_mode = True
983+
942984
################################################################################################
943985
# Automatic subset detection
944986
################################################################################################

0 commit comments

Comments
 (0)