Enhance VideoEditor with template matching state management and user interaction updates

This commit adds functionality to manage the state of template matching in the VideoEditor, including loading and saving template matching settings. It also updates user interaction for selecting template regions, changing the control scheme from Alt+Right-click to Ctrl+Left-click for better usability. Additionally, it improves the handling of the current display frame during feature extraction, ensuring robustness in the tracking process.
This commit is contained in:
2025-09-26 14:26:42 +02:00
parent c749d9af80
commit f942392fb3

View File

@@ -929,7 +929,10 @@ class VideoEditor:
'is_playing': getattr(self, 'is_playing', False),
'tracking_enabled': self.tracking_enabled,
'tracking_points': {str(k): v for k, v in self.tracking_points.items()},
'feature_tracker': self.feature_tracker.get_state_dict()
'feature_tracker': self.feature_tracker.get_state_dict(),
'template_matching_enabled': self.template_matching_enabled,
'tracking_template': self.tracking_template,
'template_region': self.template_region
}
with open(state_file, 'w') as f:
@@ -1017,6 +1020,14 @@ class VideoEditor:
self.feature_tracker.load_state_dict(state['feature_tracker'])
print(f"Loaded feature tracker state")
# Load template matching state
if 'template_matching_enabled' in state:
self.template_matching_enabled = state['template_matching_enabled']
if 'tracking_template' in state and state['tracking_template'] is not None:
self.tracking_template = state['tracking_template']
if 'template_region' in state:
self.template_region = state['template_region']
# Validate cut markers against current video length
if self.cut_start_frame is not None and self.cut_start_frame >= self.total_frames:
print(f"DEBUG: cut_start_frame {self.cut_start_frame} is beyond video length {self.total_frames}, clearing")
@@ -1831,21 +1842,22 @@ class VideoEditor:
orig_x + orig_w <= self.frame_width and
orig_y + orig_h <= self.frame_height):
region_frame = self.current_display_frame[orig_y:orig_y+orig_h, orig_x:orig_x+orig_w]
if region_frame.size > 0:
# Map coordinates from region to rotated frame coordinates
def coord_mapper(px, py):
# Map from region coordinates to rotated frame coordinates
if self.rotation_angle == 90:
rot_x = orig_x + py
rot_y = self.frame_height - (orig_y + px)
elif self.rotation_angle == 270:
rot_x = self.frame_width - (orig_y + py)
rot_y = orig_x + px
else:
rot_x = orig_x + px
rot_y = orig_y + py
return (int(rot_x), int(rot_y))
if self.current_display_frame is not None:
region_frame = self.current_display_frame[orig_y:orig_y+orig_h, orig_x:orig_x+orig_w]
if region_frame is not None and region_frame.size > 0:
# Map coordinates from region to rotated frame coordinates
def coord_mapper(px, py):
# Map from region coordinates to rotated frame coordinates
if self.rotation_angle == 90:
rot_x = orig_x + py
rot_y = self.frame_height - (orig_y + px)
elif self.rotation_angle == 270:
rot_x = self.frame_width - (orig_y + py)
rot_y = orig_x + px
else:
rot_x = orig_x + px
rot_y = orig_y + py
return (int(rot_x), int(rot_y))
# Extract features and add them to existing features
success = self.feature_tracker.extract_features_from_region(region_frame, self.current_frame, coord_mapper)
@@ -2143,7 +2155,7 @@ class VideoEditor:
# Template matching
result = cv2.matchTemplate(gray_frame, gray_template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
_, max_val, _, max_loc = cv2.minMaxLoc(result)
# Only accept matches above threshold
if max_val > 0.6: # Adjust threshold as needed
@@ -3055,21 +3067,21 @@ class VideoEditor:
self.selective_feature_deletion_start = None
self.selective_feature_deletion_rect = None
# Handle Alt+Right-click+drag for template region selection
if event == cv2.EVENT_RBUTTONDOWN and (flags & cv2.EVENT_FLAG_ALTKEY):
# Handle Ctrl+Left-click+drag for template region selection
if event == cv2.EVENT_LBUTTONDOWN and (flags & cv2.EVENT_FLAG_CTRLKEY):
if not self.is_image_mode:
self.template_selection_start = (x, y)
self.template_selection_rect = None
print(f"DEBUG: Started template selection at ({x}, {y})")
# Handle Alt+Right-click+drag for template region selection
if event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_ALTKEY) and self.template_selection_start:
# Handle Ctrl+Left-click+drag for template region selection
if event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_CTRLKEY) and self.template_selection_start:
if not self.is_image_mode:
start_x, start_y = self.template_selection_start
self.template_selection_rect = (min(start_x, x), min(start_y, y), abs(x - start_x), abs(y - start_y))
# Handle Alt+Right-click release for template region selection
if event == cv2.EVENT_RBUTTONUP and (flags & cv2.EVENT_FLAG_ALTKEY) and self.template_selection_start:
# Handle Ctrl+Left-click release for template region selection
if event == cv2.EVENT_LBUTTONUP and (flags & cv2.EVENT_FLAG_CTRLKEY) and self.template_selection_start:
if not self.is_image_mode and self.template_selection_rect:
self._set_template_from_region(self.template_selection_rect)
self.template_selection_start = None
@@ -3927,7 +3939,7 @@ class VideoEditor:
print(" m: Toggle template matching tracking")
print(" Shift+Right-click+drag: Extract features from selected region")
print(" Ctrl+Right-click+drag: Delete features from selected region")
print(" Alt+Right-click+drag: Set template region for tracking")
print(" Ctrl+Left-click+drag: Set template region for tracking")
if len(self.video_files) > 1:
print(" N: Next video")
print(" n: Previous video")