OpenCV(四):视频采集与保存
核心函数
cv2.VideoCapture
是 OpenCV 中用于视频采集的核心对象。它抽象了视频输入源,无论是来自硬件摄像头、视频文件,还是网络流(如 IP 摄像机)。
构造函数(初始化)
创建 VideoCapture
对象的关键在于传入正确的参数,以指定视频源。
语法 | 说明 |
---|---|
cap = cv2.VideoCapture(index) | 实时流: 传入整数 index 。通常 0 代表系统默认摄像头,1 代表第二个摄像头,以此类推。 |
cap = cv2.VideoCapture(filename) | 文件流: 传入视频文件的路径字符串 filename (如 'video.mp4' 或 'C:/path/to/video.avi' )。 |
cap = cv2.VideoCapture(url) | 网络流: 传入网络视频流的 URL 字符串(需确保 OpenCV 编译时支持相应的后端,如 GStreamer)。 |
核心方法
方法 | 功能 | 返回值/说明 |
---|---|---|
cap.isOpened() | 检查视频源是否成功初始化和打开。 | True (成功) 或 False (失败) |
ret, frame = cap.read() | 从视频流中读取下一帧。 | ret (bool ): 表示是否成功读取帧;frame (numpy.ndarray ): 读取到的帧图像(BGR 格式)。 |
cap.release() | 释放视频采集资源。在完成视频操作后必须调用。 | 无 |
cap.get(propId) | 获取视频属性,如帧宽度、高度、FPS 等。 | 返回属性值(通常为 float )。 |
cap.set(propId, value) | 设置视频属性。 | True (成功) 或 False (失败)。 |
关键属性标识符(propId
)
在 cap.get()
和 cap.set()
中使用的常量,用于指定操作的视频属性:
标识符 | 说明 |
---|---|
cv2.CAP_PROP_FRAME_WIDTH | 帧的宽度(像素) |
cv2.CAP_PROP_FRAME_HEIGHT | 帧的高度(像素) |
cv2.CAP_PROP_FPS | 视频帧率(Frames Per Second) |
cv2.CAP_PROP_FRAME_COUNT | 视频文件中的总帧数 |
cv2.CAP_PROP_POS_FRAMES | 当前帧的位置(基于 0 的索引) |
示例
示例1:实时摄像头视频采集(实时流)
import cv2# 1. 初始化 VideoCapture 对象,参数 0 表示默认摄像头
cap = cv2.VideoCapture(0)# 检查摄像头是否成功打开
if not cap.isOpened():print("错误:无法打开摄像头。请检查设备索引或驱动。")exit()print("摄像头已打开,按 'q' 键退出...")# 实时流处理循环
while True:# 2. 读取一帧# ret 为布尔值,表示是否成功读取# frame 为读取到的帧图像(numpy 数组)ret, frame = cap.read()# 如果未成功读取帧(如流结束或读取错误),则退出循环if not ret:print("无法接收帧(可能是流结束)。退出...")break# *** 在这里可以对 frame 进行各种图像处理操作 ***# 例如:转换为灰度图gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 3. 显示结果帧# 显示原始彩色帧cv2.imshow('Live Camera Feed', frame)# 也可以显示处理后的灰度帧# cv2.imshow('Gray Frame', gray_frame)# 4. 设置退出条件# cv2.waitKey(1) 等待按键 1 毫秒# 0xFF == ord('q') 检查按下的键是否是 'q'if cv2.waitKey(1) & 0xFF == ord('q'):break# 5. 释放资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
print("资源已释放,程序退出。")
示例2:读取视频文件(文件流)
import cv2
import time# 假设你的视频文件名为 'test_video.mp4' 且在当前目录下
video_path = 'test_video.mp4'# 1. 初始化 VideoCapture 对象,参数为视频文件路径
cap = cv2.VideoCapture(video_path)# 检查视频文件是否成功打开
if not cap.isOpened():print(f"错误:无法打开视频文件: {video_path}")exit()# 2. 获取视频属性
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)print(f"视频分辨率: {frame_width}x{frame_height}")
print(f"视频帧率 (FPS): {fps:.2f}")# 计算每帧应等待的毫秒数 (播放速度控制)
# 默认 FPS,如果读取失败,则使用 25 毫秒/帧 (约 40 FPS)
delay = int(1000 / fps) if fps > 0 else 25 print(f"每帧等待时间: {delay} 毫秒")# 文件流处理循环
while cap.isOpened():# 3. 读取一帧ret, frame = cap.read()if ret:# 4. 显示帧cv2.imshow('Video File Player', frame)# 5. 等待按键# waitKey(delay) 控制播放速度# 按 'q' 退出if cv2.waitKey(delay) & 0xFF == ord('q'):breakelse:# 如果读取失败(通常是文件末尾),则退出循环print("视频播放结束。")break# 6. 释放资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
print("资源已释放,程序退出。")
示例3:拉取 RTSP 网络实时流
import cv2
import time# !!!重要!!!
# 请替换为您实际的 RTSP URL
# 格式通常为: rtsp://用户名:密码@IP地址:端口/路径
RTSP_URL = 'rtsp://guest:password@192.168.1.100:554/live/ch0' # 替换为您的实际地址# 1. 初始化 VideoCapture 对象,传入 RTSP URL
# 注意:网络流的初始化时间可能较长,程序会阻塞直到连接尝试结束
cap = cv2.VideoCapture(RTSP_URL, cv2.CAP_FFMPEG) # 明确指定使用 FFmpeg 后端,增强兼容性# 检查流是否成功打开
if not cap.isOpened():print(f"错误:无法打开 RTSP 流:{RTSP_URL}")print("请检查 URL 格式、用户名密码、网络连通性以及 OpenCV 的 FFmpeg 支持。")exit()print(f"RTSP 流已成功连接,分辨率:{int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))}x{int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))}")
print("按 'q' 键退出...")# RTSP 实时流处理循环
while True:# 2. 读取一帧# 网络流可能会因为网络延迟或断开导致读取失败ret, frame = cap.read()# 如果未成功读取帧,可能是网络中断或流结束if not ret:print("警告:无法从 RTSP 流接收帧。尝试重新连接或退出...")# 尝试等待并重新读取time.sleep(0.1)continue# *** 在这里可以进行实时处理,例如绘制文本、目标检测等 ***cv2.putText(frame, 'RTSP Live Stream', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)# 3. 显示结果帧cv2.imshow('RTSP Stream Player', frame)# 4. 设置退出条件# 对于实时流,waitKey(1) 保证了尽可能快的帧率显示if cv2.waitKey(1) & 0xFF == ord('q'):break# 5. 释放资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
print("RTSP 资源已释放,程序退出。")
保存视频:cv2.VideoWriter
虽然请求是关于采集,但在实际应用中,采集往往伴随着处理和保存。cv2.VideoWriter
类用于将处理后的帧写入视频文件。
核心 API
语法 | 说明 |
---|---|
out = cv2.VideoWriter(filename, fourcc, fps, frame_size) | 构造函数:创建一个 VideoWriter 对象,准备写入视频文件。 |
out.write(frame) | 将一帧图像写入视频文件。 |
out.release() | 关闭视频文件并释放资源。 |
参数说明:
filename
:输出视频文件的路径,例如'output.avi'
。fourcc
:四字符代码 (FourCC),用于指定视频编码器。fps
:输出视频的帧率。frame_size
:帧的宽度和高度,格式为(width, height)
元组。
视频编码格式参考(FourCC)
格式 | FourCC | 文件扩展名 | 说明 |
---|---|---|---|
MPEG-4 | 'mp4v' | .mp4 | 通用、兼容性好 |
XVID | 'XVID' | .avi | 常用 AVI 格式 |
MJPG | 'MJPG' | .avi | 运动JPEG编码 |
H.264 | 'X264' | .mp4 | 需要系统支持 H.264 编码器 |
DIVX | 'DIVX' | .avi | 常见编码 |
示例
示例1:采集实时流并保存视频
import cv2# 1. 初始化 VideoCapture 对象,参数 0 表示默认摄像头
cap = cv2.VideoCapture(0)# 检查摄像头是否成功打开
if not cap.isOpened():print("错误:无法打开摄像头。请检查设备索引或驱动。")exit()print("摄像头已打开,按 'q' 键退出...")# 获取帧的尺寸和 FPS
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 20.0 # 设置保存视频的帧率# 1. 定义 FourCC 编码和 VideoWriter 对象
# 使用 mp4v 编码,保存为 MP4 文件
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output.mp4', fourcc, fps, (frame_width, frame_height))while True:ret, frame = cap.read()if ret:# 2. 将原始帧写入输出文件out.write(frame)# 显示帧 (与前例相同)cv2.imshow('Live Camera Feed and Saving', frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakelse:break# 3. 释放 VideoCapture 和 VideoWriter 资源
cap.release()
out.release()
cv2.destroyAllWindows()
print("视频已保存到 output.mp4。")
示例2:拉取rtsp实时流并保存视频
import cv2
import time# !!!重要!!!
# 请替换为您实际的 RTSP URL
# 格式通常为: rtsp://用户名:密码@IP地址:端口/路径
RTSP_URL = 'rtsp://admin:Gzd@791369209@192.168.0.111:554/Streaming/Channels/101' # 替换为您的实际地址# 初始化 VideoCapture 对象,传入 RTSP URL
# 注意:网络流的初始化时间可能较长,程序会阻塞直到连接尝试结束
cap = cv2.VideoCapture(RTSP_URL, cv2.CAP_FFMPEG) # 明确指定使用 FFmpeg 后端,增强兼容性# 检查流是否成功打开
if not cap.isOpened():print(f"错误:无法打开 RTSP 流:{RTSP_URL}")print("请检查 URL 格式、用户名密码、网络连通性以及 OpenCV 的 FFmpeg 支持。")exit()print(f"RTSP 流已成功连接,分辨率:{int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))}x{int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))}")
print("按 'q' 键退出...")# 获取帧的尺寸和 FPS
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = 20.0 # 设置保存视频的帧率# 1. 定义 FourCC 编码和 VideoWriter 对象
# 使用 mp4v 编码,保存为 MP4 文件
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_rtsp.mp4', fourcc, fps, (frame_width, frame_height))while True:ret, frame = cap.read()if ret:# 2. 将原始帧写入输出文件out.write(frame)# 显示帧 (与前例相同)cv2.imshow('Live Camera Feed and Saving', frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakelse:break# 3. 释放 VideoCapture 和 VideoWriter 资源
cap.release()
out.release()
cv2.destroyAllWindows()
print("视频已保存到 output.mp4。")