reab5555 commited on
Commit
2e27102
·
verified ·
1 Parent(s): d02775c

Update visualization.py

Browse files
Files changed (1) hide show
  1. visualization.py +63 -82
visualization.py CHANGED
@@ -7,6 +7,7 @@ import numpy as np
7
  import pandas as pd
8
  import cv2
9
  from moviepy.editor import VideoFileClip, AudioFileClip, CompositeVideoClip
 
10
  from matplotlib.patches import Rectangle
11
  from utils import seconds_to_timecode
12
  from anomaly_detection import determine_anomalies
@@ -220,20 +221,16 @@ def create_video_with_heatmap(video_path, df, mse_embeddings, mse_posture, mse_v
220
  os.makedirs(output_folder, exist_ok=True)
221
 
222
  output_filename = os.path.basename(video_path).rsplit('.', 1)[0] + '_heatmap.mp4'
223
- temp_video_path = os.path.join(output_folder, 'temp_' + output_filename)
224
  heatmap_video_path = os.path.join(output_folder, output_filename)
225
 
226
  print(f"Heatmap video will be saved at: {heatmap_video_path}")
227
 
228
- cap = cv2.VideoCapture(video_path)
229
- original_fps = cap.get(cv2.CAP_PROP_FPS)
230
- width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
231
- height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
232
- total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
233
 
234
- fourcc = cv2.VideoWriter_fourcc(*'avc1')
235
- out = cv2.VideoWriter(temp_video_path, fourcc, original_fps, (width, height + 200))
236
- print(f"VideoWriter initialized. FPS: {original_fps}, Size: {(width, height + 200)}")
237
 
238
  # Ensure all MSE arrays have the same length as total_frames
239
  mse_embeddings = np.interp(np.linspace(0, len(mse_embeddings) - 1, total_frames),
@@ -269,84 +266,50 @@ def create_video_with_heatmap(video_path, df, mse_embeddings, mse_posture, mse_v
269
  ax.set_yticklabels(['Face', 'Posture', 'Voice'])
270
  ax.set_xticks([])
271
  plt.tight_layout()
272
-
273
- line = None
274
- try:
275
- for frame_count in range(total_frames):
276
- ret, frame = cap.read()
277
- if not ret:
278
- print(f"Failed to read frame {frame_count}")
279
- break
280
-
281
- if line:
282
- line.remove()
283
- line = ax.axvline(x=frame_count, color='r', linewidth=2)
284
-
285
- canvas = FigureCanvasAgg(fig)
286
- canvas.draw()
287
- heatmap_img = np.frombuffer(canvas.tostring_rgb(), dtype='uint8')
288
- heatmap_img = heatmap_img.reshape(canvas.get_width_height()[::-1] + (3,))
289
- heatmap_img = cv2.resize(heatmap_img, (width, 200))
290
-
291
- # Convert frame from BGR to RGB
292
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
293
-
294
- # Combine RGB frame with RGB heatmap
295
- combined_frame = np.vstack((frame_rgb, heatmap_img))
296
-
297
- seconds = frame_count / original_fps
298
- timecode = f"{int(seconds//3600):02d}:{int((seconds%3600)//60):02d}:{int(seconds%60):02d}"
299
-
300
- # Add timecode to the combined frame (which is now in RGB)
301
- combined_frame = cv2.putText(combined_frame, f"Time: {timecode}", (10, 30),
302
- cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
303
-
304
- # Convert back to BGR for OpenCV VideoWriter
305
- combined_frame_bgr = cv2.cvtColor(combined_frame, cv2.COLOR_RGB2BGR)
306
-
307
- out.write(combined_frame_bgr)
308
-
309
- if progress is not None:
310
- try:
311
- progress((frame_count + 1) / total_frames, desc="Generating video with heatmap")
312
- except Exception as e:
313
- print(f"Error updating progress: {str(e)}")
314
-
315
- except Exception as e:
316
- print(f"Error in frame processing: {str(e)}")
317
- import traceback
318
- traceback.print_exc()
319
- finally:
320
- cap.release()
321
- out.release()
322
- plt.close(fig)
323
-
324
- # Add audio to the video
325
- try:
326
- original_video = VideoFileClip(video_path)
327
- heatmap_video = VideoFileClip(temp_video_path)
328
 
329
- # Resize the heatmap video to match the original video's duration
330
- heatmap_video = heatmap_video.set_duration(original_video.duration)
 
 
331
 
332
- # Add the audio from the original video
333
- final_video = heatmap_video.set_audio(original_video.audio)
 
 
 
334
 
335
- # Write the final video
336
- final_video.write_videofile(heatmap_video_path, codec='libx264', audio_codec='aac')
337
 
338
- # Close the video clips
339
- original_video.close()
340
- heatmap_video.close()
341
- final_video.close()
342
 
343
- # Remove the temporary video file
344
- os.remove(temp_video_path)
 
 
 
 
345
 
346
- except Exception as e:
347
- print(f"Error in adding audio to video: {str(e)}")
348
- import traceback
349
- traceback.print_exc()
 
 
 
 
 
 
 
 
350
 
351
  if os.path.exists(heatmap_video_path):
352
  print(f"Heatmap video created at: {heatmap_video_path}")
@@ -354,4 +317,22 @@ def create_video_with_heatmap(video_path, df, mse_embeddings, mse_posture, mse_v
354
  return heatmap_video_path
355
  else:
356
  print(f"Failed to create heatmap video at: {heatmap_video_path}")
357
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  import pandas as pd
8
  import cv2
9
  from moviepy.editor import VideoFileClip, AudioFileClip, CompositeVideoClip
10
+ from moviepy.video.fx.all import resize
11
  from matplotlib.patches import Rectangle
12
  from utils import seconds_to_timecode
13
  from anomaly_detection import determine_anomalies
 
221
  os.makedirs(output_folder, exist_ok=True)
222
 
223
  output_filename = os.path.basename(video_path).rsplit('.', 1)[0] + '_heatmap.mp4'
 
224
  heatmap_video_path = os.path.join(output_folder, output_filename)
225
 
226
  print(f"Heatmap video will be saved at: {heatmap_video_path}")
227
 
228
+ # Load the original video
229
+ video = VideoFileClip(video_path)
 
 
 
230
 
231
+ # Get video properties
232
+ width, height = video.w, video.h
233
+ total_frames = int(video.duration * video.fps)
234
 
235
  # Ensure all MSE arrays have the same length as total_frames
236
  mse_embeddings = np.interp(np.linspace(0, len(mse_embeddings) - 1, total_frames),
 
266
  ax.set_yticklabels(['Face', 'Posture', 'Voice'])
267
  ax.set_xticks([])
268
  plt.tight_layout()
269
+
270
+ def make_frame(t):
271
+ frame_count = int(t * video.fps)
272
+
273
+ # Get the frame from the original video
274
+ frame = video.get_frame(t)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
276
+ # Update heatmap
277
+ if hasattr(ax, 'line'):
278
+ ax.line.remove()
279
+ ax.line = ax.axvline(x=frame_count, color='r', linewidth=2)
280
 
281
+ canvas = FigureCanvasAgg(fig)
282
+ canvas.draw()
283
+ heatmap_img = np.frombuffer(canvas.tostring_rgb(), dtype='uint8')
284
+ heatmap_img = heatmap_img.reshape(canvas.get_width_height()[::-1] + (3,))
285
+ heatmap_img = resize(ImageClip(heatmap_img), width=width).get_frame(0)
286
 
287
+ # Combine frame with heatmap
288
+ combined_frame = np.vstack((frame, heatmap_img))
289
 
290
+ # Add timecode
291
+ seconds = t
292
+ timecode = f"{int(seconds//3600):02d}:{int((seconds%3600)//60):02d}:{int(seconds%60):02d}"
 
293
 
294
+ # We'll use PIL for text as it's easier to work with in this context
295
+ from PIL import Image, ImageDraw, ImageFont
296
+ pil_img = Image.fromarray(combined_frame)
297
+ draw = ImageDraw.Draw(pil_img)
298
+ font = ImageFont.load_default()
299
+ draw.text((10, 30), f"Time: {timecode}", font=font, fill=(255, 255, 255))
300
 
301
+ return np.array(pil_img)
302
+
303
+ # Create the final video
304
+ final_clip = VideoFileClip(video_path).fl(make_frame)
305
+ final_clip = final_clip.set_duration(video.duration)
306
+
307
+ # Write the final video
308
+ final_clip.write_videofile(heatmap_video_path, codec='libx264', audio_codec='aac')
309
+
310
+ # Close the video clips
311
+ video.close()
312
+ final_clip.close()
313
 
314
  if os.path.exists(heatmap_video_path):
315
  print(f"Heatmap video created at: {heatmap_video_path}")
 
317
  return heatmap_video_path
318
  else:
319
  print(f"Failed to create heatmap video at: {heatmap_video_path}")
320
+ return None
321
+
322
+ This version of the function:
323
+
324
+ Uses MoviePy for all video operations, avoiding OpenCV codec issues.
325
+ Creates the heatmap for each frame on-the-fly.
326
+ Combines the original video frame with the heatmap.
327
+ Adds the timecode to each frame.
328
+ Preserves the original audio.
329
+
330
+ Make sure you have the necessary dependencies installed:
331
+
332
+ pip install moviepy Pillow matplotlib numpy
333
+
334
+ This approach should resolve the codec issues and create a video with the heatmap, original audio, and correct playback speed. If you still encounter any issues, please provide the new error message, and I'll be happy to help further.
335
+ Claude does not have the ability to run the code it generates yet.
336
+ Claude can make mistakes. Please double-check responses.
337
+
338
+