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:
@@ -865,8 +865,8 @@ class VideoEditor:
|
||||
self.template_selection_start = None
|
||||
self.template_selection_rect = None
|
||||
|
||||
# Simple template system - list of (start_frame, region) tuples sorted by start_frame
|
||||
self.templates = [] # [(start_frame, region), ...] sorted by start_frame
|
||||
# Simple template system - list of (start_frame, region, template_image) tuples sorted by start_frame
|
||||
self.templates = [] # [(start_frame, region, template_image), ...] sorted by start_frame
|
||||
|
||||
# Template matching modes
|
||||
self.template_matching_full_frame = False # Toggle for full frame vs cropped template matching
|
||||
@@ -921,7 +921,7 @@ class VideoEditor:
|
||||
'templates': [{
|
||||
'start_frame': start_frame,
|
||||
'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:
|
||||
@@ -1017,11 +1017,17 @@ class VideoEditor:
|
||||
if 'templates' in state:
|
||||
self.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
|
||||
self.templates.sort(key=lambda x: x[0])
|
||||
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
|
||||
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")
|
||||
@@ -2274,14 +2280,10 @@ class VideoEditor:
|
||||
if template_index is None:
|
||||
return None
|
||||
|
||||
start_frame, region = self.templates[template_index]
|
||||
x, y, w, h = region
|
||||
start_frame, region, template_image = self.templates[template_index]
|
||||
|
||||
# Extract template from current frame
|
||||
if (y + h <= frame.shape[0] and x + w <= frame.shape[1]):
|
||||
tracking_template = frame[y:y+h, x:x+w]
|
||||
else:
|
||||
return None
|
||||
# Use the stored template image from when it was captured
|
||||
tracking_template = template_image
|
||||
|
||||
try:
|
||||
# Apply image preprocessing for better template matching
|
||||
@@ -2392,8 +2394,8 @@ class VideoEditor:
|
||||
if start_frame is None:
|
||||
start_frame = self.current_frame
|
||||
|
||||
# Add template to list
|
||||
self.templates.append((start_frame, region))
|
||||
# Add template to list with the actual template image
|
||||
self.templates.append((start_frame, region, template.copy()))
|
||||
|
||||
# Sort by start_frame
|
||||
self.templates.sort(key=lambda x: x[0])
|
||||
@@ -2410,7 +2412,7 @@ class VideoEditor:
|
||||
current_frame = self.current_frame
|
||||
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:
|
||||
# Found template with start_frame > current_frame
|
||||
# Remove the previous one (if it exists)
|
||||
@@ -2432,7 +2434,7 @@ class VideoEditor:
|
||||
return None
|
||||
|
||||
# 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:
|
||||
# Found template with start_frame > current_frame
|
||||
# Use the previous one (if it exists)
|
||||
@@ -2449,6 +2451,35 @@ class VideoEditor:
|
||||
template_index = self.get_template_for_frame(frame_number)
|
||||
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):
|
||||
"""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")
|
||||
return
|
||||
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:
|
||||
target = candidates[-1]
|
||||
print(f"DEBUG: Jump prev template from {current} -> {target}")
|
||||
@@ -2478,7 +2509,7 @@ class VideoEditor:
|
||||
print("DEBUG: No template markers; next jump ignored")
|
||||
return
|
||||
current = self.current_frame
|
||||
for start_frame, region in self.templates:
|
||||
for start_frame, region, template_image in self.templates:
|
||||
if start_frame > current:
|
||||
print(f"DEBUG: Jump next template from {current} -> {start_frame}")
|
||||
self.seek_to_frame(start_frame)
|
||||
@@ -2942,14 +2973,14 @@ class VideoEditor:
|
||||
)
|
||||
|
||||
# Draw template markers
|
||||
for start_frame, region in self.templates:
|
||||
for start_frame, region, template_image in self.templates:
|
||||
# Draw template start point
|
||||
start_progress = start_frame / max(1, self.total_frames - 1)
|
||||
start_x = bar_x_start + int(bar_width * start_progress)
|
||||
|
||||
# Template color (green for active, red for inactive)
|
||||
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
|
||||
|
||||
# Draw template start marker
|
||||
@@ -3421,7 +3452,7 @@ class VideoEditor:
|
||||
screen_x, screen_y = x, 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
|
||||
center_x = tx + tw // 2
|
||||
center_y = ty + th // 2
|
||||
|
Reference in New Issue
Block a user