fix warping
Browse files
app.py
CHANGED
|
@@ -220,6 +220,7 @@ def stabilize_video_using_csv(video_file, csv_file, zoom=1.0, vertical_only=Fals
|
|
| 220 |
if not ret:
|
| 221 |
break
|
| 222 |
|
|
|
|
| 223 |
if zoom != 1.0:
|
| 224 |
zoomed_frame = cv2.resize(frame, None, fx=zoom, fy=zoom, interpolation=cv2.INTER_LINEAR)
|
| 225 |
zoomed_h, zoomed_w = zoomed_frame.shape[:2]
|
|
@@ -232,6 +233,7 @@ def stabilize_video_using_csv(video_file, csv_file, zoom=1.0, vertical_only=Fals
|
|
| 232 |
dx = 0 # Only vertical stabilization.
|
| 233 |
transform = np.array([[1, 0, dx],
|
| 234 |
[0, 1, dy]], dtype=np.float32)
|
|
|
|
| 235 |
stabilized_frame = cv2.warpAffine(frame, transform, (width, height), borderMode=cv2.BORDER_REPLICATE)
|
| 236 |
|
| 237 |
out.write(stabilized_frame)
|
|
@@ -252,7 +254,7 @@ def process_video_ai(video_file, zoom, vertical_only, compress_mode, target_widt
|
|
| 252 |
Gradio interface function:
|
| 253 |
- Optionally compresses the video if compress_mode is True, resizing it to the chosen resolution.
|
| 254 |
- Generates motion data from the (possibly compressed) video.
|
| 255 |
-
- If auto_zoom is enabled, computes the optimal zoom level based on the maximum cumulative
|
| 256 |
- Stabilizes the video based on the generated motion data.
|
| 257 |
- If vertical_only is True, only vertical stabilization is applied.
|
| 258 |
|
|
@@ -285,26 +287,23 @@ def process_video_ai(video_file, zoom, vertical_only, compress_mode, target_widt
|
|
| 285 |
csv_file = generate_motion_csv(video_file, progress=progress, progress_offset=motion_offset, progress_scale=motion_scale)
|
| 286 |
gr.Info("Motion CSV generated successfully.")
|
| 287 |
|
| 288 |
-
#
|
| 289 |
if auto_zoom:
|
| 290 |
gr.Info("Auto Zoom Mode enabled. Computing optimal zoom factor...")
|
| 291 |
motion_data = read_motion_csv(csv_file)
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
|
|
|
| 296 |
cap = cv2.VideoCapture(video_file)
|
| 297 |
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 298 |
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
| 299 |
cap.release()
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
else
|
| 303 |
-
|
| 304 |
-
if height - 2*max_dy > 0:
|
| 305 |
-
zoom_y = height / (height - 2*max_dy)
|
| 306 |
-
else:
|
| 307 |
-
zoom_y = 1.0
|
| 308 |
auto_zoom_factor = max(1.0, zoom_x, zoom_y)
|
| 309 |
gr.Info(f"Auto zoom factor computed: {auto_zoom_factor:.2f}")
|
| 310 |
zoom = auto_zoom_factor
|
|
|
|
| 220 |
if not ret:
|
| 221 |
break
|
| 222 |
|
| 223 |
+
# Apply zoom by resizing and then center-cropping
|
| 224 |
if zoom != 1.0:
|
| 225 |
zoomed_frame = cv2.resize(frame, None, fx=zoom, fy=zoom, interpolation=cv2.INTER_LINEAR)
|
| 226 |
zoomed_h, zoomed_w = zoomed_frame.shape[:2]
|
|
|
|
| 233 |
dx = 0 # Only vertical stabilization.
|
| 234 |
transform = np.array([[1, 0, dx],
|
| 235 |
[0, 1, dy]], dtype=np.float32)
|
| 236 |
+
# Use BORDER_REPLICATE to avoid black borders
|
| 237 |
stabilized_frame = cv2.warpAffine(frame, transform, (width, height), borderMode=cv2.BORDER_REPLICATE)
|
| 238 |
|
| 239 |
out.write(stabilized_frame)
|
|
|
|
| 254 |
Gradio interface function:
|
| 255 |
- Optionally compresses the video if compress_mode is True, resizing it to the chosen resolution.
|
| 256 |
- Generates motion data from the (possibly compressed) video.
|
| 257 |
+
- If auto_zoom is enabled, computes the optimal zoom level based on the maximum cumulative displacements.
|
| 258 |
- Stabilizes the video based on the generated motion data.
|
| 259 |
- If vertical_only is True, only vertical stabilization is applied.
|
| 260 |
|
|
|
|
| 287 |
csv_file = generate_motion_csv(video_file, progress=progress, progress_offset=motion_offset, progress_scale=motion_scale)
|
| 288 |
gr.Info("Motion CSV generated successfully.")
|
| 289 |
|
| 290 |
+
# Auto Zoom Mode: compute the optimal zoom factor to avoid black borders.
|
| 291 |
if auto_zoom:
|
| 292 |
gr.Info("Auto Zoom Mode enabled. Computing optimal zoom factor...")
|
| 293 |
motion_data = read_motion_csv(csv_file)
|
| 294 |
+
# Compute separate left/right and top/bottom displacements.
|
| 295 |
+
left_disp = abs(min(v[0] for v in motion_data.values()))
|
| 296 |
+
right_disp = max(v[0] for v in motion_data.values())
|
| 297 |
+
top_disp = abs(min(v[1] for v in motion_data.values()))
|
| 298 |
+
bottom_disp = max(v[1] for v in motion_data.values())
|
| 299 |
cap = cv2.VideoCapture(video_file)
|
| 300 |
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 301 |
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
| 302 |
cap.release()
|
| 303 |
+
safe_width = width - (left_disp + right_disp)
|
| 304 |
+
safe_height = height - (top_disp + bottom_disp)
|
| 305 |
+
zoom_x = width / safe_width if safe_width > 0 else 1.0
|
| 306 |
+
zoom_y = height / safe_height if safe_height > 0 else 1.0
|
|
|
|
|
|
|
|
|
|
|
|
|
| 307 |
auto_zoom_factor = max(1.0, zoom_x, zoom_y)
|
| 308 |
gr.Info(f"Auto zoom factor computed: {auto_zoom_factor:.2f}")
|
| 309 |
zoom = auto_zoom_factor
|