File size: 1,968 Bytes
da07a7d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
import cv2
import numpy as np
import random
def extract_video_frames(video_path, n_frames=30, frame_size=(96, 96)):
"""
Simplified robust frame extractor for short videos (2-10 sec)
- Automatically handles varying video lengths
- Ensures consistent output shape
- Optimized for MP4/MPEG
"""
# Open video
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print(f"Error: Could not open video {video_path}")
return None
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
fps = cap.get(cv2.CAP_PROP_FPS)
# Basic video validation
if total_frames < 1 or fps < 1:
print(f"Error: Invalid video (frames:{total_frames}, fps:{fps})")
cap.release()
return None
# Calculate how many frames to skip (adaptive based on video length)
video_length = total_frames / fps
frame_step = max(1, int(total_frames / n_frames))
frames = []
last_good_frame = None
for i in range(n_frames):
# Calculate position to read (spread evenly across video)
pos = min(int(i * (total_frames / n_frames)), total_frames - 1)
cap.set(cv2.CAP_PROP_POS_FRAMES, pos)
ret, frame = cap.read()
# Fallback strategies if read fails
if not ret or frame is None:
if last_good_frame is not None:
frame = last_good_frame.copy()
else:
# Generate placeholder frame (light gray)
frame = np.full((*frame_size[::-1], 3), 0.8, dtype=np.float32)
else:
# Process valid frame
frame = cv2.resize(frame, frame_size)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame = frame.astype(np.float32) / 255.0
last_good_frame = frame
frames.append(frame)
cap.release()
return np.array(frames) |