由于捕获缓冲区,OpenCV VideoCapture延迟 [英] OpenCV VideoCapture lag due to the capture buffer
问题描述
我通过网络摄像头捕获视频,该网络摄像头会提供mjpeg流。
我在工作线程中捕获了视频。
我这样开始捕获:
I am capturing video through a webcam which gives a mjpeg stream. I did the video capture in a worker thread. I start the capture like this:
const std::string videoStreamAddress = "http://192.168.1.173:80/live/0/mjpeg.jpg?x.mjpeg";
qDebug() << "start";
cap.open(videoStreamAddress);
qDebug() << "really started";
cap.set(CV_CAP_PROP_FRAME_WIDTH, 720);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 576);
相机正在以20fps的速度馈送流。
但是如果我在20fps中这样读取:
the camera is feeding the stream at 20fps. But if I did the reading in 20fps like this:
if (!cap.isOpened()) return;
Mat frame;
cap >> frame; // get a new frame from camera
mutex.lock();
m_imageFrame = frame;
mutex.unlock();
然后有3+秒的滞后。
原因是捕获的视频首先存储在缓冲区中。当我第一次启动相机时,缓冲区已累积,但我没有读取帧。所以如果我从缓冲区读取它总是给我旧的帧。
现在我唯一的解决方案是读取30fps的缓冲区,所以它会快速清理缓冲区,没有更严重的滞后。
Then there is a 3+ seconds lag. The reason is that the captured video is first stored in a buffer.When I first start the camera, the buffer is accumulated but I did not read the frames out. So If I read from the buffer it always gives me the old frames. The only solutions I have now is to read the buffer at 30fps so it will clean the buffer quickly and there's no more serious lag.
有没有其他可能的解决方案,使我可以清理/刷新缓冲区手动每次我开始相机?
Is there any other possible solution so that I could clean/flush the buffer manually each time I start the camera?
推荐答案
根据此源代码,您可以设置 cv :: VideoCapture的buffersize 对象。
According to this source, you can set the buffersize of a cv::VideoCapture
object.
cv::VideoCapture cap;
cap.set(CV_CAP_PROP_BUFFERSIZE, 3); // internal buffer will now store only 3 frames
// rest of your code...
但是有一个重要的限制:
There is an important limitation however:
CV_CAP_PROP_BUFFERSIZE内部缓冲存储器中存储的帧数(注意:只支持DC1394 v 2.x后端)
该解决方案不起作用,请查看这个帖子解释了如何解决这个问题。
If the solution does not work, take a look at this post that explains how to hack around the issue.
简而言之:查询框架所需的时间是测量的;如果它太低,则意味着帧被从缓冲器读取并且可以被丢弃。继续查询帧,直到测量的时间超过某个限制。发生这种情况时,缓冲区为空,返回的帧是最新的。
In a nutshell: the time needed to query a frame is measured; if it is too low, it means the frame was read from the buffer and can be discarded. Continue querying frames until the time measured exceeds a certain limit. When this happens, the buffer was empty and the returned frame is up to date.
(链接的帖子显示:从缓冲区返回一个帧大约需要1 /
(The answer on the linked post shows: returning a frame from the buffer takes about 1/8th the time of returning an up to date frame. Your mileage may vary, of course!)
不同的解决方案,受到此帖子的启发,是创建一个连续抓取框架的第三个线程以高速保持缓冲器空。此主题应使用 cv :: VideoCapture.grab()
以避免开销。
A different solution, inspired by this post, is to create a third thread that grabs frames continuously at high speed to keep the buffer empty. This thread should use the cv::VideoCapture.grab()
to avoid overhead.
您可以使用简单的自旋锁来同步实际工作线程和第三线程之间的读取帧。
You could use a simple spin-lock to synchronize reading frames between the real worker thread and the third thread.
这篇关于由于捕获缓冲区,OpenCV VideoCapture延迟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!