Ask Your Question
2

try to read different frame by videocapture but failed

asked 2020-09-27 04:55:34 -0600

Aaron666 gravatar image

Hi all, this is my way i try to read and save video's different frame. below is my code, but i found that i got the same images.(i'm sure i keep moving in front of the camera lol)

pls help me to find what i need to do. thanks in advance!!

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <time.h>

using namespace cv;
using namespace std;

int main(int, char**)
{
    Mat frame;
    VideoCapture cap;
    int deviceID = 0;             // 0 = open default camera
    int apiID = cv::CAP_ANY;      // 0 = autodetect default API
    cap.open(deviceID + apiID);

    if (!cap.isOpened()) {
        cerr << "ERROR! Unable to open camera\n";
        return -1;
    }

    //--- GRAB AND WRITE LOOP
    cout << "Start grabbing" << endl
        << "Press any key to terminate" << endl;

int cnt = 0;
Mat frm_test[3];
clock_t start, finish;
start = clock();

for (;;)
{
    // wait for a new frame from camera and store it into 'frame'
    cap.read(frame);
    // check if we succeeded
    if (frame.empty()) {
        cerr << "ERROR! blank frame grabbed\n";
        break;
    }

    finish = clock();
    if ((cnt < 3) && ((finish - start)/CLOCKS_PER_SEC > 1.0)) {
        frm_test[cnt] = frame;
        start = clock();
        cnt++;
    }

        // covert color to gray
        //cvtColor(frame, frame, cv::COLOR_RGB2GRAY);

        // show live and wait for a key with timeout long enough to show images
        imshow("Live", frame);
        if (waitKey(5) >= 0) {
            cout << "Exit requested" << endl;
            destroyAllWindows();
            break;
        }

    }
    // the camera will be deinitialized automatically in VideoCapture destructor

    imshow("frm 1", frm_test[0]);
    imshow("frm 2", frm_test[1]);
    imshow("frm 3", frm_test[2]);

    waitKey(0);
    return 0;
}
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
2

answered 2020-09-27 05:19:06 -0600

berak gravatar image

updated 2020-09-27 05:37:55 -0600

hard to spot, if you don't know it, but easy to explain, i hope ;)

this line:

 frm_test[cnt] = frame;

does a shallow copy ( frm_test[cnt] points to the same data as frame)

and since Mat frame is defined outside the for loop, cap.read(frame) will not allocate new data for it.

so indeed, all items in your frm_test array will point to the same image !

the remedy is either, to move the frame definition inside the for loop, like this:

for (;;)
{
    Mat frame;
    // wait for a new frame from camera and store it into 'frame'
    cap.read(frame);
    ...

so a new Mat will be allocated for each frame

or to use deep copies:

 frm_test[cnt] = frame.clone();
edit flag offensive delete link more

Comments

i see...... i don't really know about shallow and deep copy problem. i'll research it. your answer can work! tks a lot!!

Aaron666 gravatar imageAaron666 ( 2020-09-27 05:59:07 -0600 )edit

in short:

shallow copy:

a = b; // data pointer gets copied, NOT the data, a and b share the same data

deep copy:

a = b.clone(); // a and b have seperate copies of the data
berak gravatar imageberak ( 2020-09-27 06:22:55 -0600 )edit
1

answered 2020-09-27 05:39:55 -0600

try this after reading @berak's explaining answer

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int, char**)
{
    Mat frame;
    VideoCapture cap;
    int deviceID = 0;             // 0 = open default camera
    int apiID = cv::CAP_ANY;      // 0 = autodetect default API
    cap.open(deviceID + apiID);

    if (!cap.isOpened()) {
        cerr << "ERROR! Unable to open camera\n";
        return -1;
    }

    //--- GRAB AND WRITE LOOP
    cout << "Start grabbing" << endl
        << "Press any key to terminate" << endl;

    int cnt = 0;
    Mat frm_test[3];

    for (;;)
    {
        // wait for a new frame from camera and store it into 'frm_test[circular_value]'
        cap.read(frm_test[cnt % 3]);
        // check if we succeeded
        if (frm_test[cnt % 3].empty()) {
            cerr << "ERROR! blank frame grabbed\n";
            break;
        }

        // show live and wait for a key with timeout long enough to show images
        imshow("Live", frm_test[cnt % 3]);
        cnt++;
        if (waitKey(5) >= 0) {
            cout << "Exit requested" << endl;
            destroyAllWindows();
            break;
        }

    }

    imshow("frm 1", frm_test[(cnt-3) % 3]);
    imshow("frm 2", frm_test[(cnt-2) % 3]);
    imshow("frm 3", frm_test[(cnt-1) % 3]);

    waitKey(0);
    return 0;
}
edit flag offensive delete link more

Comments

yes i tried and the solution can work. tks~

Aaron666 gravatar imageAaron666 ( 2020-09-27 06:00:02 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2020-09-27 04:55:34 -0600

Seen: 1,772 times

Last updated: Sep 27 '20