核心概念
使用 OpenCV 处理视频主要有两种方式:

- 从视频文件读取:打开一个本地存储的视频文件(如
.mp4,.avi,.mov等)。 - 从摄像头读取:打开电脑的摄像头或网络摄像头进行实时捕获。
这两种方式的原理是相似的:视频本质上是由一帧一帧的图像组成的序列,OpenCV 的任务就是逐帧读取这些图像,然后你就可以对每一帧进行处理(显示、分析、修改等)。
从视频文件读取
这是最常见的情况,我们将使用 cv2.VideoCapture() 来创建一个视频捕获对象。
基本步骤:
- 导入 OpenCV 库:
import cv2 - 创建 VideoCapture 对象:
cap = cv2.VideoCapture('video_path.mp4') - 读取视频帧:在一个循环中,使用
cap.read()方法读取每一帧。cap.read()会返回两个值:- 一个布尔值
ret,表示是否成功读取到帧,当视频结束时,它会返回False。 - 一个 NumPy 数组
frame,表示当前读取到的图像帧。
- 一个布尔值
- 显示帧:使用
cv2.imshow()在窗口中显示读取到的帧。 - 处理按键:为了让视频能够正常播放而不是一闪而过,需要使用
cv2.waitKey(),它的参数是等待按键的毫秒数,对于视频播放,通常设置一个较小的值(如 25 或 30)来控制播放速度。 - 释放资源:视频播放完毕或用户按下退出键后,必须使用
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,因为我们希望以最快的速度显示实时画面。

进阶:获取视频信息并保存视频
在处理视频时,我们经常需要知道视频的属性(如帧率、尺寸等),或者将处理后的帧保存为新的视频文件。
获取视频属性
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。
步骤:

-
创建 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): 必须和你要写入的帧的尺寸完全一致。
-
在循环中写入帧:
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) # 写入原始帧或处理后的帧 -
释放资源:
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 读取和处理视频!
