Enhance template management in VideoEditor by including template images

This commit updates the template management system in the VideoEditor to store template images alongside their start frames and regions. The changes include modifications to the loading and saving processes, ensuring that template images are recreated when needed. Additionally, the logic for adding and retrieving templates has been refined to accommodate the new structure, improving the overall efficiency and clarity of template handling during video editing sessions.
This commit is contained in:
2025-09-26 19:35:13 +02:00
parent 1ac8cd04b3
commit b5a0811cbd

View File

@@ -865,8 +865,8 @@ class VideoEditor:
self.template_selection_start = None self.template_selection_start = None
self.template_selection_rect = None self.template_selection_rect = None
# Simple template system - list of (start_frame, region) tuples sorted by start_frame # Simple template system - list of (start_frame, region, template_image) tuples sorted by start_frame
self.templates = [] # [(start_frame, region), ...] sorted by start_frame self.templates = [] # [(start_frame, region, template_image), ...] sorted by start_frame
# Template matching modes # Template matching modes
self.template_matching_full_frame = False # Toggle for full frame vs cropped template matching self.template_matching_full_frame = False # Toggle for full frame vs cropped template matching
@@ -921,7 +921,7 @@ class VideoEditor:
'templates': [{ 'templates': [{
'start_frame': start_frame, 'start_frame': start_frame,
'region': region 'region': region
} for start_frame, region in self.templates] } for start_frame, region, template_image in self.templates]
} }
with open(state_file, 'w') as f: with open(state_file, 'w') as f:
@@ -1017,10 +1017,16 @@ class VideoEditor:
if 'templates' in state: if 'templates' in state:
self.templates = [] self.templates = []
for template_data in state['templates']: for template_data in state['templates']:
self.templates.append((template_data['start_frame'], template_data['region'])) start_frame = template_data['start_frame']
region = template_data['region']
# We'll recreate the template image when needed
self.templates.append((start_frame, region, None))
# Sort by start_frame # Sort by start_frame
self.templates.sort(key=lambda x: x[0]) self.templates.sort(key=lambda x: x[0])
print(f"Loaded {len(self.templates)} templates") print(f"Loaded {len(self.templates)} templates")
# Recreate template images by seeking to capture frames
self._recreate_template_images()
# 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:
@@ -2274,14 +2280,10 @@ class VideoEditor:
if template_index is None: if template_index is None:
return None return None
start_frame, region = self.templates[template_index] start_frame, region, template_image = self.templates[template_index]
x, y, w, h = region
# Extract template from current frame # Use the stored template image from when it was captured
if (y + h <= frame.shape[0] and x + w <= frame.shape[1]): tracking_template = template_image
tracking_template = frame[y:y+h, x:x+w]
else:
return None
try: try:
# Apply image preprocessing for better template matching # Apply image preprocessing for better template matching
@@ -2392,8 +2394,8 @@ class VideoEditor:
if start_frame is None: if start_frame is None:
start_frame = self.current_frame start_frame = self.current_frame
# Add template to list # Add template to list with the actual template image
self.templates.append((start_frame, region)) self.templates.append((start_frame, region, template.copy()))
# Sort by start_frame # Sort by start_frame
self.templates.sort(key=lambda x: x[0]) self.templates.sort(key=lambda x: x[0])
@@ -2410,7 +2412,7 @@ class VideoEditor:
current_frame = self.current_frame current_frame = self.current_frame
template_to_remove = None template_to_remove = None
for i, (start_frame, region) in enumerate(self.templates): for i, (start_frame, region, template_image) in enumerate(self.templates):
if start_frame > current_frame: if start_frame > current_frame:
# Found template with start_frame > current_frame # Found template with start_frame > current_frame
# Remove the previous one (if it exists) # Remove the previous one (if it exists)
@@ -2432,7 +2434,7 @@ class VideoEditor:
return None return None
# Find template with start_frame > current_frame # Find template with start_frame > current_frame
for i, (start_frame, region) in enumerate(self.templates): for i, (start_frame, region, template_image) in enumerate(self.templates):
if start_frame > frame_number: if start_frame > frame_number:
# Found template with start_frame > current_frame # Found template with start_frame > current_frame
# Use the previous one (if it exists) # Use the previous one (if it exists)
@@ -2449,6 +2451,35 @@ class VideoEditor:
template_index = self.get_template_for_frame(frame_number) template_index = self.get_template_for_frame(frame_number)
return template_index is not None return template_index is not None
def _recreate_template_images(self):
"""Recreate template images by seeking to their capture frames"""
if not self.templates:
return
current_frame_backup = self.current_frame
for i, (start_frame, region, template_image) in enumerate(self.templates):
if template_image is None: # Only recreate if missing
try:
# Seek to the capture frame
self.seek_to_frame(start_frame)
# Extract template from current frame
x, y, w, h = region
if (y + h <= self.current_display_frame.shape[0] and
x + w <= self.current_display_frame.shape[1]):
template_image = self.current_display_frame[y:y+h, x:x+w].copy()
# Update the template in the list
self.templates[i] = (start_frame, region, template_image)
print(f"DEBUG: Recreated template {i} from frame {start_frame}")
else:
print(f"DEBUG: Failed to recreate template {i} - region outside frame bounds")
except Exception as e:
print(f"DEBUG: Failed to recreate template {i}: {e}")
# Restore original frame
self.seek_to_frame(current_frame_backup)
def jump_to_previous_template(self): def jump_to_previous_template(self):
"""Jump to the previous template marker (frame where template was created).""" """Jump to the previous template marker (frame where template was created)."""
@@ -2459,7 +2490,7 @@ class VideoEditor:
print("DEBUG: No template markers; prev jump ignored") print("DEBUG: No template markers; prev jump ignored")
return return
current = self.current_frame current = self.current_frame
candidates = [start_frame for start_frame, region in self.templates if start_frame < current] candidates = [start_frame for start_frame, region, template_image in self.templates if start_frame < current]
if candidates: if candidates:
target = candidates[-1] target = candidates[-1]
print(f"DEBUG: Jump prev template from {current} -> {target}") print(f"DEBUG: Jump prev template from {current} -> {target}")
@@ -2478,7 +2509,7 @@ class VideoEditor:
print("DEBUG: No template markers; next jump ignored") print("DEBUG: No template markers; next jump ignored")
return return
current = self.current_frame current = self.current_frame
for start_frame, region in self.templates: for start_frame, region, template_image in self.templates:
if start_frame > current: if start_frame > current:
print(f"DEBUG: Jump next template from {current} -> {start_frame}") print(f"DEBUG: Jump next template from {current} -> {start_frame}")
self.seek_to_frame(start_frame) self.seek_to_frame(start_frame)
@@ -2942,14 +2973,14 @@ class VideoEditor:
) )
# Draw template markers # Draw template markers
for start_frame, region in self.templates: for start_frame, region, template_image in self.templates:
# Draw template start point # Draw template start point
start_progress = start_frame / max(1, self.total_frames - 1) start_progress = start_frame / max(1, self.total_frames - 1)
start_x = bar_x_start + int(bar_width * start_progress) start_x = bar_x_start + int(bar_width * start_progress)
# Template color (green for active, red for inactive) # Template color (green for active, red for inactive)
template_index = self.get_template_for_frame(self.current_frame) template_index = self.get_template_for_frame(self.current_frame)
is_active = (template_index is not None and self.templates[template_index] == (start_frame, region)) is_active = (template_index is not None and self.templates[template_index][0] == start_frame)
template_color = (0, 255, 0) if is_active else (255, 0, 0) # Green if active, red if inactive template_color = (0, 255, 0) if is_active else (255, 0, 0) # Green if active, red if inactive
# Draw template start marker # Draw template start marker
@@ -3421,7 +3452,7 @@ class VideoEditor:
screen_x, screen_y = x, y screen_x, screen_y = x, y
raw_x, raw_y = self._map_screen_to_rotated(screen_x, screen_y) raw_x, raw_y = self._map_screen_to_rotated(screen_x, screen_y)
for i, (start_frame, region) in enumerate(self.templates): for i, (start_frame, region, template_image) in enumerate(self.templates):
tx, ty, tw, th = region tx, ty, tw, th = region
center_x = tx + tw // 2 center_x = tx + tw // 2
center_y = ty + th // 2 center_y = ty + th // 2