简体   繁体   中英

Capturing camera frames once a while

I have a system that is typically running a scan time of 100 HZ or 10 ms and performing time critical tasks. I'm trying to add a camera with opencv to once a while (depends on when a user interacts with the system so it can be anywhere from 10 seconds pauses to minutes) capture an image for quality control. Here is what my code is doing:

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if(!cap.isOpened())  // check if we succeeded
        return -1;

    UMat frame;
    for(;;){
        if (timing_variable_100Hz){
            cap >> frame; // get a new frame from camera

            *Do something time critical*
            if(some_criteria_is_met){
                if(!frame.empty())   imwrite( "Image.jpg", frame);
            }
        }
    }
    return 0;
}

Now the issue I'm having is that cap >> frame takes a lot of time.

My scan time regularly runs around 3ms and now it's at 40ms. Now my question is, are there anyway to open the camera, capture, then not have to capture every frame after until I have to? I tried to move the cap >> frame inside the if(some_criteria_is_met) which allowed me to capture the first image correctly but the second image which was taken a few minutes later was a single frame past the first captured image (I hope that makes sense).

Thanks

The problem is that your camera has a framerate of less than 100fps, probably 30fps (according to the 32ms you measured), so grab wait for a new frame to be available.

Since there is no way to do a non blocking read in opencv, i think that your best option is to do the video grabbing in another thread.

Something like this, if you use c++11 (this is an example, not sure it is entirely correct):

void camera_loop(std::atomic<bool> &capture, std::atomic<bool> &stop)
{
    VideoCapture cap(0);
    Mat frame;
    while(!stop)
    {
        cap.grab();
        if(capture)
        {
           cap.retrieve(frame);
           // do whatever you do with the frame
           capture=false;
        }
    }
}

int main()
{
    std::atomic<bool> capture=false, stop=false;
    std::thread camera_thread(camera_loop, std::ref(capture), std::ref(stop));
    for(;;)
    {
        // do something time critical
        if(some_criteria_is_met)
        {
            capture=true;
        }
    }
    stop=true;
    camera_thread.join();
}

It doesn't answer your question of are there anyway to open the camera, capture, then not have to capture every frame after until I have to? , but a suggestion

You could try and have the cap >> frame in a background thread which is responsible only for capturing the frames.

Once the frame is in memory, push it to some sort of shared cyclic queue to be accessed from the main thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM