对于我正在处理的计算机视觉项目,我需要使用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的新手,我真的需要尽快解决这个问题,所以我对你们的问题是:
此致
米哈伊
答案 0 :(得分:0)
看起来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
最后,如果你有正确的设置,你可以知道一帧被拍摄的时间(并因此得到补偿)。
答案 1 :(得分:0)
问题出在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:为了检查我案例中实际使用的格式,我添加了
fprintf(stderr, ">>> palette: %d\n", capture->palette);
在OpenCV代码中的this line。