Hi! Im trying to track and object through feature detection. The code of example I have works very well using all the matches. But, to make it "better", i would like to use only the best matches. Then I select them, but when I use drawMatches the program doesnt work. Here is my code:
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
VideoCapture cap(0); // open the video camera no. 0
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the video cam" << endl;
return -1;
}
double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
cout << "Frame size : " << dWidth << " x " << dHeight << endl;
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
Mat img1 = imread( "ake.jpg", CV_LOAD_IMAGE_GRAYSCALE );
OrbFeatureDetector detector;
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
// computing descriptors
OrbDescriptorExtractor extractor(32);
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
BFMatcher matcher(NORM_L2,true);
vector<DMatch> matches;
while (1)
{
Mat img2;
cap >> img2;
detector.detect(img2, keypoints2);
// computing descriptors
extractor.compute(img2, keypoints2, descriptors2);
//FlannBasedMatcher matcher;
//std::vector< DMatch > matches;
matcher.match(descriptors1, descriptors2, matches);
double max_dist = 0; double min_dist = 100;
for( int i = 0; i < descriptors1.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
//-- or a small arbitary value ( 0.02 ) in the event that min_dist is very
//-- small)
//-- PS.- radiusMatch can also be used here.
vector< DMatch > good_matches;
for( int i = 0; i < descriptors1.rows; i++ )
{ if( matches[i].distance <= max(2*min_dist, 0.02) )
{ good_matches.push_back( matches[i]); }
}
Mat img_matches;
drawMatches( img1, keypoints1, img2, keypoints2,good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
imshow("MyVideo", img_matches); //show the frame in "MyVideo" window
if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
And this is the error:
OpenCV Error: Assertion failed (i1 >= 0 && i1 < static_cast<int>(keypoints1.size())) in drawMatches, file /home/edrone/Documents/OpenCV/opencv-2.4.9/modules/features2d/src/draw.cpp, line 207
terminate called after throwing an instance of 'cv::Exception'
what(): /home/edrone/Documents/OpenCV/opencv-2.4.9/modules/features2d/src/draw.cpp:207: error: (-215) i1 >= 0 && i1 < static_cast<int>(keypoints1.size()) in function drawMatches
However, if i dont use good_matches but matches, it works.
I hope someone can help me Thanks!