How can I get the most current frame in OpenCV?

I’m trying to take and display the most current frame on any key event. It is important for me that the photo will be taken only once (without using infinity loop). I have a problem because displayed photo is the previous one not the most current. It looks like some buffor with captured frames in VideoCapture object.

I’m using OpenCV 4.6.0 and laptop camera.

#include <iostream>
#include <opencv2/opencv.hpp>

int main() {
    cv::VideoCapture cap0(0);

    cv::Mat frame0;
    for (;;)
    {
        cap0.read(frame0);
        if (!frame0.empty())
        {
            imshow("cap0", frame0);
        }
        cv::waitKey(0);
    }
    return 0;
}

Is it possible to get and display current photo without doing infinity loop whenever I click any key?

crosspost:

Hello Piter217,
this might not be the best or smartest solution but you can capture 4 frames before calling imshow(). This will clear the old frames and leave you with the most current frame. You can do this by calling cap0.read(frame0); multiple times.

note that that number is arbitrary and not justified by any technical fact. there are some hacks to flush the queue, such as setting buffer size to 0 or 1 or something else small that works. the usual way is to run capture in a separate thread and keep a reference to the last captured frame, for the rest of the program to access whenever needed.

the initial post should simply not use waitKey(0) but instead waitKey(1) or pollKey(). all of this was already discussed on Stack Overflow

Thank you for clarifying, I was under the impression that the buffer size defaulted to store 4 frames.

Another way of getting the most current frame from camera might be measuring time of grabing. Usual grab times for web cameras are 20 - 40 ms. If grabbing is faster than this time, you can assume that the frame was copied from buffer, so you can grab again unitil the grabbing time is more than threshold: ~20 ms (50 FPS).

Make sure that the actual grab time is more than the threshold, your code might end up in infinite loop.

A post was merged into an existing topic: How would you synchronize two webcams to be acquiring their images at the same times?

Usual grab times for web cameras are not 20 - 40 ms. The grab time depends on whether your polling the camera to grab comes after it’s grabbed its latest already or whether it’s waiting on its cadence of the requested frame rate (if you’re in streaming mode at least). And it can be even more unexpected since different cameras may have different logic implemented, as the UVC standard keeps things rather open, or conformance to some of its details may not be as stellar. That’s before mentioning host drivers.

It is highly variable, in any event, when putting the webcam into streaming mode at least. Have you been grabbing outside of a streaming mode?