由于捕获缓冲区，OpenCV VideoCapture延迟 [英] OpenCV VideoCapture lag due to the capture buffer
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);
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();
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 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.
(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!)
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.