@@ -90,6 +90,7 @@ def __init__(self, video):
9090
9191 # Ensure method-specific widgets are visible on startup
9292 self .method_selected (self .button_group .checkedId ())
93+ self .auto_method_selected (0 )
9394
9495 # Set the initial mode
9596 self .switch_mode ("manual" ) # Default to manual mode
@@ -286,40 +287,87 @@ def update_label_and_recompute(val):
286287 self .manual_layout .addWidget (self .delete_grid_button )
287288
288289 def ui_auto_right_menu (self ):
290+ # Title and method selector
291+ self .automatic_layout .addWidget (QtWidgets .QLabel ("Automatic method:" ))
292+
293+ self .auto_method_group = QtWidgets .QButtonGroup (self .automatic_widget )
294+ self .auto_method_group .setExclusive (True )
295+
296+ self .auto_method_buttons = {}
297+ method_names = [
298+ "Shi-Tomasi" ,
299+ ]
300+ for i , name in enumerate (method_names ):
301+ button = QtWidgets .QPushButton (name )
302+ button .setCheckable (True )
303+ if i == 0 :
304+ button .setChecked (True )
305+ self .auto_method_group .addButton (button , i )
306+ self .automatic_layout .addWidget (button )
307+ self .auto_method_buttons [name ] = button
308+
309+ self .auto_method_group .idClicked .connect (self .auto_method_selected )
310+
311+ self .automatic_layout .addSpacing (10 )
312+
313+ # Dynamic method-specific widgets (for now shared)
289314 self .candidate_count_label = QtWidgets .QLabel ("N candidate points: 0" )
290315 font = self .candidate_count_label .font ()
291316 font .setPointSize (10 )
292317 font .setBold (True )
293318 self .candidate_count_label .setFont (font )
294319 self .automatic_layout .addWidget (self .candidate_count_label )
295320
321+ self .clear_candidates_button = QtWidgets .QPushButton ("Clear candidates" )
322+ self .clear_candidates_button .clicked .connect (self .clear_candidates )
323+ self .automatic_layout .addWidget (self .clear_candidates_button )
324+
325+ # Checkbox to show/hide scatter and ROI overlay
326+ self .show_points_checkbox = QtWidgets .QCheckBox ("Show points/ROIs" )
327+ self .show_points_checkbox .setChecked (False )
328+ def toggle_points_and_roi (state ):
329+ self .roi_overlay .setVisible (state )
330+ self .scatter .setVisible (state )
331+ self .show_points_checkbox .stateChanged .connect (toggle_points_and_roi )
332+ self .automatic_layout .addWidget (self .show_points_checkbox )
333+
334+ # Horizontal line separator for visual clarity
335+ hline = QtWidgets .QFrame ()
336+ hline .setFrameShape (QtWidgets .QFrame .Shape .HLine )
337+ hline .setFrameShadow (QtWidgets .QFrame .Shadow .Sunken )
338+ self .automatic_layout .addWidget (hline )
339+
340+ self .automatic_layout .addSpacing (10 )
341+
342+ # Shi-Tomasi method settings
296343 self .threshold_label = QtWidgets .QLabel ("Threshold:" )
344+ self .threshold_label .setVisible (False )
297345 self .automatic_layout .addWidget (self .threshold_label )
298346
299347 self .threshold_slider = QtWidgets .QSlider (QtCore .Qt .Orientation .Horizontal )
300348 self .threshold_slider .setRange (1 , 100 )
301349 self .threshold_slider .setSingleStep (1 )
302350 self .threshold_slider .setValue (10 )
351+ self .threshold_slider .setVisible (False )
303352 self .automatic_layout .addWidget (self .threshold_slider )
304353
305354 def update_label_and_recompute (val ):
306355 self .threshold_label .setText (f"Threshold: { str (val )} " )
307- self .compute_candidate_points ()
356+ self .compute_candidate_points_shi_tomasi () # Placeholder method
308357 self .threshold_slider .valueChanged .connect (update_label_and_recompute )
309358
359+ self .automatic_layout .addStretch (1 )
310360
311- # Checkbox to show/hide scatter and ROI overlay
312- self .show_points_checkbox = QtWidgets .QCheckBox ("Show points/ROIs" )
313- self .show_points_checkbox .setChecked (False )
314- def toggle_points_and_roi (state ):
315- self .roi_overlay .setVisible (state )
316- self .scatter .setVisible (state )
317- self .show_points_checkbox .stateChanged .connect (toggle_points_and_roi )
318- self .automatic_layout .addWidget (self .show_points_checkbox )
361+ def auto_method_selected (self , id : int ):
362+ method_name = list (self .auto_method_buttons .keys ())[id ]
363+ print (f"Selected automatic method: { method_name } " )
364+ # Here you can switch method behavior, show/hide widgets, etc.
365+ is_shi_tomasi = method_name == "Shi-Tomasi"
366+ self .threshold_label .setVisible (is_shi_tomasi )
367+ self .threshold_slider .setVisible (is_shi_tomasi )
319368
320- self .clear_candidates_button = QtWidgets .QPushButton ("Clear candidates" )
321- self .clear_candidates_button .clicked .connect (self .clear_candidates )
322- self .automatic_layout .addWidget (self .clear_candidates_button )
369+ if is_shi_tomasi :
370+ self .compute_candidate_points_shi_tomasi ()
323371
324372 def method_selected (self , id : int ):
325373 method_name = list (self .method_buttons .keys ())[id ]
@@ -691,7 +739,7 @@ def handle_remove_point(self, event):
691739 self .update_selected_points ()
692740
693741 # Automatic filtering
694- def compute_candidate_points (self ):
742+ def compute_candidate_points_shi_tomasi (self ):
695743 """Compute good feature points using structure tensor analysis (Shi–Tomasi style)."""
696744 from scipy .ndimage import sobel
697745
0 commit comments