3、视频帧读取基础:cv2.VideoCapture的使用,帧率、分辨率参数获取与设置
做视频处理,第一步就是把视频文件或者摄像头的数据「拽」进来。OpenCV 里干这活的就是 cv2.VideoCapture。说白了,它就是个视频流读取器,不管是本地的 MP4 文件,还是你笔记本上的摄像头,它都能搞定。
我个人习惯,拿到一个新视频流,第一件事不是急着处理,而是先看看它的「底细」——帧率多少?分辨率多大?这些参数决定了你后面怎么设计处理流程。
3.1 打开视频源:从文件到摄像头
cv2.VideoCapture 的构造方法很简单,传一个参数就行。传文件路径,它就打开本地视频;传一个数字(比如 0),它就打开摄像头。
import cv2
# 打开本地视频文件
cap = cv2.VideoCapture('test_video.mp4')
# 打开默认摄像头(通常是笔记本前置摄像头)
cap_cam = cv2.VideoCapture(0)
# 检查是否成功打开
if not cap.isOpened():
print("视频文件打开失败,请检查路径")
exit()
注意: 摄像头索引 0 是系统默认摄像头。如果你插了外接摄像头,索引可能是 1 或 2。我在项目里遇到过,笔记本自带摄像头坏了,插了个 USB 摄像头,结果索引 0 打不开,换成 1 就好了。建议打开前先打印一下可用设备列表。
3.2 读取帧:核心循环
视频其实就是一帧一帧的图片快速播放。读取帧的代码就两行,但这里有个坑——ret 这个返回值,很多人会忽略它。
while True:
ret, frame = cap.read()
if not ret:
print("读取完毕或读取失败")
break
# 在这里处理 frame
cv2.imshow('Frame', frame)
# 按 'q' 键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
ret 是个布尔值,告诉你这一帧有没有读成功。为什么会失败?视频读到结尾了,或者文件损坏了,或者摄像头突然断开了。我曾经在部署到嵌入式设备时,摄像头线松了,程序直接卡死在 cap.read() 上,就是因为没检查 ret。
3.3 获取视频参数:帧率、分辨率、总帧数
拿到视频流之后,你得知道它的「体质」。OpenCV 用 cv2.CAP_PROP_* 这些常量来获取参数。
| 参数常量 | 含义 | 返回值类型 |
|---|---|---|
cv2.CAP_PROP_FPS |
帧率(每秒多少帧) | float |
cv2.CAP_PROP_FRAME_WIDTH |
帧宽度(像素) | float |
cv2.CAP_PROP_FRAME_HEIGHT |
帧高度(像素) | float |
cv2.CAP_PROP_FRAME_COUNT |
视频总帧数 | float |
cv2.CAP_PROP_POS_FRAME |
当前帧索引 | float |
# 获取视频参数
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(f"帧率: {fps} FPS")
print(f"分辨率: {width} x {height}")
print(f"总帧数: {total_frames}")
print(f"视频时长: {total_frames / fps:.2f} 秒")
小技巧: 有些视频文件(尤其是网络流或某些编码格式)的
CAP_PROP_FRAME_COUNT 返回 -1,这是正常的。别慌,你只需要按帧读取直到 ret 为 False 就行。
3.4 设置视频参数:分辨率、帧率、编码
有时候你需要改变视频流的参数,比如把摄像头采集的分辨率从 640x480 改成 1280x720。用 cap.set() 就行。
# 设置摄像头分辨率
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap.set(cv2.CAP_PROP_FPS, 30) # 设置帧率
# 验证设置是否生效
actual_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
actual_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(f"实际分辨率: {actual_width} x {actual_height}")
注意: 不是所有摄像头都支持你设置的分辨率。比如你设 1920x1080,但摄像头最高只支持 1280x720,那它可能会自动降级到最接近的支持分辨率。我建议设置完后,用
get() 读一下实际值,确认一下。
3.5 知识结构图:视频帧读取核心流程
下面这张图,把整个视频帧读取的流程串起来了。从打开源到释放资源,每一步都离不开。
3.6 实战:读取视频并显示参数信息
把上面学的东西串起来,写一个完整的例子。这个程序会打开一个视频文件,在每一帧的左上角显示当前帧索引和帧率。
import cv2
cap = cv2.VideoCapture('test_video.mp4')
# 获取参数
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(f"视频信息: {width}x{height} @ {fps:.2f} FPS, 共 {total} 帧")
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
# 在帧上显示信息
text = f"Frame: {frame_idx} / {total}"
cv2.putText(frame, text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
frame_idx += 1
cap.release()
cv2.destroyAllWindows()
核心要点:
cv2.VideoCapture是视频读取的入口,支持文件和摄像头- 每次读取都要检查
ret,防止空帧导致程序崩溃 - 用
get()获取参数,用set()设置参数 - 设置参数后务必用
get()验证是否生效 - 记得释放资源:
cap.release()