You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV与Python的动作识别:等帧数视频帧提取方案咨询

Hey there! I’ve worked on similar action recognition pipelines before, so I can share a practical, straightforward approach to extract an equal number of frames from videos of varying lengths using OpenCV and Python.

Core Idea

The key is to sample frames uniformly across the entire duration of the video. For longer videos, we calculate a skip interval so that we pick frames spread evenly from start to finish. For shorter videos that have fewer frames than your target n, we can either take all available frames and repeat the last few to hit n, or adjust based on your project needs.

Step-by-Step Implementation

1. Get Video Metadata

First, we need to fetch the total number of frames in the video using OpenCV’s VideoCapture class. This helps us calculate how often we should skip frames.

2. Calculate Sampling Interval

If the total frames are greater than or equal to your target n, compute the interval as total_frames // n. If there are fewer frames than n, we’ll take every frame and pad with duplicates if needed.

3. Extract and Save Frames

Loop through the video, saving frames at the calculated intervals.

Here’s a basic working code example:

import cv2
import os

def extract_equal_frames(video_path, output_dir, num_frames=10):
    # Create output directory if it doesn't exist
    os.makedirs(output_dir, exist_ok=True)
    
    # Initialize video capture
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print(f"Error: Failed to open video file {video_path}")
        return
    
    # Get total number of frames in the video
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    # Calculate frame skip interval (ensure we don't skip 0 frames)
    skip_interval = max(total_frames // num_frames, 1)
    
    frame_idx = 0
    saved_frames = 0
    last_saved_frame = None
    
    while saved_frames < num_frames:
        ret, frame = cap.read()
        
        if not ret:
            # If video ends before we collect n frames, repeat the last saved frame
            if last_saved_frame is not None:
                frame = last_saved_frame
            else:
                print(f"Error: No frames could be read from {video_path}")
                break
        
        # Save frame if it's at the skip interval, or if we're short on frames
        if frame_idx % skip_interval == 0 or saved_frames >= total_frames:
            output_path = os.path.join(output_dir, f"frame_{saved_frames:04d}.jpg")
            cv2.imwrite(output_path, frame)
            last_saved_frame = frame
            saved_frames += 1
        
        frame_idx += 1
    
    cap.release()
    print(f"Successfully extracted {saved_frames} frames to {output_dir}")

# Example usage
extract_equal_frames("your_video.mp4", "extracted_frames", num_frames=15)
Optimized Approach (Faster for Long Videos)

For very long videos, iterating through every frame can be slow. Instead, we can generate a list of evenly spaced frame indices and jump directly to those frames using cap.set():

import cv2
import os
import numpy as np

def extract_equal_frames_optimized(video_path, output_dir, num_frames=10):
    os.makedirs(output_dir, exist_ok=True)
    
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print(f"Error: Failed to open video file {video_path}")
        return
    
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    # Generate evenly spaced indices across the entire video
    frame_indices = np.linspace(0, total_frames - 1, num_frames, dtype=int)
    
    saved_frames = 0
    for idx in frame_indices:
        # Jump directly to the target frame
        cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
        ret, frame = cap.read()
        
        if ret:
            output_path = os.path.join(output_dir, f"frame_{saved_frames:04d}.jpg")
            cv2.imwrite(output_path, frame)
            saved_frames += 1
        else:
            print(f"Warning: Could not read frame {idx} from {video_path}")
    
    cap.release()
    print(f"Successfully extracted {saved_frames} frames to {output_dir}")

This method is much faster because it avoids processing every single frame in long videos.

Key Notes
  • Handle Video Encoding Quirks: Some videos might report an incorrect total frame count due to encoding issues. Adding checks for ret (frame read success) ensures your code doesn’t crash unexpectedly.
  • Frame Quality: Use .png instead of .jpg if you want lossless frame storage (trades off for larger file sizes).
  • Edge Cases: For videos with fewer frames than num_frames, you can choose to repeat frames, stop at the available frames, or interpolate between frames—adjust the code based on your action recognition model’s requirements.

内容的提问来源于stack exchange,提问作者abhay gurrala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:45:46