如何使 cv2.videoCapture.read() 更快?

新手上路,请多包涵

我的问题 :

我正在从事我的计算机视觉项目。我使用 opencv(4.1.2) 和 python 来实现它。

我需要一种更快的方法将阅读框传递到我的计算机(Ubuntu 18.04 8 核 i7 3.00GHz 内存 32GB)上的图像处理中。 cv2.VideoCapture.read() 读取帧(帧大小:720x1280)大约需要 120~140 毫秒。 这太慢了。 我的处理模块每次运行大约需要 40 毫秒。我们希望 25~30 FPS。

到目前为止,这是我的演示代码:

 import cv2
from collections import deque
from time import sleep, time
import threading

class camCapture:
    def __init__(self, camID, buffer_size):
        self.Frame = deque(maxlen=buffer_size)
        self.status = False
        self.isstop = False
        self.capture = cv2.VideoCapture(camID)

    def start(self):
        print('camera started!')
        t1 = threading.Thread(target=self.queryframe, daemon=True, args=())
        t1.start()

    def stop(self):
        self.isstop = True
        print('camera stopped!')

    def getframe(self):
        print('current buffers : ', len(self.Frame))
        return self.Frame.popleft()

    def queryframe(self):
        while (not self.isstop):
            start = time()
            self.status, tmp = self.capture.read()
            print('read frame processed : ', (time() - start) *1000, 'ms')
            self.Frame.append(tmp)

        self.capture.release()

cam = camCapture(camID=0, buffer_size=50)
W, H = 1280, 720
cam.capture.set(cv2.CAP_PROP_FRAME_WIDTH, W)
cam.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, H)

# start the reading frame thread
cam.start()

# filling frames
sleep(5)

while True:
  frame = cam.getframe() # numpy array shape (720, 1280, 3)

  cv2.imshow('video',frame)
  sleep( 40 / 1000) # mimic the processing time

  if cv2.waitKey(1) == 27:
        cv2.destroyAllWindows()
        cam.stop()
        break

我试过的:

  1. 多线程 - 一个线程只读取帧,另一个执行图像处理。 这不是我想要的。 因为我可以设置一个缓冲区双端队列,例如保存 50 帧。但是帧读取线程的工作速度为 ~ frame/130ms。我的图像处理线程以 ~ frame/40ms 的速度工作。然后双端队列就用完了。所以我已经尝试过解决方案。但不是我需要的。

  2. 这个 话题 是我发现最接近我的问题的讨论。但不幸的是,我尝试了公认的解决方案(讨论下面的两个)。

其中一个解决方案(6 个竖起大拇指)指出他可以在他的 mac 上以 1 秒的间隔读取和保存 100 帧。为什么我的机器无法处理帧读取工作?我错过了什么吗?我的安装使用了 conda 和 pip conda install -c conda-forge opencv , pip install opencv-python (是的,我都试过了。)

另一个解决方案(1 个大拇指)使用 ffmpeg 解决方案。但它似乎适用于视频文件而不是相机设备?

  1. 调整c2.waitKey() :该参数只是控制视频显示时的频率。不是解决方案。

然后,我知道我只需要一些关键字即可。

到目前为止,上面的代码是我的演示代码,我需要一些方法或指南来使我的 videoCapture.read() 更快。也许是一种在 videoCapture 对象或其他相机读取模块中使用多线程的方法。

有什么建议么?

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

阅读 3.7k
1 个回答

这有点晚了,但我想知道我在 Ubuntu 20.04 和 OpenCV 上使用我的罗技 C920 HD Pro USB 摄像头。我试图命令捕获会话以 30 FPS 的速度运行全高清,但 FPS 在 4-5 FPS 之间波动。

我相机的捕获格式默认为“YUYV 4:2:2”。无论我如何尝试更改视频捕获设置,OpenCV 都没有神奇地更改视频格式以匹配所需的 FPS 设置。

当我列出罗技 C920 的视频格式时,它显示:

 ubuntu:~$ v4l2-ctl --list-formats-ext

ioctl: VIDIOC_ENUM_FMT
    Type: Video Capture

    [0]: 'YUYV' (YUYV 4:2:2)
<clip>
        Size: Discrete 1600x896
            Interval: Discrete 0.133s (7.500 fps)
            Interval: Discrete 0.200s (5.000 fps)
        Size: Discrete 1920x1080
            Interval: Discrete 0.200s (5.000 fps)
        Size: Discrete 2304x1296
            Interval: Discrete 0.500s (2.000 fps)
    [1]: 'MJPG' (Motion-JPEG, compressed)
<clip>
        Size: Discrete 1920x1080
            Interval: Discrete 0.033s (30.000 fps)
            Interval: Discrete 0.042s (24.000 fps)
            Interval: Discrete 0.050s (20.000 fps)
            Interval: Discrete 0.067s (15.000 fps)
            Interval: Discrete 0.100s (10.000 fps)
            Interval: Discrete 0.133s (7.500 fps)
            Interval: Discrete 0.200s (5.000 fps)

解决方案是手动命令 OpenCV 捕获设备使用压缩的“MJPG”格式:

 import numpy as np
import cv2

capture = cv2.VideoCapture(0)
W, H = 1920, 1080
capture.set(cv2.CAP_PROP_FRAME_WIDTH, W)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, H)
capture.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
capture.set(cv2.CAP_PROP_FPS, 30)

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

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