我有一个非常奇怪的错误,几年来一直困扰着我的研究。我使用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线上。我还没有尝试在另一台机器上重现错误。
答案 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()时,它将具有来自网络摄像头的最新帧。哇噢!