NihalGazi commited on
Commit
73e6bc5
·
verified ·
1 Parent(s): 34603a5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -17
app.py CHANGED
@@ -9,6 +9,9 @@ import ffmpeg
9
  def extract_frames(video_path):
10
  """
11
  Extracts all frames from the input video.
 
 
 
12
  """
13
  cap = cv2.VideoCapture(video_path)
14
  frames = []
@@ -23,8 +26,13 @@ def extract_frames(video_path):
23
 
24
  def apply_style_propagation(frames, style_image_path):
25
  """
26
- Applies the style from the provided image to all frames via optical flow warping.
27
- Also clips remapping coordinates to avoid out-of-bound values.
 
 
 
 
 
28
  """
29
  style_image = cv2.imread(style_image_path)
30
  if style_image is None:
@@ -33,7 +41,6 @@ def apply_style_propagation(frames, style_image_path):
33
  h, w = frames[0].shape[:2]
34
  style_image = cv2.resize(style_image, (w, h))
35
 
36
- # The first styled frame is the style image.
37
  styled_frames = [style_image]
38
  prev_gray = cv2.cvtColor(frames[0], cv2.COLOR_BGR2GRAY)
39
 
@@ -47,7 +54,7 @@ def apply_style_propagation(frames, style_image_path):
47
  grid_x, grid_y = np.meshgrid(np.arange(w), np.arange(h))
48
  map_x = grid_x + flow[..., 0]
49
  map_y = grid_y + flow[..., 1]
50
- # Clip coordinates to avoid accessing invalid pixels.
51
  map_x = np.clip(map_x, 0, w - 1).astype(np.float32)
52
  map_y = np.clip(map_y, 0, h - 1).astype(np.float32)
53
 
@@ -56,7 +63,6 @@ def apply_style_propagation(frames, style_image_path):
56
  prev_gray = curr_gray
57
 
58
  print(f"Propagated style to {len(styled_frames)} frames.")
59
- # Debug: show a sample frame's mean pixel intensity.
60
  sample_frame = styled_frames[len(styled_frames) // 2]
61
  print(f"Sample styled frame mean intensity: {np.mean(sample_frame):.2f}")
62
  return styled_frames
@@ -64,6 +70,8 @@ def apply_style_propagation(frames, style_image_path):
64
  def save_video_cv2(frames, output_path, fps=30):
65
  """
66
  Saves a list of frames as a video using OpenCV.
 
 
67
  """
68
  h, w, _ = frames[0].shape
69
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
@@ -74,13 +82,23 @@ def save_video_cv2(frames, output_path, fps=30):
74
  size = os.path.getsize(output_path)
75
  print(f"Intermediate video saved to {output_path} (size: {size} bytes)")
76
 
77
- def process_video(video_file, style_image_file, fps=30):
78
  """
79
- Processes the input video using the provided style image.
80
- Then re-encodes the output video with FFmpeg for web compatibility.
81
- Returns the path to the final video.
 
 
 
 
 
 
 
 
 
 
82
  """
83
- # Get the video file path.
84
  video_path = video_file if isinstance(video_file, str) else video_file["name"]
85
 
86
  # Process the style image input.
@@ -95,17 +113,27 @@ def process_video(video_file, style_image_file, fps=30):
95
  else:
96
  return "Error: Unsupported style image format."
97
 
98
- # Extract frames from the video.
99
  frames = extract_frames(video_path)
100
  if not frames:
101
  return "Error: No frames extracted from the video."
102
 
 
 
 
 
 
 
 
 
 
 
103
  # Propagate style.
104
  styled_frames = apply_style_propagation(frames, style_image_path)
105
 
106
  # Save intermediate video using OpenCV to a named temporary file.
107
  temp_video_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
108
- temp_video_file.close() # Close so that OpenCV can write to this file.
109
  temp_video_path = temp_video_file.name
110
  save_video_cv2(styled_frames, temp_video_path, fps=fps)
111
 
@@ -140,14 +168,17 @@ iface = gr.Interface(
140
  inputs=[
141
  gr.Video(label="Input Video (v.mp4)"),
142
  gr.Image(label="Stylized Keyframe (a.jpeg)"),
143
- gr.Slider(minimum=1, maximum=60, step=1, value=30, label="Output FPS")
 
 
144
  ],
145
  outputs=gr.Video(label="Styled Video"),
146
- title="Optical Flow Style Propagation",
147
  description=(
148
- "Upload a video and a stylized keyframe image. The style from the keyframe is propagated "
149
- "across the video using optical flow and warping. The resulting video is re-encoded to be "
150
- "web-friendly."
 
151
  )
152
  )
153
 
 
9
  def extract_frames(video_path):
10
  """
11
  Extracts all frames from the input video.
12
+ Logic:
13
+ - Open the video file using cv2.VideoCapture.
14
+ - Read frames until the video ends.
15
  """
16
  cap = cv2.VideoCapture(video_path)
17
  frames = []
 
26
 
27
  def apply_style_propagation(frames, style_image_path):
28
  """
29
+ Applies the style from the provided image to each video frame using optical flow.
30
+ Logic:
31
+ - Load and resize the style image to match the frame dimensions.
32
+ - Use the style image as the first styled frame.
33
+ - For each subsequent frame, compute dense optical flow between consecutive frames.
34
+ - Warp the previously styled frame using the computed flow.
35
+ - Clip mapping coordinates to avoid out-of-bound values.
36
  """
37
  style_image = cv2.imread(style_image_path)
38
  if style_image is None:
 
41
  h, w = frames[0].shape[:2]
42
  style_image = cv2.resize(style_image, (w, h))
43
 
 
44
  styled_frames = [style_image]
45
  prev_gray = cv2.cvtColor(frames[0], cv2.COLOR_BGR2GRAY)
46
 
 
54
  grid_x, grid_y = np.meshgrid(np.arange(w), np.arange(h))
55
  map_x = grid_x + flow[..., 0]
56
  map_y = grid_y + flow[..., 1]
57
+ # Clip mapping coordinates to valid pixel indices.
58
  map_x = np.clip(map_x, 0, w - 1).astype(np.float32)
59
  map_y = np.clip(map_y, 0, h - 1).astype(np.float32)
60
 
 
63
  prev_gray = curr_gray
64
 
65
  print(f"Propagated style to {len(styled_frames)} frames.")
 
66
  sample_frame = styled_frames[len(styled_frames) // 2]
67
  print(f"Sample styled frame mean intensity: {np.mean(sample_frame):.2f}")
68
  return styled_frames
 
70
  def save_video_cv2(frames, output_path, fps=30):
71
  """
72
  Saves a list of frames as a video using OpenCV.
73
+ Logic:
74
+ - Use cv2.VideoWriter with codec 'mp4v' to create a temporary video file.
75
  """
76
  h, w, _ = frames[0].shape
77
  fourcc = cv2.VideoWriter_fourcc(*'mp4v')
 
82
  size = os.path.getsize(output_path)
83
  print(f"Intermediate video saved to {output_path} (size: {size} bytes)")
84
 
85
+ def process_video(video_file, style_image_file, fps=30, target_width=0, target_height=0):
86
  """
87
+ Processes the input video by applying the style image via optical flow,
88
+ optionally downscaling the video and style image to a specified resolution.
89
+ Then re-encodes the video with FFmpeg for web compatibility.
90
+
91
+ Inputs:
92
+ - video_file: The input video file.
93
+ - style_image_file: The stylized keyframe image.
94
+ - fps: Output frames per second.
95
+ - target_width: Target width for downscaling (0 means no downscale).
96
+ - target_height: Target height for downscaling (0 means no downscale).
97
+
98
+ Returns:
99
+ - Path to the final, web-playable video.
100
  """
101
+ # Determine video file path.
102
  video_path = video_file if isinstance(video_file, str) else video_file["name"]
103
 
104
  # Process the style image input.
 
113
  else:
114
  return "Error: Unsupported style image format."
115
 
116
+ # Extract frames from the input video.
117
  frames = extract_frames(video_path)
118
  if not frames:
119
  return "Error: No frames extracted from the video."
120
 
121
+ original_h, original_w = frames[0].shape[:2]
122
+ print(f"Original video resolution: {original_w}x{original_h}")
123
+
124
+ # Downscale if target dimensions are provided (non-zero).
125
+ if target_width > 0 and target_height > 0:
126
+ print(f"Downscaling frames to resolution: {target_width}x{target_height}")
127
+ frames = [cv2.resize(frame, (target_width, target_height)) for frame in frames]
128
+ else:
129
+ print("No downscaling applied. Using original resolution.")
130
+
131
  # Propagate style.
132
  styled_frames = apply_style_propagation(frames, style_image_path)
133
 
134
  # Save intermediate video using OpenCV to a named temporary file.
135
  temp_video_file = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
136
+ temp_video_file.close() # Close so OpenCV can write to this file.
137
  temp_video_path = temp_video_file.name
138
  save_video_cv2(styled_frames, temp_video_path, fps=fps)
139
 
 
168
  inputs=[
169
  gr.Video(label="Input Video (v.mp4)"),
170
  gr.Image(label="Stylized Keyframe (a.jpeg)"),
171
+ gr.Slider(minimum=1, maximum=60, step=1, value=30, label="Output FPS"),
172
+ gr.Slider(minimum=0, maximum=1920, step=1, value=0, label="Target Width (0 for original)"),
173
+ gr.Slider(minimum=0, maximum=1080, step=1, value=0, label="Target Height (0 for original)")
174
  ],
175
  outputs=gr.Video(label="Styled Video"),
176
+ title="Optical Flow Style Propagation with Optional Downscaling",
177
  description=(
178
+ "Upload a video and a stylized keyframe image. Optionally downscale both to a target resolution "
179
+ "by specifying width and height (set both to 0 for original resolution). "
180
+ "The style from the keyframe is propagated across the video using optical flow and warping. "
181
+ "The output video is re-encoded for web compatibility."
182
  )
183
  )
184