从视频中每隔10帧截取一帧并保存为图片

  • 要从视频中每隔10帧截取一帧并保存为图片,可以使用 OpenCV 库。
复制代码
import cv2

# 视频文件的路径
video_path = 'path/to/your/video.mp4'

# 创建一个 VideoCapture 对象
cap = cv2.VideoCapture(video_path)

# 检查是否成功打开视频文件
if not cap.isOpened():
    print("Error opening video file")

# 获取视频的帧率
fps = cap.get(cv2.CAP_PROP_FPS)
print(f"Frames per second: {fps:.2f}")

# 初始化帧计数器
frame_count = 0

# 循环读取视频帧
while cap.isOpened():
    # 读取一帧
    ret, frame = cap.read()

    # 如果读取成功,ret 将为 True
    if ret:
        # 每隔10帧保存一次
        if frame_count % 10 == 0:
            # 构建输出图片的文件名
            output_path = f'output/frame_{frame_count}.jpg'
            
            # 保存图片
            cv2.imwrite(output_path, frame)
            print(f"Frame saved at {output_path}")

        # 增加帧计数器
        frame_count += 1
    else:
        # 如果读取失败(到达视频末尾),则退出循环
        break

# 释放 VideoCapture 对象
cap.release()

# 关闭所有 OpenCV 窗口(如果有打开的话)
cv2.destroyAllWindows()

在这段代码中:

  1. 我们首先导入 cv2 模块。
  2. 使用 cv2.VideoCapture() 函数打开视频文件。
  3. 检查视频是否成功打开。
  4. 获取视频的帧率,这可以帮助你了解视频的播放速度。
  5. 初始化一个帧计数器 frame_count
  6. 使用一个无限循环来读取视频帧,直到视频结束。
  7. 在循环中,我们使用 cap.read() 函数读取每一帧。ret 变量将返回一个布尔值,表示读取是否成功;frame 变量将包含实际的图像数据。
  8. 如果读取成功,我们检查 frame_count 是否是10的倍数。如果是,我们就保存当前帧为图片。
  9. 使用 cv2.imwrite() 函数保存图片,文件名格式为 frame_{frame_count}.jpg
  10. 增加帧计数器。
  11. 如果读取失败(通常是因为到达了视频的末尾),我们跳出循环。
  12. 最后,我们释放 VideoCapture 对象并关闭所有 OpenCV 窗口。

确保将 'path/to/your/video.mp4' 替换为你的视频文件的实际路径。

  • 如果你想要按照更精确的时间间隔(比如每秒一次)从视频中提取帧,而不只是简单地每隔一定数量的帧提取,你可以利用视频的编码时间戳。OpenCV 的 VideoCapture 类提供了访问这些时间戳的方法,但默认情况下并不直接提供它们。为了获取时间戳,你需要在读取每一帧时同时读取它们。

下面是一个修改后的示例,展示如何根据时间戳每秒提取一帧:

复制代码
import cv2
import time

# 视频文件的路径
video_path = 'path/to/your/video.mp4'

# 创建一个 VideoCapture 对象
cap = cv2.VideoCapture(video_path)

# 检查是否成功打开视频文件
if not cap.isOpened():
    print("Error opening video file")

# 获取视频的帧率
fps = cap.get(cv2.CAP_PROP_FPS)
print(f"Frames per second: {fps:.2f}")

# 获取视频的总时间(以毫秒为单位)
total_time_ms = cap.get(cv2.CAP_PROP_POS_MSEC)

# 计算视频的总帧数
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

# 初始化当前时间戳
current_time_ms = 0

# 循环读取视频帧
for frame_num in range(total_frames):
    # 设置视频的位置到特定的时间戳
    cap.set(cv2.CAP_PROP_POS_MSEC, current_time_ms)
    
    # 读取一帧
    ret, frame = cap.read()

    # 如果读取成功,ret 将为 True
    if ret:
        # 构建输出图片的文件名
        output_path = f'output/frame_{int(current_time_ms / 1000)}.jpg'
        
        # 保存图片
        cv2.imwrite(output_path, frame)
        print(f"Frame saved at {output_path}")
        
        # 更新时间戳,增加一秒
        current_time_ms += 1000
    else:
        # 如果读取失败(到达视频末尾),则退出循环
        break

# 释放 VideoCapture 对象
cap.release()

# 关闭所有 OpenCV 窗口(如果有打开的话)
cv2.destroyAllWindows()

然而,上述代码有一个关键问题:它假设视频的帧率是恒定的,并且每一帧的持续时间都是相等的。在实际情况中,视频的帧率可能不是完全恒定的,特别是对于一些编码方式更为复杂的视频。因此,使用时间戳来定位帧可能不会总是准确的,尤其是在视频的某些部分帧率发生变化时。

  • 一个更可靠的方法是使用视频的解码时间戳,但这需要额外的库,如 ffmpeg-pythonmoviepy,它们可以提供更高级的视频处理功能,包括对时间戳的精确访问。如果你需要非常精确的时间控制,你可能需要考虑使用这些库之一。

例如,使用 ffmpeg-python 库,你可以如下操作:

复制代码
import ffmpeg

# 视频文件的路径
video_path = 'path/to/your/video.mp4'

# 使用 ffmpeg 接口读取视频
input_video = ffmpeg.input(video_path)

# 获取视频的总时间(以秒为单位)
probe = ffmpeg.probe(video_path)
video_info = next(s for s in probe['streams'] if s['codec_type'] == 'video')
total_time_s = float(video_info['duration'])

# 循环遍历每一秒
for sec in range(int(total_time_s)):
    # 使用 ffmpeg 接口截取视频中的特定帧
    out, _ = (
        ffmpeg
        .filter(input_video, 'select', f'gte(t,{sec}')
        .output('pipe:', format='rawvideo', pix_fmt='rgb24')
        .run(capture_stdout=True)
    )
    
    # 将字节流转换为 numpy 数组
    image = np.frombuffer(out, np.uint8).reshape([int(video_info['height']), int(video_info['width']), 3])
    
    # 构建输出图片的文件名
    output_path = f'output/frame_{sec}.jpg'
    
    # 保存图片
    cv2.imwrite(output_path, image)
    print(f"Frame saved at {output_path}")

请注意,使用 ffmpeg-pythonmoviepy 可能需要安装额外的依赖项,并且它们的使用方法与 OpenCV 有所不同。上述 ffmpeg-python 示例代码需要你有 ffmpeg 工具安装在你的系统上,并且熟悉 ffmpeg 的命令行语法。

相关推荐
数据智能老司机5 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机6 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i6 小时前
drf初步梳理
python·django
每日AI新事件6 小时前
python的异步函数
python
这里有鱼汤8 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook17 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室17 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三19 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试