Update VideoEditor to manage template lifecycle and improve frame handling
This commit enhances the VideoEditor by implementing logic to end the previous template at the current frame when a new template is added. It also updates the method for retrieving the best template for a given frame to prioritize the most recent template. Additionally, a new method is introduced to recreate templates from their data region, ensuring templates are correctly initialized when needed. These changes improve template management and user feedback during video editing sessions.
This commit is contained in:
@@ -2432,6 +2432,11 @@ 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 the previous template at the current frame (if there is one)
|
||||||
|
if self.current_template_id is not None and self.current_template_id in self.templates:
|
||||||
|
self.templates[self.current_template_id]['end_frame'] = self.current_frame - 1
|
||||||
|
print(f"DEBUG: Ended previous template {self.current_template_id} at frame {self.current_frame - 1}")
|
||||||
|
|
||||||
self.templates[template_id] = {
|
self.templates[template_id] = {
|
||||||
'template': template.copy(),
|
'template': template.copy(),
|
||||||
'region': region,
|
'region': region,
|
||||||
@@ -2439,11 +2444,10 @@ class VideoEditor:
|
|||||||
'end_frame': end_frame
|
'end_frame': end_frame
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set as current template if it's the first one or if it covers current frame
|
# Set as current template
|
||||||
if self.current_template_id is None or (start_frame <= self.current_frame <= end_frame):
|
self.current_template_id = template_id
|
||||||
self.current_template_id = template_id
|
self.tracking_template = template.copy()
|
||||||
self.tracking_template = template.copy()
|
self.template_region = region
|
||||||
self.template_region = region
|
|
||||||
|
|
||||||
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
|
||||||
@@ -2462,9 +2466,9 @@ class VideoEditor:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def get_template_for_frame(self, frame_number):
|
def get_template_for_frame(self, frame_number):
|
||||||
"""Get the best template for a given frame number"""
|
"""Get the most recent template that covers this frame"""
|
||||||
|
# Find the most recent template (highest ID) that covers this frame
|
||||||
best_template_id = None
|
best_template_id = None
|
||||||
best_priority = -1
|
|
||||||
|
|
||||||
for template_id, template_data in self.templates.items():
|
for template_id, template_data in self.templates.items():
|
||||||
start_frame = template_data['start_frame']
|
start_frame = template_data['start_frame']
|
||||||
@@ -2472,21 +2476,29 @@ class VideoEditor:
|
|||||||
|
|
||||||
# Check if template covers this frame
|
# Check if template covers this frame
|
||||||
if start_frame <= frame_number <= end_frame:
|
if start_frame <= frame_number <= end_frame:
|
||||||
# Priority: templates that start earlier and end later are preferred
|
# Use the template with the highest ID (most recent)
|
||||||
priority = (end_frame - start_frame) - abs(frame_number - (start_frame + end_frame) // 2)
|
if best_template_id is None or template_id > best_template_id:
|
||||||
if priority > best_priority:
|
|
||||||
best_priority = priority
|
|
||||||
best_template_id = template_id
|
best_template_id = template_id
|
||||||
|
|
||||||
return best_template_id
|
return best_template_id
|
||||||
|
|
||||||
def _select_best_template_for_frame(self, frame_number):
|
def _select_best_template_for_frame(self, frame_number):
|
||||||
"""Select the best template for the current frame"""
|
"""Select the most recent template for the current frame"""
|
||||||
best_template_id = self.get_template_for_frame(frame_number)
|
best_template_id = self.get_template_for_frame(frame_number)
|
||||||
|
|
||||||
if best_template_id is not None:
|
if best_template_id is not None:
|
||||||
self.current_template_id = best_template_id
|
self.current_template_id = best_template_id
|
||||||
template_data = self.templates[best_template_id]
|
template_data = self.templates[best_template_id]
|
||||||
|
|
||||||
|
# Recreate template if it's None (loaded from state)
|
||||||
|
if template_data['template'] is None:
|
||||||
|
if self.current_display_frame is not None:
|
||||||
|
success = self._recreate_template_from_template_data(best_template_id, self.current_display_frame)
|
||||||
|
if not success:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
self.tracking_template = template_data['template'].copy()
|
self.tracking_template = template_data['template'].copy()
|
||||||
self.template_region = template_data['region']
|
self.template_region = template_data['region']
|
||||||
return True
|
return True
|
||||||
@@ -2496,6 +2508,31 @@ class VideoEditor:
|
|||||||
self.template_region = None
|
self.template_region = None
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _recreate_template_from_template_data(self, template_id, frame):
|
||||||
|
"""Recreate template from template data region"""
|
||||||
|
try:
|
||||||
|
template_data = self.templates[template_id]
|
||||||
|
x, y, w, h = template_data['region']
|
||||||
|
|
||||||
|
# Ensure region is within frame bounds
|
||||||
|
if (x >= 0 and y >= 0 and
|
||||||
|
x + w <= frame.shape[1] and
|
||||||
|
y + h <= frame.shape[0]):
|
||||||
|
|
||||||
|
# Extract template from frame
|
||||||
|
template = frame[y:y+h, x:x+w]
|
||||||
|
if template.size > 0:
|
||||||
|
self.templates[template_id]['template'] = template.copy()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error recreating template {template_id}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
def navigate_to_next_template(self):
|
def navigate_to_next_template(self):
|
||||||
"""Navigate to next template (; key)"""
|
"""Navigate to next template (; key)"""
|
||||||
if not self.templates:
|
if not self.templates:
|
||||||
|
Reference in New Issue
Block a user