Update .gitignore and enhance VideoEditor with improved crop handling and logging
This commit adds a new entry to the .gitignore file to exclude log files. In the VideoEditor class, it refines the crop position adjustment logic to calculate the center of the crop rectangle before applying offsets, ensuring more accurate positioning. Additionally, it enhances logging throughout the point transformation and tracking processes, providing better insights into the state of tracking points and their visibility relative to the crop area.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
croppa/build/lib
|
croppa/build/lib
|
||||||
croppa/croppa.egg-info
|
croppa/croppa.egg-info
|
||||||
|
*.log
|
||||||
|
@@ -1120,8 +1120,18 @@ class VideoEditor:
|
|||||||
|
|
||||||
# Only apply offset if it's not zero
|
# Only apply offset if it's not zero
|
||||||
if tracking_offset[0] != 0 or tracking_offset[1] != 0:
|
if tracking_offset[0] != 0 or tracking_offset[1] != 0:
|
||||||
x += int(tracking_offset[0])
|
# Calculate the center of the crop rect
|
||||||
y += int(tracking_offset[1])
|
center_x = x + w // 2
|
||||||
|
center_y = y + h // 2
|
||||||
|
|
||||||
|
# Apply offset to center
|
||||||
|
new_center_x = center_x + int(tracking_offset[0])
|
||||||
|
new_center_y = center_y + int(tracking_offset[1])
|
||||||
|
|
||||||
|
# Calculate new top-left corner
|
||||||
|
x = new_center_x - w // 2
|
||||||
|
y = new_center_y - h // 2
|
||||||
|
|
||||||
print(f"apply_crop_zoom_and_rotation: adjusted crop position to ({x}, {y})")
|
print(f"apply_crop_zoom_and_rotation: adjusted crop position to ({x}, {y})")
|
||||||
|
|
||||||
x, y, w, h = int(x), int(y), int(w), int(h)
|
x, y, w, h = int(x), int(y), int(w), int(h)
|
||||||
@@ -1192,7 +1202,6 @@ class VideoEditor:
|
|||||||
|
|
||||||
x, y = float(point[0]), float(point[1])
|
x, y = float(point[0]), float(point[1])
|
||||||
|
|
||||||
# Log original point
|
|
||||||
print(f"transform_point: original point ({x}, {y})")
|
print(f"transform_point: original point ({x}, {y})")
|
||||||
|
|
||||||
# Step 1: Apply crop (adjust point relative to crop origin)
|
# Step 1: Apply crop (adjust point relative to crop origin)
|
||||||
@@ -1200,8 +1209,7 @@ class VideoEditor:
|
|||||||
crop_x, crop_y, crop_w, crop_h = self.crop_rect
|
crop_x, crop_y, crop_w, crop_h = self.crop_rect
|
||||||
print(f"transform_point: crop_rect = {self.crop_rect}")
|
print(f"transform_point: crop_rect = {self.crop_rect}")
|
||||||
|
|
||||||
# Check if point is inside the crop area - but don't filter out points
|
# Check if point is inside the crop area
|
||||||
# We'll still transform them and let the drawing code decide visibility
|
|
||||||
is_inside = (crop_x <= x < crop_x + crop_w and crop_y <= y < crop_y + crop_h)
|
is_inside = (crop_x <= x < crop_x + crop_w and crop_y <= y < crop_y + crop_h)
|
||||||
print(f"transform_point: point ({x}, {y}) is {'inside' if is_inside else 'outside'} crop area")
|
print(f"transform_point: point ({x}, {y}) is {'inside' if is_inside else 'outside'} crop area")
|
||||||
|
|
||||||
@@ -1214,10 +1222,11 @@ class VideoEditor:
|
|||||||
if self.rotation_angle != 0:
|
if self.rotation_angle != 0:
|
||||||
# Get dimensions after crop
|
# Get dimensions after crop
|
||||||
if self.crop_rect:
|
if self.crop_rect:
|
||||||
crop_w, crop_h = self.crop_rect[2], self.crop_rect[3]
|
crop_w, crop_h = float(self.crop_rect[2]), float(self.crop_rect[3])
|
||||||
else:
|
else:
|
||||||
if self.current_display_frame is not None:
|
if self.current_display_frame is not None:
|
||||||
crop_h, crop_w = self.current_display_frame.shape[:2]
|
crop_h, crop_w = self.current_display_frame.shape[:2]
|
||||||
|
crop_h, crop_w = float(crop_h), float(crop_w)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -1306,14 +1315,8 @@ class VideoEditor:
|
|||||||
y += crop_y
|
y += crop_y
|
||||||
print(f"untransform_point: after reverse crop ({x}, {y}), crop_rect = {self.crop_rect}")
|
print(f"untransform_point: after reverse crop ({x}, {y}), crop_rect = {self.crop_rect}")
|
||||||
|
|
||||||
# Ensure coordinates are within the frame bounds
|
# Don't clamp coordinates - allow points outside frame bounds
|
||||||
if self.current_display_frame is not None:
|
# This is important for tracking points that may be outside the current crop
|
||||||
height, width = self.current_display_frame.shape[:2]
|
|
||||||
orig_x, orig_y = x, y
|
|
||||||
x = max(0, min(width - 1, x))
|
|
||||||
y = max(0, min(height - 1, y))
|
|
||||||
if orig_x != x or orig_y != y:
|
|
||||||
print(f"untransform_point: clamped from ({orig_x}, {orig_y}) to ({x}, {y})")
|
|
||||||
|
|
||||||
print(f"untransform_point: final result = ({x}, {y})")
|
print(f"untransform_point: final result = ({x}, {y})")
|
||||||
return (x, y)
|
return (x, y)
|
||||||
@@ -1495,11 +1498,14 @@ class VideoEditor:
|
|||||||
tracking_points = self.motion_tracker.get_tracking_points_for_frame(self.current_frame)
|
tracking_points = self.motion_tracker.get_tracking_points_for_frame(self.current_frame)
|
||||||
print(f"draw_tracking_points: found {len(tracking_points)} tracking points for frame {self.current_frame}")
|
print(f"draw_tracking_points: found {len(tracking_points)} tracking points for frame {self.current_frame}")
|
||||||
|
|
||||||
|
# Get current frame dimensions for bounds checking
|
||||||
|
frame_height, frame_width = self.current_display_frame.shape[:2]
|
||||||
|
|
||||||
for i, point in enumerate(tracking_points):
|
for i, point in enumerate(tracking_points):
|
||||||
print(f"draw_tracking_points: processing point {i}: {point}")
|
print(f"draw_tracking_points: processing point {i}: {point}")
|
||||||
|
|
||||||
# Transform point from original frame coordinates to display coordinates
|
# Check if the point is within the frame bounds
|
||||||
display_point = self.transform_point(point)
|
is_in_frame = (0 <= point[0] < frame_width and 0 <= point[1] < frame_height)
|
||||||
|
|
||||||
# Check if the point is within the crop area (if cropping is active)
|
# Check if the point is within the crop area (if cropping is active)
|
||||||
is_in_crop = True
|
is_in_crop = True
|
||||||
@@ -1508,7 +1514,10 @@ class VideoEditor:
|
|||||||
is_in_crop = (crop_x <= point[0] < crop_x + crop_w and
|
is_in_crop = (crop_x <= point[0] < crop_x + crop_w and
|
||||||
crop_y <= point[1] < crop_y + crop_h)
|
crop_y <= point[1] < crop_y + crop_h)
|
||||||
|
|
||||||
if display_point:
|
# Transform point from original frame coordinates to display coordinates
|
||||||
|
display_point = self.transform_point(point)
|
||||||
|
|
||||||
|
if display_point is not None:
|
||||||
print(f"draw_tracking_points: point {i} transformed to {display_point}")
|
print(f"draw_tracking_points: point {i} transformed to {display_point}")
|
||||||
|
|
||||||
# Scale and offset the point to match the canvas
|
# Scale and offset the point to match the canvas
|
||||||
@@ -1517,6 +1526,10 @@ class VideoEditor:
|
|||||||
|
|
||||||
print(f"draw_tracking_points: point {i} canvas position: ({x},{y})")
|
print(f"draw_tracking_points: point {i} canvas position: ({x},{y})")
|
||||||
|
|
||||||
|
# Check if the point is within the canvas bounds
|
||||||
|
is_on_canvas = (0 <= x < self.window_width and 0 <= y < self.window_height)
|
||||||
|
|
||||||
|
if is_on_canvas:
|
||||||
# Draw the point - use different colors based on whether it's in the crop area
|
# Draw the point - use different colors based on whether it's in the crop area
|
||||||
if is_in_crop:
|
if is_in_crop:
|
||||||
# Point is in crop area - draw normally
|
# Point is in crop area - draw normally
|
||||||
@@ -1525,11 +1538,13 @@ class VideoEditor:
|
|||||||
# Draw green circle
|
# Draw green circle
|
||||||
cv2.circle(canvas, (x, y), self.tracking_point_radius, (0, 255, 0), -1)
|
cv2.circle(canvas, (x, y), self.tracking_point_radius, (0, 255, 0), -1)
|
||||||
else:
|
else:
|
||||||
# Point is outside crop area - draw with different color (semi-transparent)
|
# Point is outside crop area - draw with different color
|
||||||
# Draw gray border
|
# Draw gray border
|
||||||
cv2.circle(canvas, (x, y), self.tracking_point_radius + 2, (128, 128, 128), 2)
|
cv2.circle(canvas, (x, y), self.tracking_point_radius + 2, (128, 128, 128), 2)
|
||||||
# Draw yellow circle
|
# Draw yellow circle
|
||||||
cv2.circle(canvas, (x, y), self.tracking_point_radius, (0, 255, 255), -1)
|
cv2.circle(canvas, (x, y), self.tracking_point_radius, (0, 255, 255), -1)
|
||||||
|
else:
|
||||||
|
print(f"draw_tracking_points: point {i} is outside canvas bounds")
|
||||||
else:
|
else:
|
||||||
print(f"draw_tracking_points: point {i} not visible in current view")
|
print(f"draw_tracking_points: point {i} not visible in current view")
|
||||||
|
|
||||||
@@ -2112,6 +2127,8 @@ class VideoEditor:
|
|||||||
start_x = (self.window_width - final_display_width) // 2
|
start_x = (self.window_width - final_display_width) // 2
|
||||||
start_y = (available_height - final_display_height) // 2
|
start_y = (available_height - final_display_height) // 2
|
||||||
|
|
||||||
|
print(f"mouse_callback: right-click at ({x}, {y}), display frame at ({start_x}, {start_y}), scale={scale}")
|
||||||
|
|
||||||
# Check if click is within the frame area
|
# Check if click is within the frame area
|
||||||
if (start_x <= x < start_x + final_display_width and
|
if (start_x <= x < start_x + final_display_width and
|
||||||
start_y <= y < start_y + final_display_height):
|
start_y <= y < start_y + final_display_height):
|
||||||
@@ -2120,9 +2137,13 @@ class VideoEditor:
|
|||||||
display_x = (x - start_x) / scale
|
display_x = (x - start_x) / scale
|
||||||
display_y = (y - start_y) / scale
|
display_y = (y - start_y) / scale
|
||||||
|
|
||||||
|
print(f"mouse_callback: converted to display coords ({display_x}, {display_y})")
|
||||||
|
|
||||||
# Now convert display coordinates to original frame coordinates
|
# Now convert display coordinates to original frame coordinates
|
||||||
original_point = self.untransform_point((display_x, display_y))
|
original_point = self.untransform_point((display_x, display_y))
|
||||||
|
|
||||||
|
print(f"mouse_callback: untransformed to original coords {original_point}")
|
||||||
|
|
||||||
if original_point:
|
if original_point:
|
||||||
# Check if clicking on an existing tracking point to remove it
|
# Check if clicking on an existing tracking point to remove it
|
||||||
removed = self.motion_tracker.remove_tracking_point(
|
removed = self.motion_tracker.remove_tracking_point(
|
||||||
@@ -2132,13 +2153,16 @@ class VideoEditor:
|
|||||||
self.tracking_point_distance
|
self.tracking_point_distance
|
||||||
)
|
)
|
||||||
|
|
||||||
if not removed:
|
if removed:
|
||||||
|
print(f"mouse_callback: removed tracking point at {original_point}")
|
||||||
|
else:
|
||||||
# If no point was removed, add a new tracking point
|
# If no point was removed, add a new tracking point
|
||||||
self.motion_tracker.add_tracking_point(
|
self.motion_tracker.add_tracking_point(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
original_point[0],
|
original_point[0],
|
||||||
original_point[1]
|
original_point[1]
|
||||||
)
|
)
|
||||||
|
print(f"mouse_callback: added tracking point at {original_point}")
|
||||||
|
|
||||||
# Save state when tracking points change
|
# Save state when tracking points change
|
||||||
self.save_state()
|
self.save_state()
|
||||||
@@ -3115,7 +3139,6 @@ class VideoEditor:
|
|||||||
if self.motion_tracker.tracking_enabled:
|
if self.motion_tracker.tracking_enabled:
|
||||||
self.motion_tracker.stop_tracking()
|
self.motion_tracker.stop_tracking()
|
||||||
print("Motion tracking disabled")
|
print("Motion tracking disabled")
|
||||||
print("Motion tracking disabled")
|
|
||||||
else:
|
else:
|
||||||
# If we have tracking points, start tracking
|
# If we have tracking points, start tracking
|
||||||
if self.motion_tracker.has_tracking_points():
|
if self.motion_tracker.has_tracking_points():
|
||||||
@@ -3123,24 +3146,17 @@ class VideoEditor:
|
|||||||
current_pos = self.motion_tracker.get_interpolated_position(self.current_frame)
|
current_pos = self.motion_tracker.get_interpolated_position(self.current_frame)
|
||||||
print(f"Toggle tracking: interpolated position = {current_pos}")
|
print(f"Toggle tracking: interpolated position = {current_pos}")
|
||||||
|
|
||||||
# Use crop center if we have a crop rect
|
# Always use the current position as the base zoom center if available
|
||||||
if self.crop_rect:
|
|
||||||
x, y, w, h = self.crop_rect
|
|
||||||
crop_center = (x + w//2, y + h//2)
|
|
||||||
print(f"Toggle tracking: crop_rect = {self.crop_rect}, crop_center = {crop_center}")
|
|
||||||
|
|
||||||
# If we have a current position from tracking points, use that as base
|
|
||||||
if current_pos:
|
if current_pos:
|
||||||
# The base zoom center is the current position
|
|
||||||
base_zoom_center = current_pos
|
base_zoom_center = current_pos
|
||||||
print(f"Toggle tracking: using interpolated position as base: {base_zoom_center}")
|
print(f"Toggle tracking: using interpolated position as base: {base_zoom_center}")
|
||||||
else:
|
# Use crop center if we have a crop rect
|
||||||
# Use crop center as fallback
|
elif self.crop_rect:
|
||||||
base_zoom_center = crop_center
|
x, y, w, h = self.crop_rect
|
||||||
|
base_zoom_center = (x + w//2, y + h//2)
|
||||||
print(f"Toggle tracking: using crop center as base: {base_zoom_center}")
|
print(f"Toggle tracking: using crop center as base: {base_zoom_center}")
|
||||||
else:
|
|
||||||
# No crop rect, use frame center
|
# No crop rect, use frame center
|
||||||
if self.current_display_frame is not None:
|
elif self.current_display_frame is not None:
|
||||||
h, w = self.current_display_frame.shape[:2]
|
h, w = self.current_display_frame.shape[:2]
|
||||||
base_zoom_center = (w // 2, h // 2)
|
base_zoom_center = (w // 2, h // 2)
|
||||||
print(f"Toggle tracking: using frame center as base: {base_zoom_center}")
|
print(f"Toggle tracking: using frame center as base: {base_zoom_center}")
|
||||||
@@ -3148,8 +3164,10 @@ class VideoEditor:
|
|||||||
base_zoom_center = None
|
base_zoom_center = None
|
||||||
print("Toggle tracking: no base center available")
|
print("Toggle tracking: no base center available")
|
||||||
|
|
||||||
# Create a crop rect if one doesn't exist
|
# Use current crop rect as base
|
||||||
base_crop_rect = self.crop_rect
|
base_crop_rect = self.crop_rect
|
||||||
|
|
||||||
|
# Create a crop rect if one doesn't exist
|
||||||
if not base_crop_rect and current_pos and self.current_display_frame is not None:
|
if not base_crop_rect and current_pos and self.current_display_frame is not None:
|
||||||
# Create a default crop rect centered on the current position
|
# Create a default crop rect centered on the current position
|
||||||
h, w = self.current_display_frame.shape[:2]
|
h, w = self.current_display_frame.shape[:2]
|
||||||
@@ -3157,6 +3175,8 @@ class VideoEditor:
|
|||||||
x = max(0, int(current_pos[0] - crop_size // 2))
|
x = max(0, int(current_pos[0] - crop_size // 2))
|
||||||
y = max(0, int(current_pos[1] - crop_size // 2))
|
y = max(0, int(current_pos[1] - crop_size // 2))
|
||||||
base_crop_rect = (x, y, crop_size, crop_size)
|
base_crop_rect = (x, y, crop_size, crop_size)
|
||||||
|
# Update the actual crop rect
|
||||||
|
self.crop_rect = base_crop_rect
|
||||||
print(f"Toggle tracking: created default crop rect: {base_crop_rect}")
|
print(f"Toggle tracking: created default crop rect: {base_crop_rect}")
|
||||||
|
|
||||||
self.motion_tracker.start_tracking(
|
self.motion_tracker.start_tracking(
|
||||||
@@ -3164,10 +3184,8 @@ class VideoEditor:
|
|||||||
base_zoom_center
|
base_zoom_center
|
||||||
)
|
)
|
||||||
print("Motion tracking enabled")
|
print("Motion tracking enabled")
|
||||||
print(f"Motion tracking enabled with base_crop_rect={base_crop_rect}, base_zoom_center={base_zoom_center}")
|
|
||||||
else:
|
else:
|
||||||
print("No tracking points available. Add tracking points with right-click first.")
|
print("No tracking points available. Add tracking points with right-click first.")
|
||||||
print("Motion tracking not enabled - no tracking points available")
|
|
||||||
self.save_state()
|
self.save_state()
|
||||||
else: # V - Clear all tracking points
|
else: # V - Clear all tracking points
|
||||||
self.motion_tracker.clear_tracking_points()
|
self.motion_tracker.clear_tracking_points()
|
||||||
|
@@ -137,12 +137,16 @@ class MotionTracker:
|
|||||||
self.tracking_enabled = True
|
self.tracking_enabled = True
|
||||||
self.base_crop_rect = base_crop_rect
|
self.base_crop_rect = base_crop_rect
|
||||||
|
|
||||||
|
print(f"start_tracking: base_crop_rect={base_crop_rect}, base_zoom_center={base_zoom_center}")
|
||||||
|
|
||||||
# If no base_zoom_center is provided, use the center of the crop rect
|
# If no base_zoom_center is provided, use the center of the crop rect
|
||||||
if base_zoom_center is None and base_crop_rect is not None:
|
if base_zoom_center is None and base_crop_rect is not None:
|
||||||
x, y, w, h = base_crop_rect
|
x, y, w, h = base_crop_rect
|
||||||
self.base_zoom_center = (x + w//2, y + h//2)
|
self.base_zoom_center = (x + w//2, y + h//2)
|
||||||
|
print(f"start_tracking: using crop center as base_zoom_center: {self.base_zoom_center}")
|
||||||
else:
|
else:
|
||||||
self.base_zoom_center = base_zoom_center
|
self.base_zoom_center = base_zoom_center
|
||||||
|
print(f"start_tracking: using provided base_zoom_center: {self.base_zoom_center}")
|
||||||
|
|
||||||
def stop_tracking(self):
|
def stop_tracking(self):
|
||||||
"""Stop motion tracking"""
|
"""Stop motion tracking"""
|
||||||
|
Reference in New Issue
Block a user