Refactor template management in VideoEditor to streamline template handling

This commit removes unused attributes and logic related to template matching, enhancing the clarity and efficiency of the template management system. The changes include the removal of the template matching enabled flag and associated state management, focusing on the current template ID and its associated data. Debug messages have been updated to reflect these changes, ensuring better tracking and feedback during video editing sessions.
This commit is contained in:
2025-09-26 18:42:35 +02:00
parent 9df6d73db8
commit e1d94f2b24

View File

@@ -860,9 +860,6 @@ class VideoEditor:
self.previous_frame_for_flow = None
# Template matching tracking
self.template_matching_enabled = False
self.tracking_template = None
self.template_region = None
self.template_match_history = [] # Store recent match confidences for adaptive thresholding
# (x, y, w, h) in rotated frame coordinates
self.template_selection_start = None
@@ -922,8 +919,6 @@ class VideoEditor:
'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(),
'template_matching_enabled': self.template_matching_enabled,
'template_region': self.template_region,
'template_matching_full_frame': self.template_matching_full_frame,
'templates': {str(k): {
'template': None, # Don't save template images (too large)
@@ -1021,12 +1016,6 @@ class VideoEditor:
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 'template_region' in state and state['template_region'] is not None:
self.template_region = state['template_region']
# Recreate template from region when needed
self.tracking_template = None
if 'template_matching_full_frame' in state:
self.template_matching_full_frame = state['template_matching_full_frame']
@@ -1666,7 +1655,7 @@ class VideoEditor:
# Calculate offset from template matching if enabled
template_offset = None
if self.template_matching_enabled and self.tracking_template is not None:
if self.templates and self.current_template_id is not None:
if self.current_display_frame is not None:
if self.template_matching_full_frame:
# Full frame mode - use the entire original frame
@@ -1836,7 +1825,7 @@ class VideoEditor:
def _get_template_matching_position(self, frame_number):
"""Get template matching position and confidence for a frame"""
if not self.template_matching_enabled or self.tracking_template is None:
if not self.templates or self.current_template_id is None:
return None
if self.current_display_frame is not None:
@@ -1948,8 +1937,6 @@ class VideoEditor:
def _map_screen_to_rotated(self, sx, sy):
"""Map a point on canvas screen coords back to ROTATED frame coords (pre-crop)."""
frame_number = getattr(self, 'current_frame', 0)
angle = self.rotation_angle
# Use unified display params
params = self._get_display_params()
# Back to processed (zoomed+cropped) space
@@ -2293,12 +2280,18 @@ class VideoEditor:
def track_template(self, frame):
"""Track the template in the current frame"""
if self.tracking_template is None:
if self.current_template_id is None or self.current_template_id not in self.templates:
return None
template_data = self.templates[self.current_template_id]
tracking_template = template_data['template']
if tracking_template is None:
return None
try:
# Apply image preprocessing for better template matching
gray_frame, gray_template = self._improve_template_matching(frame, self.tracking_template)
gray_frame, gray_template = self._improve_template_matching(frame, tracking_template)
# Single-scale template matching (faster)
result = cv2.matchTemplate(gray_frame, gray_template, cv2.TM_CCOEFF_NORMED)
@@ -2391,7 +2384,7 @@ class VideoEditor:
# Extract template from raw frame
template = self.current_display_frame[raw_y:raw_y+raw_h, raw_x:raw_x+raw_w]
if template.size > 0:
# Add template to collection instead of setting single template
# Add template to collection
template_id = self.add_template(template, (raw_x, raw_y, raw_w, raw_h))
self.show_feedback_message(f"Template {template_id} set from region ({raw_w}x{raw_h})")
print(f"DEBUG: Template {template_id} set with size {template.shape}")
@@ -2410,16 +2403,19 @@ class VideoEditor:
if end_frame is None:
end_frame = self.total_frames - 1
# End any templates that start after the current frame
# Only end the current template if it exists and starts at or before the current frame
if self.current_template_id is not None and self.current_template_id in self.templates:
current_template = self.templates[self.current_template_id]
if current_template['start_frame'] <= self.current_frame:
# End the current template at the previous frame
self.templates[self.current_template_id]['end_frame'] = self.current_frame - 1
print(f"DEBUG: Ended current template {self.current_template_id} at frame {self.current_frame - 1}")
# Remove any templates that start after the current frame (they shouldn't exist yet)
for template_id, template_data in list(self.templates.items()):
if template_data['start_frame'] > self.current_frame:
# This template starts after the current frame, so remove it
del self.templates[template_id]
print(f"DEBUG: Removed future template {template_id} that started at frame {template_data['start_frame']}")
elif template_data['start_frame'] == self.current_frame:
# This template starts at the same frame, end it at the previous frame
self.templates[template_id]['end_frame'] = self.current_frame - 1
print(f"DEBUG: Ended template {template_id} at frame {self.current_frame - 1}")
self.templates[template_id] = {
'template': template.copy(),
@@ -2428,11 +2424,8 @@ class VideoEditor:
'end_frame': end_frame
}
# Set as current template and enable template matching
# Set as current template
self.current_template_id = template_id
self.tracking_template = template.copy()
self.template_region = region
self.template_matching_enabled = True # Enable template matching when template is created
self.show_feedback_message(f"Template {template_id} added (frames {start_frame}-{end_frame})")
return template_id
@@ -2446,11 +2439,8 @@ class VideoEditor:
if self.current_template_id == template_id:
self._select_best_template_for_frame(self.current_frame)
# If no templates left, disable template matching
# If no templates left, clear current template
if not self.templates:
self.template_matching_enabled = False
self.tracking_template = None
self.template_region = None
self.current_template_id = None
self.show_feedback_message(f"Template {template_id} removed")
@@ -2491,13 +2481,10 @@ class VideoEditor:
else:
return False
self.tracking_template = template_data['template'].copy()
self.template_region = template_data['region']
# Template is already stored in the templates dict
return True
else:
self.current_template_id = None
self.tracking_template = None
self.template_region = None
return False
def _recreate_template_from_template_data(self, template_id, frame):
@@ -3168,7 +3155,7 @@ class VideoEditor:
if self.optical_flow_enabled:
feature_text += " (OPTICAL FLOW)"
template_text = ""
if self.template_matching_enabled:
if self.templates:
mode = "Full Frame" if self.template_matching_full_frame else "Cropped"
template_text = f" | Template: {mode}"
autorepeat_text = (
@@ -3284,8 +3271,8 @@ class VideoEditor:
# Draw template matching point (blue circle with confidence)
if (not self.is_image_mode and
self.template_matching_enabled and
self.tracking_template is not None):
self.templates and
self.current_template_id is not None):
# Get template matching position for current frame
template_pos = self._get_template_matching_position(self.current_frame)
if template_pos:
@@ -3911,13 +3898,10 @@ class VideoEditor:
def _render_video_worker(self, output_path: str):
"""Worker method that runs in the render thread"""
render_cap = None
try:
if not output_path.endswith(".mp4"):
output_path += ".mp4"
start_time = time.time()
# Send progress update to main thread
self.render_progress_queue.put(("init", "Initializing render...", 0.0, 0.0))
@@ -4728,10 +4712,15 @@ class VideoEditor:
self.show_feedback_message(f"Optical flow {'ON' if self.optical_flow_enabled else 'OFF'}")
self.save_state()
elif key == ord("m"):
# Toggle template matching tracking
self.template_matching_enabled = not self.template_matching_enabled
print(f"DEBUG: Template matching toggled to {self.template_matching_enabled}")
self.show_feedback_message(f"Template matching {'ON' if self.template_matching_enabled else 'OFF'}")
# Clear all templates
if self.templates:
self.templates.clear()
self.current_template_id = None
print("DEBUG: All templates cleared")
self.show_feedback_message("All templates cleared")
else:
print("DEBUG: No templates to clear")
self.show_feedback_message("No templates to clear")
self.save_state()
elif key == ord("M"): # Shift+M - Toggle multi-scale template matching
self.template_matching_full_frame = not self.template_matching_full_frame