Enhance feature tracking with smooth interpolation and center calculation
This commit improves the feature tracking logic in the VideoEditor by implementing smooth interpolation between feature positions across frames. It introduces methods to calculate the center of features for a given frame, ensuring a more fluid tracking experience. These enhancements provide better continuity in feature tracking, particularly when features are sparse, and improve overall user experience.
This commit is contained in:
@@ -1620,13 +1620,25 @@ class VideoEditor:
|
|||||||
|
|
||||||
def _get_interpolated_tracking_position(self, frame_number):
|
def _get_interpolated_tracking_position(self, frame_number):
|
||||||
"""Linear interpolation in ROTATED frame coords. Returns (rx, ry) or None."""
|
"""Linear interpolation in ROTATED frame coords. Returns (rx, ry) or None."""
|
||||||
# First try feature tracking if enabled
|
# First try feature tracking if enabled - but use smooth interpolation instead of averaging
|
||||||
if self.feature_tracker.tracking_enabled:
|
if self.feature_tracker.tracking_enabled:
|
||||||
feature_pos = self.feature_tracker.get_tracking_position(frame_number)
|
# Get the nearest frames with features for smooth interpolation
|
||||||
if feature_pos:
|
feature_frames = sorted(self.feature_tracker.features.keys())
|
||||||
# Features are stored in rotated frame coordinates (like existing motion tracking)
|
if feature_frames:
|
||||||
# We can use them directly for the tracking system
|
# Find the two nearest frames for interpolation
|
||||||
return (feature_pos[0], feature_pos[1])
|
if frame_number <= feature_frames[0]:
|
||||||
|
# Before first feature frame - use first frame
|
||||||
|
return self._get_feature_center(feature_frames[0])
|
||||||
|
elif frame_number >= feature_frames[-1]:
|
||||||
|
# After last feature frame - use last frame
|
||||||
|
return self._get_feature_center(feature_frames[-1])
|
||||||
|
else:
|
||||||
|
# Between two feature frames - interpolate smoothly
|
||||||
|
for i in range(len(feature_frames) - 1):
|
||||||
|
if feature_frames[i] <= frame_number <= feature_frames[i + 1]:
|
||||||
|
return self._interpolate_feature_positions(
|
||||||
|
feature_frames[i], feature_frames[i + 1], frame_number
|
||||||
|
)
|
||||||
|
|
||||||
# Fall back to manual tracking points
|
# Fall back to manual tracking points
|
||||||
if not self.tracking_points:
|
if not self.tracking_points:
|
||||||
@@ -2036,6 +2048,37 @@ class VideoEditor:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error filling all gaps: {e}")
|
print(f"Error filling all gaps: {e}")
|
||||||
|
|
||||||
|
def _get_feature_center(self, frame_number):
|
||||||
|
"""Get the center of features for a frame (smooth, not jarring)"""
|
||||||
|
if frame_number not in self.feature_tracker.features:
|
||||||
|
return None
|
||||||
|
|
||||||
|
positions = self.feature_tracker.features[frame_number]['positions']
|
||||||
|
if not positions:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Calculate center of mass (smoother than average)
|
||||||
|
center_x = sum(pos[0] for pos in positions) / len(positions)
|
||||||
|
center_y = sum(pos[1] for pos in positions) / len(positions)
|
||||||
|
|
||||||
|
return (center_x, center_y)
|
||||||
|
|
||||||
|
def _interpolate_feature_positions(self, start_frame, end_frame, target_frame):
|
||||||
|
"""Smoothly interpolate between feature centers of two frames"""
|
||||||
|
start_center = self._get_feature_center(start_frame)
|
||||||
|
end_center = self._get_feature_center(end_frame)
|
||||||
|
|
||||||
|
if not start_center or not end_center:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Linear interpolation between centers
|
||||||
|
alpha = (target_frame - start_frame) / (end_frame - start_frame)
|
||||||
|
|
||||||
|
interp_x = start_center[0] + alpha * (end_center[0] - start_center[0])
|
||||||
|
interp_y = start_center[1] + alpha * (end_center[1] - start_center[1])
|
||||||
|
|
||||||
|
return (interp_x, interp_y)
|
||||||
|
|
||||||
|
|
||||||
def apply_rotation(self, frame):
|
def apply_rotation(self, frame):
|
||||||
|
Reference in New Issue
Block a user