Ask Your Question
0

Read latest live image from webcam, not from queue?

asked 2016-07-25 15:51:06 -0600

charles.fox gravatar image

Hi all,

I've been running some speed tests of a webcam-based opencv program and I was surprised to find that a bottleneck seems to be due to cap.read() behaviour for live cams.

My cpp code runs every 0.5 seconds and takes a snapshot from the webcam, displays it on screen, then sleeps till the next time. When I display these images on the screen there is loads of latency, sometimes several seconds.

What I think is happening is that cap.read() isn't reading the latest image from the webcam. Rather, the webcam is running at a higher fps, eg 10fps, determined by its 4vl settings, and storing these images in a buffer. Then cap.read() is only getting the next image from the buffer, as if it was reading from a movie file. As my code only runs twice per second, I'm reading old image from the camera hardware rather than the latest ones. It looks like the buffer holds a few seconds of images, because my latency doesn't get worse than that once the buffer is full.

My webcam doesn't go down to 2fps, I think the lowest is about 10. But regardless of this, I wonder if cv has a function that is like cap.read() but which always returns the latest available live image rather than the next one off the buffer? Something like cap.readlatest() ? Or any other workarounds? At the moment I just call cap.read() five times in a row on each callback, which has just about got rid of the latency. But that's a hack for the particular rates here, I'd prefer a general solution. Maybe there is some way to purge the buffer of all but the latest image? I have googled but can't find the right words for such a thing if it exists.

(Strange I have never noticed this effect before -- all my other cv codes have been driven by the frame rate of the camera, blocking on cap.read, but this is the first time I've needed the timer to come from elsewhere.)

edit retag flag offensive close merge delete

Comments

note, that this is only a v4l problem (other captures, e.g. dshow do not have such buffering)

berak gravatar imageberak ( 2016-07-27 02:32:07 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-07-26 05:53:22 -0600

This is known behaviour and sadly there is no straightforward way of solving it. There is also no way of telling OpenCV to always flush the buffer, because that depends on the manufacturer of the camera. So there are several solutions to this problem.

  1. Install the development API of the camera provided and use the developer settings to put the camera on a buffer lenght of a single frame. Most camera's with a buffer do support this.
  2. If your camera does not support this, then use OpenCV to discard the buffer size, before grabbing a new frame. This can be done with a simple for loop, which is a loop simply reading headers of frames, calling them from buffer but immediatly discarding them, your loop should for example run 50 times before using the frame that was lastly captured.

The overhead on the second approach is so minimal that it can be ignored in most cases.

edit flag offensive delete link more

Comments

How can you just read the headers? Are you referring to cap->grab() or some other way I don't know about?

yonib gravatar imageyonib ( 2016-12-27 14:25:52 -0600 )edit

Simple cap >> frame; pushing in a continuous loop.

StevenPuttemans gravatar imageStevenPuttemans ( 2017-01-02 05:02:44 -0600 )edit

Can you give a code to do it in python to flush not able to get. Cant do cap>frame as cap is videovapture object.

kritesh gravatar imagekritesh ( 2019-01-17 02:14:12 -0600 )edit

Euhm python does have the frame retrieval functions that you can loop. Just use cap.read() which does exactly the same as the overload >> operator.

StevenPuttemans gravatar imageStevenPuttemans ( 2019-01-18 03:20:58 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2016-07-25 15:51:06 -0600

Seen: 6,294 times

Last updated: Jul 26 '16