diff --git a/croppa/main.py b/croppa/main.py index 3497523..2d7acf7 100644 --- a/croppa/main.py +++ b/croppa/main.py @@ -882,7 +882,7 @@ class VideoEditor: self.tracking_template = None self.template_region = None self.template_match_history = [] # Store recent match confidences for adaptive thresholding - self.multi_scale_template_matching = False # Disable multi-scale by default # (x, y, w, h) in rotated frame coordinates + # (x, y, w, h) in rotated frame coordinates self.template_selection_start = None self.template_selection_rect = None @@ -890,6 +890,9 @@ class VideoEditor: self.templates = {} # {template_id: {'template': image, 'region': (x,y,w,h), 'start_frame': int, 'end_frame': int}} self.current_template_id = None self.template_id_counter = 0 + + # Template matching modes + self.template_matching_full_frame = False # Toggle for full frame vs cropped template matching # Project view mode self.project_view_mode = False @@ -939,7 +942,7 @@ class VideoEditor: 'feature_tracker': self.feature_tracker.get_state_dict(), 'template_matching_enabled': self.template_matching_enabled, 'template_region': self.template_region, - 'multi_scale_template_matching': self.multi_scale_template_matching, + 'template_matching_full_frame': self.template_matching_full_frame, 'templates': {str(k): { 'template': None, # Don't save template images (too large) 'region': v['region'], @@ -1042,8 +1045,8 @@ class VideoEditor: self.template_region = state['template_region'] # Recreate template from region when needed self.tracking_template = None - if 'multi_scale_template_matching' in state: - self.multi_scale_template_matching = state['multi_scale_template_matching'] # Will be recreated on first use + if 'template_matching_full_frame' in state: + self.template_matching_full_frame = state['template_matching_full_frame'] # Load multiple templates state if 'templates' in state: @@ -1683,34 +1686,42 @@ class VideoEditor: template_offset = None if self.template_matching_enabled and self.tracking_template is not None: if self.current_display_frame is not None: - # Use only the cropped region for much faster template matching - if self.crop_rect: - crop_x, crop_y, crop_w, crop_h = self.crop_rect - # Extract only the cropped region from raw frame - cropped_frame = self.current_display_frame[crop_y:crop_y+crop_h, crop_x:crop_x+crop_w] - if cropped_frame is not None and cropped_frame.size > 0: - # Apply motion tracking offset to the cropped frame - offset_frame = self._apply_motion_tracking_offset(cropped_frame, base_pos) + if self.template_matching_full_frame: + # Full frame mode - use the entire original frame + result = self.track_template(self.current_display_frame) + if result: + center_x, center_y, confidence = result + print(f"DEBUG: Template match found at ({center_x}, {center_y}) with confidence {confidence:.2f}") + template_offset = (center_x, center_y) + else: + # Cropped mode - use only the cropped region for faster template matching + if self.crop_rect: + crop_x, crop_y, crop_w, crop_h = self.crop_rect + # Extract only the cropped region from raw frame + cropped_frame = self.current_display_frame[crop_y:crop_y+crop_h, crop_x:crop_x+crop_w] + if cropped_frame is not None and cropped_frame.size > 0: + # Apply motion tracking offset to the cropped frame + offset_frame = self._apply_motion_tracking_offset(cropped_frame, base_pos) + if offset_frame is not None: + # Track template in cropped and offset frame (much faster!) + result = self.track_template(offset_frame) + if result: + center_x, center_y, confidence = result + print(f"DEBUG: Template match found at ({center_x}, {center_y}) with confidence {confidence:.2f}") + + # Map from cropped frame coordinates to raw frame coordinates + # Add crop offset back + raw_x = center_x + crop_x + raw_y = center_y + crop_y + template_offset = (raw_x, raw_y) + else: + # No crop - use full frame with offset + offset_frame = self._apply_motion_tracking_offset(self.current_display_frame, base_pos) if offset_frame is not None: - # Track template in cropped and offset frame (much faster!) result = self.track_template(offset_frame) if result: center_x, center_y, confidence = result - print(f"DEBUG: Template match found at ({center_x}, {center_y}) with confidence {confidence:.2f}") - - # Map from cropped frame coordinates to raw frame coordinates - # Add crop offset back - raw_x = center_x + crop_x - raw_y = center_y + crop_y - template_offset = (raw_x, raw_y) - else: - # No crop - use full frame with offset - offset_frame = self._apply_motion_tracking_offset(self.current_display_frame, base_pos) - if offset_frame is not None: - result = self.track_template(offset_frame) - if result: - center_x, center_y, confidence = result - template_offset = (center_x, center_y) + template_offset = (center_x, center_y) # Calculate offset from feature tracking if enabled feature_offset = None @@ -1850,32 +1861,39 @@ class VideoEditor: # Get base position for motion tracking offset base_pos = self._get_manual_tracking_position(frame_number) - # Use only the cropped region for much faster template matching - if self.crop_rect: - crop_x, crop_y, crop_w, crop_h = self.crop_rect - # Extract only the cropped region from raw frame - cropped_frame = self.current_display_frame[crop_y:crop_y+crop_h, crop_x:crop_x+crop_w] - if cropped_frame is not None and cropped_frame.size > 0: - # Apply motion tracking offset to the cropped frame - offset_frame = self._apply_motion_tracking_offset(cropped_frame, base_pos) + if self.template_matching_full_frame: + # Full frame mode - use the entire original frame + result = self.track_template(self.current_display_frame) + if result: + center_x, center_y, confidence = result + return (center_x, center_y, confidence) + else: + # Cropped mode - use only the cropped region for faster template matching + if self.crop_rect: + crop_x, crop_y, crop_w, crop_h = self.crop_rect + # Extract only the cropped region from raw frame + cropped_frame = self.current_display_frame[crop_y:crop_y+crop_h, crop_x:crop_x+crop_w] + if cropped_frame is not None and cropped_frame.size > 0: + # Apply motion tracking offset to the cropped frame + offset_frame = self._apply_motion_tracking_offset(cropped_frame, base_pos) + if offset_frame is not None: + # Track template in cropped and offset frame (much faster!) + result = self.track_template(offset_frame) + if result: + center_x, center_y, confidence = result + # Map from cropped frame coordinates to raw frame coordinates + # Add crop offset back + raw_x = center_x + crop_x + raw_y = center_y + crop_y + return (raw_x, raw_y, confidence) + else: + # No crop - use full frame with offset + offset_frame = self._apply_motion_tracking_offset(self.current_display_frame, base_pos) if offset_frame is not None: - # Track template in cropped and offset frame (much faster!) result = self.track_template(offset_frame) if result: center_x, center_y, confidence = result - # Map from cropped frame coordinates to raw frame coordinates - # Add crop offset back - raw_x = center_x + crop_x - raw_y = center_y + crop_y - return (raw_x, raw_y, confidence) - else: - # No crop - use full frame with offset - offset_frame = self._apply_motion_tracking_offset(self.current_display_frame, base_pos) - if offset_frame is not None: - result = self.track_template(offset_frame) - if result: - center_x, center_y, confidence = result - return (center_x, center_y, confidence) + return (center_x, center_y, confidence) return None @@ -2312,7 +2330,7 @@ class VideoEditor: gray_frame, gray_template = self._improve_template_matching(frame, self.tracking_template) # Multi-scale template matching for better tracking (if enabled) - if self.multi_scale_template_matching: + if False: # Multi-scale template matching removed scales = [0.8, 0.9, 1.0, 1.1, 1.2] # Different scales to try best_match = None best_confidence = 0.0 @@ -3231,10 +3249,11 @@ class VideoEditor: feature_text = f" | Features: {feature_count} pts" if self.optical_flow_enabled: feature_text += " (OPTICAL FLOW)" - template_text = ( - f" | Template: {self.template_matching_enabled}" if self.template_matching_enabled else "" - ) - if self.template_matching_enabled and self.multi_scale_template_matching: + template_text = "" + if self.template_matching_enabled: + mode = "Full Frame" if self.template_matching_full_frame else "Cropped" + template_text = f" | Template: {mode}" + if False: # Multi-scale template matching removed template_text += " (MULTI-SCALE)" autorepeat_text = ( f" | Loop: ON" if self.looping_between_markers else "" @@ -4799,9 +4818,9 @@ class VideoEditor: self.show_feedback_message(f"Template matching {'ON' if self.template_matching_enabled else 'OFF'}") self.save_state() elif key == ord("M"): # Shift+M - Toggle multi-scale template matching - self.multi_scale_template_matching = not self.multi_scale_template_matching - print(f"DEBUG: Multi-scale template matching toggled to {self.multi_scale_template_matching}") - self.show_feedback_message(f"Multi-scale template matching {'ON' if self.multi_scale_template_matching else 'OFF'}") + self.template_matching_full_frame = not self.template_matching_full_frame + print(f"DEBUG: Template matching full frame toggled to {self.template_matching_full_frame}") + self.show_feedback_message(f"Template matching: {'Full Frame' if self.template_matching_full_frame else 'Cropped'}") self.save_state() elif key == ord(";"): # Semicolon - Jump to previous template marker self.jump_to_previous_template()