繁体   English   中英

OpenCV VideoCapture 仅在 5 个 read()s 后更新

[英]OpenCV VideoCapture only updates after 5 read()s

我有一个非常奇怪的错误,几年来一直困扰着我的研究。 我正在使用 OpenCV2 和 Python 从网络摄像头读取图像数据。 但是,图像滞后 5 帧。 换句话说,对 read() 的每次调用都比实时延迟 5 帧。

我一直在使用的一种绷带修复方法是抓取() 4 帧,然后在每次需要更新图像时读取第 5 帧,但这绝对会扼杀我的表现。

这是我用来显示来自网络摄像头的图像的代码

    frame = self.getGoodFrame()

    if self.DEBUG:
        window = cv2.namedWindow("Angles")
    imgHSV = cv2.cvtColor(frame, cv2.cv.CV_BGR2HSV)

    ... Reseach specific code I shouldn't be giving out here ...
    ... It finds the center of a few bright colors in an image

    if self.DEBUG:
        debugImage = numpy.zeros((self.CAMERA_HEIGHT, self.CAMERA_WIDTH), numpy.uint8) #blank image

       ... Then we draw some stuff to the image to be displayed ...

        cv2.imshow("Angles", debugImage)
        cv2.waitKey(1)
        raw_input()

和 getGoodFrame()

def getGoodFrame(self):
    MIN_READS_FOR_GOOD_FRAME = 4

    for i in xrange(MIN_READS_FOR_GOOD_FRAME):
        successful_read = self.capture.grab() 

    successful_read, frame = self.capture.read()

    if not successful_read:
        print "Unable to read from webcam, exiting."

    return frame

你会注意到我有一个 raw_input() 调用。 这样我就可以通过在控制台中按几次 enter 来查看需要进行多少次读取。 这表明正好有 5 帧的滞后。

我认为这不是硬件问题,我在使用多个网络摄像头和多个 USB 线时遇到过这种情况。 不过,我还没有尝试在另一台机器上重现该错误。

因此,问题与我的硬件缓冲帧的方式有关。 我从来没有完全了解它,但是我发现的解决方案是非常简单的并行化。 我修改了代码以打开线程并不断更新保存当前帧的变量。 然后,当我需要当前帧时,我只是询问当前该变量是什么。

请注意,由于始终存在缓冲,因此仍然落后5个read()调用,但是由于我正在连续进行read()调用,并且它们都在自己的线程上,所以它是最新的。 这是因为我每秒可以调用许多read()调用。 我得到的图像根本没有明显落后于实时性。

我为此编写的Python类如下。 不是很好的代码,但是可以工作。 为了正确执行此操作,我将(并且将)添加一些优美的方法来退出无限循环。 它将对我有效,并且将我的图像检测代码的速度提高了100倍以上,这对我来说真是太棒了,也很令人兴奋:)

class webcamImageGetter:

    def __init__(self):
        self.currentFrame = None
        self.CAMERA_WIDTH = #webcam width
        self.CAMERA_HEIGHT = #webcam height
        self.CAMERA_NUM = 0

        self.capture = cv2.VideoCapture(0) #Put in correct capture number here
        #OpenCV by default gets a half resolution image so we manually set the correct resolution
        self.capture.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,self.CAMERA_WIDTH)
        self.capture.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,self.CAMERA_HEIGHT)

    #Starts updating the images in a thread
    def start(self):
        Thread(target=self.updateFrame, args=()).start()

    #Continually updates the frame
    def updateFrame(self):
        while(True):
            ret, self.currentFrame = self.capture.read()

            while (self.currentFrame == None): #Continually grab frames until we get a good one
                ret, frame = self.capture.read()

    def getFrame(self):
        return self.currentFrame

要使用此功能,请对其进行初始化,然后在实例上调用start。 这样,以后调用getFrame()时,它将具有来自网络摄像头的最新帧。 哇噢!

默认缓冲区设置为 4.0 而不是 1.0。

要解决这个问题:

帽集(38,1)

参考: https ://docs.opencv.org/4.x/d4/d15/group__videoio__flags__base.html#ga41c5cfa7859ae542b71b1d33bbd4d2b4

您可以在图片参数 nr 38 上看到。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM