简体   繁体   中英

OpenCV VideoCapture C++: reading 2 frames gives the same picture

I am writing a program with a for loop that captures two different frames in each iteration of the for loop. My webcam is directed at something that is constantly changing.

The 1st and second frame within a single iteration of the for loop are different from each other, as expected. However, many times (but not all of the time), the 2nd frame of the i'th iteration of the for loop looks the exact same as the 1st frame of the (i+1)th iteration of the for loop. Why does this happen? Here is my code...

 #include "opencv2/core/core.hpp"
 #include "opencv2/features2d/features2d.hpp"
 #include "opencv2/nonfree/features2d.hpp"
 #include "opencv2/calib3d/calib3d.hpp"
 #include "opencv2/highgui/highgui.hpp"
 #include "opencv2/nonfree/nonfree.hpp"
 #include "opencv2/imgproc/imgproc.hpp"


 #include <iostream>
 #include <fstream>
 #include <sstream>
 #include <stdlib.h>

 using namespace cv;
 using namespace std;


 int main(int argc, const char *argv[]) {
//open webcam to capture video from it
int choice;
cout << " 1. Save frames and homography matrices to file.\n";
cout << " 2. Read in frames and homography matrices from file.\n";
cin >> choice;
 // Choice 1: output
if (choice == 1){
cout << "You picked choice 1!";
VideoCapture cap(0);
if(!cap.isOpened())  
    return -1;

Mat frame1c; // will hold the i'th frame, color
Mat frame1; // ^^, grayscale
Mat frame2c; // will hold the (i+1)'th frame, color
Mat frame2; // ^^, grayscale
std::vector<Mat> theframes; // will hold all the frames
int myvar;
string Hmatrices; // will hold all values of all H matrices.
std::stringstream s;  //used for converting the numerical values to a string

//for(;;){
for(int i = 0; i<10; i++){
// Capture the two frames
    cvWaitKey(500);
    cap.read(frame1c);
    cvWaitKey(200);
    cap.read(frame2c);
    cvWaitKey(200);

    cvtColor(frame1c,frame1,CV_RGB2GRAY);
    cvtColor(frame2c,frame2,CV_RGB2GRAY);

//Detect points on the 2 successive images
    int minHessian = 400;
    SurfFeatureDetector detector(minHessian);
    std::vector<KeyPoint> keypoints1, keypoints2;
    detector.detect(frame1, keypoints1);
    detector.detect(frame2, keypoints2);
// If not enough keypoints are found (e.g. when ThinkPad webcam displays black screen initially),
// then go to the next iteration of the For loop.

    if (keypoints1.size() < 4){
        cout << "   keypoints size <4\n\n";
        continue;
    }

// If the frames have keypoints, save them to "theframes"
    cout << "pushback " << i << " f1c\n";
    theframes.push_back(frame1c.clone());
    cout << "pushback " << i << " f2c\n";
    theframes.push_back(frame2c.clone());

// Calculate feature-vectors of the points
    SurfDescriptorExtractor extractor;
    Mat descriptors1, descriptors2;
    extractor.compute(frame1, keypoints1, descriptors1);
    extractor.compute(frame2, keypoints2, descriptors2);

// Match points on the 2 successive images by comparing feature-vectors
    FlannBasedMatcher matcher;
    std::vector<DMatch> matches;
    matcher.match(descriptors1, descriptors2, matches);
    cout << " all matches size is " << matches.size();

//Eliminate weaker matches
    double maxdist = 0; 
    double mindist = 100;
    for (int j = 0; j < descriptors1.rows; j++){
        double dist = matches[j].distance;
        if( dist < mindist ) mindist = dist;
        if( dist > maxdist ) maxdist = dist;
    }

//build the list of "good" matches
    std::vector<DMatch> goodmatches;
    for( int k = 0; k < descriptors1.rows; k++ ){
        if( matches[k].distance <= 3*mindist ){
            goodmatches.push_back(matches[k]); 
        }
    }


//Now compute homography matrix  between the stronger matches

    //-- Localize the object
    std::vector<Point2f> obj;
    std::vector<Point2f> scene;
    cout << "goodmatches size is " << goodmatches.size();
    unsigned int i;
    std::stringstream s;
    for(int l = 0; l < goodmatches.size(); l++){
    //-- Get the keypoints from the good matches
    obj.push_back(keypoints1[goodmatches[l].queryIdx].pt);
    scene.push_back(keypoints2[goodmatches[l].trainIdx].pt);
    }

    Mat Hmatrix;
    cout << "obj size is " << obj.size();
    Hmatrix = findHomography(obj, scene, CV_RANSAC);

    cout << "found the hmatrix\n";

            //from http://computer-vision-talks.com/articles/2013-06-07-undocumented-opencv/ 
            //The documentation of cv::findHomography does not state it, but return value of cv::findHomography was always 3x3 matrix of CV_64FC1 type
            //cv_64fc1 is type double
            // so can do cout << M.at<double>(0,0), cout << M.at<double>(0,1), etc

// Save the values of the H matrix into the Hmatrices string
    s << Hmatrix.at<double>(0,0) << " ";
    s << Hmatrix.at<double>(0,1) << " ";
    s << Hmatrix.at<double>(0,2) << " ";

    s << Hmatrix.at<double>(1,0) << " ";
    s << Hmatrix.at<double>(1,1) << " ";
    s << Hmatrix.at<double>(1,2) << " ";

    s << Hmatrix.at<double>(2,0) << " ";
    s << Hmatrix.at<double>(2,1) << " ";
    s << Hmatrix.at<double>(2,2) << "\n";
    Hmatrices = Hmatrices + s.str();
    /*
    std::string test = s.str();

    cout << "now printing matrix " << test << " and done"; */

}//end for loop

//std::string tosave = s.str();
cout << "now printing matrix " << Hmatrices << " and done";
ofstream savetofile;
savetofile.open("hmatrices.txt");
Hmatrices.pop_back();
savetofile << Hmatrices;
savetofile.close();

// Save theframes to jpeg files:
for(int m = 0; m<theframes.size(); m++){
    cout << "saving to jpg" << m << "num\n";
    imwrite("frame" + std::to_string((long long)m) + ".jpg", theframes[m]);
    cout << "made it after theframes i \n";
    cout << "inforloop theframes size " << theframes.size() << " that\n";
}
int theint;
cin >> theint;

return 0;}

 //Choice 2: Read in
else{
string filename;
cout << "You picked choice 2!";
cout << "Enter name of file with the homography matrices: ";
cin >> filename;
cout << "\nYou entered the filename " << filename << "\n";

// Read in homography matrices
ifstream readh;
readh.open(filename);
vector <double[3]> hs;
int counter = 0;
int i = 0;
cout << "made it this far";
vector<Mat> thematrices;
double dataforMat [3][3];
while(readh>>dataforMat[0][0]>>dataforMat[0][1]>>dataforMat[0][2]>>dataforMat[1][0]>>dataforMat[1][1]>>dataforMat[1][2]>>dataforMat[2][0]>>dataforMat[2][1]>>dataforMat[2][2]){
    cout << "made it to whileloop iteration number " << i;
    thematrices.push_back(Mat(3,3,CV_64FC1,dataforMat));
    cout << "now printing matrix in mat form..\n";
    cout << thematrices[i];
    cout << "\nfinished printing mat matrix\n";
    i++;
}

int numh = thematrices.size();
vector<Mat> theimages;

// Read in image files, named i.jpg for i = 1,2,3,.....
for(int n = 0; n < numh; n++){
    theimages.push_back(imread("frame" + std::to_string((long long)n) + ".jpg"));
}

    imshow("title",theimages[0]);
    waitKey(1000);

    imshow("title",theimages[1]);
    waitKey(1000);

    imshow("title",theimages[2]);
    waitKey(1000);

    imshow("title",theimages[3]);
    waitKey(1000);

/*
int theint;
cin >> theint;*/

return 0;}
return 0;
}

What is the fps of your camera? It's quite possible that in you loop you are reading the last frame from camera and when you try to read it again (second time in loop) there is no new frame so the camera gives the latest frame.
Try to check whether frames are equal and if so read next frame till you get 'something new'. And if you want to be sure that images are equal compare both images using subtract function and than call countNonZero . If the result will be 0, images are equal.

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