OpenCV Python录制高帧率视频问题:无法达到相机额定260FPS
相机帧率不达标的问题排查与解决
我使用一款标称640×360分辨率下支持260FPS MJPEG格式的相机,通过Python+OpenCV录制视频时,无法达到额定帧率。
当前使用的代码片段:
stream = cv2.VideoCapture(1, cv2.CAP_DSHOW) stream.set(cv2.CAP_PROP_FRAME_HEIGHT, 360) stream.set(cv2.CAP_PROP_FRAME_WIDTH, 640) stream.set(cv2.CAP_PROP_FORMAT, cv2.CAP_OPENCV_MJPEG) t0 = cv2.getTickCount() while (cv2.getTickCount() - t0)/cv2.getTickFrequency() < 10: ret, frame = stream.read() frames.append(frame) total = (cv2.getTickCount()-t0)/cv2.getTickFrequency() print("Total time:", total, "# of Frames:", len(frames), "fps:", len(frames)/total)
运行输出:
Total time: 10.0027773 # of Frames: 1874 fps: 187.34796784888934
打印每帧耗时的前几帧结果:
1 - 0.3112283 2 - 0.3267393, before+0.015511 3 - 0.3289934, before+0.0022541 4 - 0.3311813, before+0.0021879 5 - 0.3427716, before+0.0115903
存在两个核心问题:
- 初始帧耗时未从0开始
- 每3帧左右,
read()函数耗时会突然大幅增加,且该现象持续存在
原因分析
- 初始帧耗时偏高:相机启动时需要完成硬件初始化、格式协商、缓冲区填充等操作,这部分额外开销会体现在前几帧的耗时上。
- 周期性耗时突增:
- OpenCV的
CAP_DSHOW后端缓冲区管理机制,当缓冲区达到阈值时会触发批量清理,导致单次read()耗时增加; - USB带宽调度冲突:MJPEG格式需要较高USB带宽,若系统其他设备占用带宽,会导致相机数据传输间歇性卡顿;
- 代码中
frames.append(frame)的动态扩容操作,会带来周期性的性能波动。
- OpenCV的
解决方案
1. 跳过初始化阶段的帧
在正式录制前,先读取几帧丢弃,让相机完成初始化:
# 初始化后先读取5帧丢弃,跳过初始化阶段 for _ in range(5): stream.read()
2. 优化缓冲区与后端设置
- 减小缓冲区大小,降低批量清理的频率:
stream.set(cv2.CAP_PROP_BUFFERSIZE, 2)
- 切换到更适配高帧率的后端(Windows平台推荐
CAP_MSMF):
stream = cv2.VideoCapture(1, cv2.CAP_MSMF)
3. 优化数据存储操作
预先分配列表空间,避免动态扩容的性能开销:
expected_frames = int(260 * 10) # 预估10秒的帧数 frames = [None] * expected_frames frame_idx = 0 while (cv2.getTickCount() - t0)/cv2.getTickFrequency() < 10: ret, frame = stream.read() if ret: frames[frame_idx] = frame frame_idx += 1 frames = frames[:frame_idx] # 截取有效帧
4. 检查系统USB环境
- 确保相机连接到USB3.0及以上接口(USB2.0带宽不足以支撑260FPS的MJPEG传输);
- 暂时断开其他USB设备,避免带宽抢占。
5. 直接读取MJPEG原始数据(进阶)
跳过OpenCV的MJPEG解码步骤,直接读取原始字节流,减少CPU消耗:
stream.set(cv2.CAP_PROP_FORMAT, cv2.CAP_OPENCV_MJPEG) stream.set(cv2.CAP_PROP_MODE, cv2.CAP_MODE_MJPEG) while ...: ret, buf = stream.read() # buf为MJPEG原始字节数据
内容的提问来源于stack exchange,提问作者Ruka
相关产品推荐
相关产品推荐

