OpenCV VideoCapture仅在5次read()后更新

时间:2014-06-23 16:22:28

标签: python opencv

我有一个非常奇怪的错误,几年来一直困扰着我的研究。我使用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()调用。这样就可以通过在控制台中输入几次来查看需要执行的读取次数。这表明恰好有5帧滞后。

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

1 个答案:

答案 0 :(得分:0)

所以这个问题与我的硬件缓冲帧的方式有关。我从来没有完全了解它,但我找到的解决方案是非常简单的paralellization。我修改了我的代码以打开一个线程并不断更新保存当前帧的变量。然后,当我需要当前帧时,我只需要询问当前的变量。

请注意,由于持续存在缓冲,此仍然是后面的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()时,它将具有来自网络摄像头的最新帧。哇噢!