OpenCV 视频处理入门教程
目录
--
一、学习目标
学习完本文后,你应该能够掌握:
- 使用
cv2.VideoCapture()打开摄像头或视频文件。 - 使用
cap.read()一帧一帧读取视频。 - 使用
cv2.imshow()显示视频画面。 - 使用
cv2.waitKey()控制播放速度和退出逻辑。 - 使用
cv2.VideoWriter()保存处理后的视频。 - 理解 FPS、帧、分辨率、FourCC 编码器等基础概念。
二、环境准备
1. 安装 OpenCV
bash
pip install opencv-python
如果你不需要 GUI 显示窗口,只在服务器上处理视频,可以安装:
bash
pip install opencv-python-headless
不过本文会用到 cv2.imshow(),所以建议安装:
bash
pip install opencv-python
2. 验证安装
python
import cv2
print(cv2.__version__)
如果可以正常输出版本号,说明安装成功。
三、核心概念
1. 视频是什么?
视频本质上是一系列连续图片。
每一张图片叫做一帧:
text
video = frame1 + frame2 + frame3 + ... + frameN
OpenCV 处理视频时,也是按帧读取:
text
打开视频源 -> 读取一帧 -> 处理一帧 -> 显示/保存 -> 继续下一帧
2. VideoCapture
cv2.VideoCapture() 用来打开视频源。
视频源可以是:
python
cv2.VideoCapture(0) # 打开默认摄像头
cv2.VideoCapture(1) # 打开第二个摄像头
cv2.VideoCapture("test.mp4") # 打开本地视频文件
参数说明:
| 参数 | 含义 |
|---|---|
0 |
默认摄像头 |
1 |
第二个摄像头 |
"xxx.mp4" |
本地视频文件路径 |
"rtsp://..." |
网络摄像头或视频流地址 |
3. cap.read()
cap.read() 用来读取一帧画面。
返回两个值:
python
ret, frame = cap.read()
| 返回值 | 含义 |
|---|---|
ret |
是否读取成功,成功为 True,失败为 False |
frame |
当前帧图像,本质是一个 NumPy 数组 |
4. imshow
cv2.imshow() 用来显示图像或视频帧。
python
cv2.imshow("frame", frame)
参数说明:
| 参数 | 含义 |
|---|---|
"frame" |
窗口名称 |
frame |
要显示的图像 |
5. waitKey
cv2.waitKey() 用来等待键盘输入,同时也负责刷新 OpenCV 窗口。
python
cv2.waitKey(1)
常见用法:
| 写法 | 含义 |
|---|---|
cv2.waitKey(0) |
一直等待按键 |
cv2.waitKey(1) |
等待 1 毫秒,适合实时摄像头 |
cv2.waitKey(25) |
等待 25 毫秒,适合普通视频播放 |
"等待"的本质是控制每一帧显示多久。
判断是否按下 q:
python
if cv2.waitKey(1) == ord("q"):
break
6. VideoWriter
cv2.VideoWriter() 用来保存视频。
python
out = cv2.VideoWriter("output.avi", fourcc, fps, (width, height))
参数说明:
| 参数 | 含义 |
|---|---|
"output.avi" |
输出视频文件名 |
fourcc |
视频编码格式 |
fps |
每秒帧数 |
(width, height) |
视频尺寸 |
四、从摄像头读取视频
1. 基础示例
python
import cv2
# 打开默认摄像头
cap = cv2.VideoCapture(0)
# 判断摄像头是否打开成功
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# 读取一帧
ret, frame = cap.read()
# 如果读取失败,退出循环
if not ret:
print("Can't receive frame. Exiting ...")
break
# 显示画面
cv2.imshow("Camera", frame)
# 按 q 退出
if cv2.waitKey(1) == ord("q"):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
2. 代码解释
python
cap = cv2.VideoCapture(0)
打开默认摄像头。
python
if not cap.isOpened():
判断摄像头是否打开成功。
python
ret, frame = cap.read()
读取摄像头的一帧画面。
python
cv2.imshow("Camera", frame)
显示当前帧。
python
if cv2.waitKey(1) == ord("q"):
如果按下 q,退出程序。
python
cap.release()
cv2.destroyAllWindows()
释放摄像头资源,关闭所有 OpenCV 窗口。
五、读取本地视频文件
1. 基础示例
python
import cv2
video_path = "test.mp4"
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print("Cannot open video file")
exit()
while cap.isOpened():
ret, frame = cap.read()
if not ret:
print("Video finished or frame read failed.")
break
cv2.imshow("Video", frame)
# 数值越小播放越快,数值越大播放越慢
if cv2.waitKey(25) == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
2. 摄像头和视频文件的区别
| 视频源 | 写法 | 特点 |
|---|---|---|
| 摄像头 | cv2.VideoCapture(0) |
实时读取 |
| 本地视频 | cv2.VideoCapture("test.mp4") |
从文件逐帧读取 |
3. waitKey 对播放速度的影响
python
cv2.waitKey(1)
等待时间短,播放更快。
python
cv2.waitKey(25)
等待时间较长,播放速度更接近普通视频。
如果视频是 25 FPS,可以近似理解为:
text
每帧等待 40 ms 左右
因为:
text
1000 ms / 25 FPS = 40 ms
六、保存视频到本地
1. 保存摄像头视频
python
import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
# 获取摄像头分辨率
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 20.0
# 设置视频编码器
fourcc = cv2.VideoWriter_fourcc(*"XVID")
# 创建 VideoWriter 对象
out = cv2.VideoWriter("output.avi", fourcc, fps, (width, height))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
print("Can't receive frame. Exiting ...")
break
# 写入视频
out.write(frame)
# 显示画面
cv2.imshow("Recording", frame)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
out.release()
cv2.destroyAllWindows()
2. FourCC 是什么?
FourCC 是视频编码格式的四字符代码。
常见编码:
| FourCC | 常见扩展名 | 说明 |
|---|---|---|
XVID |
.avi |
兼容性较好 |
MJPG |
.avi |
文件较大,但兼容性好 |
mp4v |
.mp4 |
常用于 mp4 |
X264 |
.mkv / .mp4 |
压缩率高,但环境依赖更多 |
示例:
python
fourcc = cv2.VideoWriter_fourcc(*"XVID")
等价于:
python
fourcc = cv2.VideoWriter_fourcc("X", "V", "I", "D")
3. 保存灰度视频
如果你要保存灰度视频,需要注意 isColor=False。
python
import cv2
cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("gray_output.avi", fourcc, 20.0, (width, height), isColor=False)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(gray)
cv2.imshow("Gray", gray)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
out.release()
cv2.destroyAllWindows()
注意:
text
保存彩色视频:isColor=True,写入 BGR 三通道图像
保存灰度视频:isColor=False,写入单通道灰度图像
七、常用属性读取与设置
1. 获取视频属性
python
import cv2
cap = cv2.VideoCapture("test.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("width:", width)
print("height:", height)
print("fps:", fps)
print("frame_count:", frame_count)
cap.release()
常用属性:
| 属性 | 含义 |
|---|---|
cv2.CAP_PROP_FRAME_WIDTH |
视频宽度 |
cv2.CAP_PROP_FRAME_HEIGHT |
视频高度 |
cv2.CAP_PROP_FPS |
视频 FPS |
cv2.CAP_PROP_FRAME_COUNT |
视频总帧数 |
cv2.CAP_PROP_POS_FRAMES |
当前帧位置 |
cv2.CAP_PROP_POS_MSEC |
当前播放时间,单位毫秒 |
2. 设置摄像头分辨率
python
import cv2
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
while True:
ret, frame = cap.read()
if not ret:
break
cv2.imshow("Camera", frame)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
注意:
text
并不是所有摄像头都支持任意分辨率。
set() 返回成功,不代表摄像头一定按该分辨率输出。
最好设置后再用 get() 读取确认。
八、完整项目示例:摄像头灰度显示并保存
这个示例实现:
text
打开摄像头
读取实时画面
转灰度
显示灰度画面
保存为 gray_camera.avi
按 q 退出
完整代码:
python
import cv2
def main():
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
return
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 20.0
fourcc = cv2.VideoWriter_fourcc(*"XVID")
writer = cv2.VideoWriter(
"gray_camera.avi",
fourcc,
fps,
(width, height),
isColor=False
)
if not writer.isOpened():
print("Cannot open video writer")
cap.release()
return
while True:
ret, frame = cap.read()
if not ret:
print("Cannot receive frame")
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
writer.write(gray)
cv2.imshow("Gray Camera", gray)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
writer.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
九、常见问题
1. 摄像头打不开
可能原因:
text
摄像头被其他软件占用
设备编号不对
系统没有摄像头权限
Linux 上摄像头设备权限不足
解决方式:
python
cap = cv2.VideoCapture(0)
可以尝试:
python
cap = cv2.VideoCapture(1)
Windows 上也可以尝试:
python
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
2. 视频播放太快或太慢
调整:
python
cv2.waitKey(25)
数值越小,播放越快;数值越大,播放越慢。
3. 保存的视频打不开
重点检查:
text
编码器 FourCC 和文件后缀是否匹配
写入帧尺寸是否和 VideoWriter 初始化尺寸一致
是否调用 out.release()
推荐组合:
python
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("output.avi", fourcc, 20.0, (640, 480))
或者:
python
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
out = cv2.VideoWriter("output.mp4", fourcc, 20.0, (640, 480))
4. imshow 没有窗口
如果你使用的是:
bash
opencv-python-headless
它不支持 GUI 显示窗口。
需要安装:
bash
pip uninstall opencv-python-headless
pip install opencv-python
如果你在 Linux 服务器无桌面环境中运行,也无法正常弹出窗口,可以改为保存图片或视频文件。
5. 为什么 OpenCV 读取的颜色怪怪的?
OpenCV 默认读取图片和视频帧是:
text
BGR
不是常见的:
text
RGB
如果要转 RGB:
python
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
如果要转灰度:
python
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
十、总结
OpenCV-Python 处理视频的核心流程非常固定:
text
创建 VideoCapture
-> 判断是否打开成功
-> 循环读取 frame
-> 对 frame 做处理
-> imshow 显示
-> waitKey 控制退出和播放速度
-> release 释放资源