对于我正在处理的计算机视觉项目,我需要使用Logitech C920网络摄像头抓取图像 . 我正在使用OpenCV的VideoCapture来做到这一点,但我面临的问题是我在某个时刻拍摄的图像并没有显示相机看到的最新内容 . 也就是说,如果我在时间戳t拍摄一张图像,它会显示相机在时间戳(t-delta)处看到的内容,可以这么说 .
我这样做是通过编写一个程序来增加计数器并在屏幕上显示它 . 我将相机对准屏幕并让它记录下来 . 当计数器达到某个值(例如10000)时,它会抓取一个图像并用文件名“counter_value.png”(例如10000.png)保存 . 这样我就可以将计数器的当前值与摄像机看到的当前值进行比较 . 我注意到大多数时候延迟大约是4-5帧,但它不是固定值 .
我看到关于这个问题的类似帖子,但没有一个真的有帮助 . 有些人建议将帧抓取例程放入一个单独的线程中并更新“current_frame”Mat变量 . 我试过了,但由于某种原因,这个问题仍然存在 . 其他人提到相机在Windows上运行良好(但我需要使用Linux) . 我尝试在Windows上运行相同的代码,实际上延迟只有大约1帧(这可能是相机没有看到计数器,因为屏幕没有足够快地更新) .
然后我决定只运行一个基于V4L2代码的简单网络摄像头查看器,认为问题可能来自OpenCV . 我再次遇到了相同的延迟,这让我相信驱动程序正在使用某种缓冲区来缓存图像 .
我是V4L2的新手,我真的需要尽快解决这个问题,所以我对你们的问题是:
-
有没有人找到使用V4L2(也许是OpenCV)获取最新图像的解决方案?
-
如果使用V4L2无法解决问题,有没有人知道在Linux上修复此问题的另一种方法?
问候,
米哈伊
2 回答
看起来
VideoCapture::grab()
呼叫和实际拍摄帧之间总会有延迟 . 这是因为帧缓冲是在硬件/ SO级别完成的,您无法避免这种情况 .OpenCV提供了
VideoCapture::get( CV_CAP_PROP_POS_MEC) )
方法来为您提供捕获帧的确切时间,但这只有在摄像机支持时才可以 .最近在V4L OpenCV实现中发现了一个问题:http://answers.opencv.org/question/61099/is-it-possible-to-get-frame-timestamps-for-live-streaming-video-frames-on-linux/
而且几天前已经解决了一个问题:https://github.com/Itseez/opencv/pull/3998
最后,如果您有正确的设置,您可以知道帧的拍摄时间(因此可以补偿) .
问题出在Linux UVC驱动程序上,但我一直在Ubuntu 12.04和14.04机器上使用Microsoft LifeCam Cinemas进行机器视觉,并且没有看到4-5帧延迟 . 我在低光条件下操作它们,在这种情况下,它们将帧速率降低到7.5 fps .
另一个可能的罪魁祸首是网络摄像头的延迟取决于使用的格式 . C920似乎支持H.264(很少有网络摄像头支持),因此罗技可能已经付出了大量努力使这项工作做得很好,但OpenCV似乎不支持Linux上的H.264;请参阅answer了解它支持的格式 . 同样的问题还有一个带有内核破解(!)的answer来解决UVC驱动程序的问题 .
PS:我补充说,检查我案例中实际使用的格式
在this line在OpenCV代码中 .