You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()函数耗时会突然大幅增加,且该现象持续存在

原因分析

  1. 初始帧耗时偏高:相机启动时需要完成硬件初始化、格式协商、缓冲区填充等操作,这部分额外开销会体现在前几帧的耗时上。
  2. 周期性耗时突增:
    • OpenCV的CAP_DSHOW后端缓冲区管理机制,当缓冲区达到阈值时会触发批量清理,导致单次read()耗时增加;
    • USB带宽调度冲突:MJPEG格式需要较高USB带宽,若系统其他设备占用带宽,会导致相机数据传输间歇性卡顿;
    • 代码中frames.append(frame)的动态扩容操作,会带来周期性的性能波动。

解决方案

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 17:23:17