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