杰瑞科技汇

Python OpenCV如何高效读取视频帧?

核心概念

使用 OpenCV 处理视频主要有两种方式:

Python OpenCV如何高效读取视频帧?-图1
(图片来源网络,侵删)
  1. 从视频文件读取:打开一个本地存储的视频文件(如 .mp4, .avi, .mov 等)。
  2. 从摄像头读取:打开电脑的摄像头或网络摄像头进行实时捕获。

这两种方式的原理是相似的:视频本质上是由一帧一帧的图像组成的序列,OpenCV 的任务就是逐帧读取这些图像,然后你就可以对每一帧进行处理(显示、分析、修改等)。


从视频文件读取

这是最常见的情况,我们将使用 cv2.VideoCapture() 来创建一个视频捕获对象。

基本步骤:

  1. 导入 OpenCV 库import cv2
  2. 创建 VideoCapture 对象cap = cv2.VideoCapture('video_path.mp4')
  3. 读取视频帧:在一个循环中,使用 cap.read() 方法读取每一帧。
    • cap.read() 会返回两个值:
      • 一个布尔值 ret,表示是否成功读取到帧,当视频结束时,它会返回 False
      • 一个 NumPy 数组 frame,表示当前读取到的图像帧。
  4. 显示帧:使用 cv2.imshow() 在窗口中显示读取到的帧。
  5. 处理按键:为了让视频能够正常播放而不是一闪而过,需要使用 cv2.waitKey(),它的参数是等待按键的毫秒数,对于视频播放,通常设置一个较小的值(如 25 或 30)来控制播放速度。
  6. 释放资源:视频播放完毕或用户按下退出键后,必须使用 cap.release() 释放 VideoCapture 对象,并使用 cv2.destroyAllWindows() 关闭所有 OpenCV 窗口。

完整代码示例

import cv2
# 1. 指定视频文件路径
video_path = 'my_video.mp4'  # 请替换为你的视频文件路径
# 2. 创建 VideoCapture 对象
cap = cv2.VideoCapture(video_path)
# 检查视频是否成功打开
if not cap.isOpened():
    print("错误:无法打开视频文件")
    exit()
# 3. 循环读取视频帧
while True:
    # ret: 是否成功读取到帧 (True/False)
    # frame: 当前帧的图像数据 (一个 NumPy 数组)
    ret, frame = cap.read()
    # ret 为 False,表示视频已经读取完毕
    if not ret:
        print("视频播放完毕")
        break
    # 4. 显示当前帧
    cv2.imshow('Video Playback', frame)
    # 5. 等待按键,并判断是否按下 'q' 键来退出
    # cv2.waitKey(25) 会等待 25 毫秒
    # 如果按下 'q' 键 (ASCII 码为 113),则退出循环
    if cv2.waitKey(25) & 0xFF == ord('q'):
        print("用户按下 'q' 键,退出播放")
        break
# 6. 释放资源
cap.release()
cv2.destroyAllWindows()

从摄像头读取

从摄像头读取的流程与从文件读取几乎完全相同,只是创建 VideoCapture 对象的方式不同。

  • 从默认摄像头(索引为 0)读取cap = cv2.VideoCapture(0)
  • 从特定摄像头读取:如果你的电脑有多个摄像头,可以尝试索引 1, 2, ... cap = cv2.VideoCapture(1)
  • 从网络摄像头(IP Camera)读取cap = cv2.VideoCapture('rtsp://username:password@ip_address:port/path')

完整代码示例(实时摄像头捕获)

import cv2
# 1. 创建 VideoCapture 对象,参数 0 表示使用默认摄像头
cap = cv2.VideoCapture(0)
# 检查摄像头是否成功打开
if not cap.isOpened():
    print("错误:无法打开摄像头")
    exit()
print("摄像头已打开,按 'q' 键退出...")
# 2. 循环读取摄像头帧
while True:
    # ret: 是否成功读取到帧 (True/False)
    # frame: 当前帧的图像数据
    ret, frame = cap.read()
    if not ret:
        print("无法获取帧,或摄像头已断开")
        break
    # 3. 显示当前帧
    cv2.imshow('Camera Feed', frame)
    # 4. 等待按键,判断是否按下 'q' 键来退出
    # 0xFF 是为了确保兼容性,因为 cv2.waitKey() 在某些系统上返回的是 32 位整数
    if cv2.waitKey(1) & 0xFF == ord('q'):
        print("用户按下 'q' 键,退出")
        break
# 5. 释放资源
cap.release()
cv2.destroyAllWindows()

注意:从摄像头读取时,cv2.waitKey() 的参数通常设为 1,因为我们希望以最快的速度显示实时画面。

Python OpenCV如何高效读取视频帧?-图2
(图片来源网络,侵删)

进阶:获取视频信息并保存视频

在处理视频时,我们经常需要知道视频的属性(如帧率、尺寸等),或者将处理后的帧保存为新的视频文件。

获取视频属性

VideoCapture 对象提供了一些方法来获取视频的元信息。

cap = cv2.VideoCapture('my_video.mp4')
# 获取视频的属性
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))   # 宽度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))  # 高度
fps = cap.get(cv2.CAP_PROP_FPS)                  # 帧率
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 总帧数
print(f"视频宽度: {width}")
print(f"视频高度: {height}")
print(f"视频帧率: {fps:.2f} FPS")
print(f"视频总帧数: {frame_count}")
cap.release()

保存视频(视频写入)

要将处理后的帧保存为新视频,你需要使用 cv2.VideoWriter

步骤:

Python OpenCV如何高效读取视频帧?-图3
(图片来源网络,侵删)
  1. 创建 VideoWriter 对象

    # 参数依次为: 输出文件名, 编码格式, 帧率, 帧尺寸, 是否为彩色
    fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 'mp4v' 是一种常见的编码格式
    out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (width, height))
    • cv2.VideoWriter_fourcc(*'mp4v'): 指定视频编码器。'mp4v' 通常用于生成 .mp4 文件,'XVID' 用于 .avi 文件,如果保存失败,可以尝试其他编码器。
    • fps: 使用原视频的帧率。
    • (width, height): 必须和你要写入的帧的尺寸完全一致。
  2. 在循环中写入帧

    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        # ... 在这里对 frame 进行处理 ...
        # 转为灰度图
        # processed_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 写入处理后的帧
        # 注意:如果是灰度图,尺寸是 (width, height),需要转换为 (width, height, 1) 或直接使用原尺寸
        # 但 VideoWriter 通常期望 BGR 格式的彩色帧
        out.write(frame) # 写入原始帧或处理后的帧
  3. 释放资源

    cap.release()
    out.release() # 别忘了释放 VideoWriter!

综合示例:读取视频,转为灰度,并保存

import cv2
# --- 1. 读取原始视频 ---
input_video_path = 'my_video.mp4'
output_video_path = 'output_gray_video.mp4'
cap = cv2.VideoCapture(input_video_path)
if not cap.isOpened():
    print(f"错误:无法打开视频 {input_video_path}")
    exit()
# --- 2. 获取视频属性并设置 VideoWriter ---
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
print(f"原始视频尺寸: {width}x{height}, 帧率: {fps:.2f}")
# 定义编码器和创建 VideoWriter 对象
# 'mp4v' 是一个常用的编码器,如果不行可以尝试 'avc1' 或 'XVID'
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))
# --- 3. 循环处理并保存 ---
print("开始处理视频...")
while True:
    ret, frame = cap.read()
    if not ret:
        print("视频处理完毕")
        break
    # 将帧转换为灰度图
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 将单通道的灰度图转换为三通道,以便 VideoWriter 可以写入
    # 因为 VideoWriter 通常期望 BGR 格式的彩色图像
    three_channel_gray = cv2.cvtColor(gray_frame, cv2.COLOR_GRAY2BGR)
    # 写入处理后的帧
    out.write(three_channel_gray)
# --- 4. 释放所有资源 ---
cap.release()
out.release()
cv2.destroyAllWindows()
print(f"处理完成,新视频已保存为 {output_video_path}")
功能 核心代码 说明
读取视频文件 cap = cv2.VideoCapture('path/to/video.mp4') 创建视频捕获对象。
读取摄像头 cap = cv2.VideoCapture(0) 0 是默认摄像头索引。
读取一帧 ret, frame = cap.read() 返回是否成功和帧数据。
显示一帧 cv2.imshow('Window Name', frame) 在窗口中显示图像。
控制播放/退出 if cv2.waitKey(25) & 0xFF == ord('q'): 等待按键,q 用于退出。
释放资源 cap.release() 必须调用,关闭视频流。
获取视频宽度 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) 获取视频的元数据。
保存视频 out = cv2.VideoWriter(...) 创建视频写入对象。
写入一帧 out.write(frame) 将处理后的帧写入新视频。
释放写入器 out.release() 必须调用,完成视频保存。

希望这个详细的指南能帮助你掌握在 Python 中使用 OpenCV 读取和处理视频!

分享:
扫描分享到社交APP
上一篇
下一篇