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