在 opencv 3.4.2 中更改帧率

新手上路,请多包涵

我想减少网络摄像头每秒获取的帧数,这是我正在使用的代码

#!/usr/bin/env python

import cv2

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FPS, 10)
fps = int(cap.get(5))
print("fps:", fps)

while(cap.isOpened()):

    ret,frame = cap.read()
    if not ret:
        break

    cv2.imshow('frame', frame)

    k = cv2.waitKey(1)
    if k == 27:
        break

但它没有生效,我仍然默认有 30 fps 而不是 cap.set(cv2.CAP_PROP_FPS, 10) 设置的 10。我想降低帧速率,因为我有一个手检测器,它需要花费大量时间来处理每一帧,我不能将帧存储在缓冲区中,因为它会检测到以前位置的手。我可以使用计时器或其他方式运行检测器,但我认为更改 fps 是一种更简单的方法,但它不起作用,我也不知道为什么。

我在 Windows 8.1 中使用 Opencv 3.4.2 和 Python 3.6.3

原文由 Mr. C 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
1 个回答

设置帧速率并不总是像您期望的那样有效。这取决于两件事:

  1. 您的相机能够输出什么。
  2. 您当前使用的捕获后端是否支持更改帧速率。

所以点(1)。您的相机将有一个格式列表,它能够将这些格式传送到捕获设备(例如您的计算机)。这可能是 1920x1080 @ 30 fps 或 1920x1080 @ 60 fps,它还指定了一种像素格式。绝大多数消费类相机不允许您以比这更细粒度的方式更改它们的帧速率。而且大多数捕获库将拒绝更改为相机未宣传的捕获格式。

即使是允许您进行更多控制的机器视觉相机,通常也只提供帧速率的选择(例如 1、2、5、10、15、25、30 等)。如果您想要在硬件级别上不受支持的帧速率,通常唯一的方法是使用硬件触发。

和点(2)。当您使用 cv.VideoCapture 时,您实际上是在调用特定于平台的库,例如 DirectShow 或 V4L2。我们称之为后端。您可以使用类似以下内容的方式准确指定正在使用的后端:

cv2.VideoCapture(0 + cv2.CAP_DSHOW)

定义了很多 CAP_X ,但只有一些适用于您的平台(例如 CAP_V4L2 仅适用于 Linux)。在 Windows 上,强制系统使用 DirectShow 是一个不错的选择。但是如上所述,如果你的相机只报告它可以输出 30fps 和 60fps,那么请求 10fps 将毫无意义。更糟糕的是,许多设置只是在 OpenCV 中报告 True 而实际上并未实现。您已经看到,大多数时候读取参数都会给您带来合理的结果,但是如果未实现该参数(例如,曝光是一种常见的参数),那么您可能会胡说八道。

您最好等待一段时间,然后再阅读最后一张图片。

谨慎使用此策略。不要这样做:

 while capturing:
    res, image = cap.read()
    time.sleep(1)

您需要确保不断清除相机的帧缓冲区,否则您将开始看到视频出现滞后现象。像下面这样的东西应该工作:

 frame_rate = 10
prev = 0

while capturing:

    time_elapsed = time.time() - prev
    res, image = cap.read()

    if time_elapsed > 1./frame_rate:
        prev = time.time()

        # Do something with your image here.
        process_image()

对于像手部检测器这样的应用程序,最好的方法是让一个线程捕获图像,而检测器在另一个线程(也控制 GUI)中运行。您的检测器提取最后捕获的图像,运行并显示结果(您可能需要在读取/写入图像缓冲区时锁定对图像缓冲区的访问)。这样你的瓶颈就是探测器,而不是相机的性能。

原文由 Josh 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进