I use Sift/Surf and ORB but sometimes i have a problem with the drawMatch function.
Here the error :
OpenCV Error: Assertion failed (i2 >= 0 && i2 < static_cast(keypoints2.size())) in drawMatches, file /home/opencv-2.4.6.1/modules/features2d/src/draw.cpp, line 208 terminate called after throwing an instance of 'cv::Exception' what(): /home/opencv-2.4.6.1/modules/features2d/src/draw.cpp:208: error: (-215) i2 >= 0 && i2 < static_cast(keypoints2.size()) in function drawMatche
The code :
drawMatchPoints(img1,keypoints_img1,img2,keypoints_img2,matches);
I tried to invert img 1,keypoints_img1 with img2 and keypoints_img2 like that :
drawMatchPoints(img2,keypoints_img2,img1,keypoints_img1,matches);
Corresponding to my function who is doing an homography :
void drawMatchPoints(cv::Mat image1,std::vector<KeyPoint> keypoints_img1,
cv::Mat image2,std::vector<KeyPoint> keypoints_img2,std::vector<cv::DMatch> matches){
cv::Mat img_matches;
drawMatches( image1, keypoints_img1, image2, keypoints_img2,
matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
std::cout << "Number of good matching " << (int)matches.size() << "\n" << endl;
//-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for( int i = 0; i < matches.size(); i++ )
{
//-- Get the keypoints from the good matches
obj.push_back( keypoints_img1[ matches[i].queryIdx ].pt );
scene.push_back( keypoints_img2[matches[i].trainIdx ].pt );
}
Mat H = findHomography( obj, scene, CV_RANSAC );
std::cout << "Size of homography " << *H.size << std::endl ;
//-- Get the corners from the image_1 ( the object to be "detected" )
std::vector<Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( image1.cols, 0 );
obj_corners[2] = cvPoint( image1.cols, image1.rows ); obj_corners[3] = cvPoint( 0, image1.rows );
std::vector<Point2f> scene_corners(4);
perspectiveTransform( obj_corners, scene_corners, H);
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
line( img_matches, scene_corners[0] + Point2f( image1.cols, 0), scene_corners[1] + Point2f( image1.cols, 0), Scalar(0, 255, 0), 4 );
line( img_matches, scene_corners[1] + Point2f( image1.cols, 0), scene_corners[2] + Point2f( image1.cols, 0), Scalar( 0, 255, 0), 4 );
line( img_matches, scene_corners[2] + Point2f( image1.cols, 0), scene_corners[3] + Point2f( image1.cols, 0), Scalar( 0, 255, 0), 4 );
line( img_matches, scene_corners[3] + Point2f( image1.cols, 0), scene_corners[0] + Point2f( image1.cols, 0), Scalar( 0, 255, 0), 4 );
//-- Show detected matches
cv::imshow( "Good Matches & Object detection", img_matches );
cv::waitKey(5000);
}
But i have still the error !
I have noticed that the error happened when the size of my keypoints_img1 is lower than the size of my keypoints_img2 :
Size keyPoint1 : 244 - Size keyPoint2 : 400
So if i invert the loading of my two picture, that works but i can't now in advance if my first picture will have more keypoints that my second picture...
My code (the most important step) in order to create the features :
init_Sift(400,5,0.04,25,1.6);
void init_Sift(int nf,int nOctaveL,double contrastThresh, double edgeThresh,double sigma){
this->nfeatureSift=nf;
this->nOctaveLayerSift=nOctaveL;
this->contrastThresholdSift=contrastThresh;
this->edgeThresholdSift=edgeThresh;
this->sigmaSift=sigma;}
cv::FeatureDetector* detector=new SiftFeatureDetector(nfeatureSift,nOctaveLayerSift,contrastThresholdSift,edgeThresholdSift,sigmaSift);
cv::DescriptorExtractor* extractor=new SiftDescriptorExtractor
extractor->compute( image, keypoints, descriptors );
The matching part :
std::cout << "Type of matcher : " << type_of_matcher << std::endl;
if (type_of_matcher=="FLANN" || type_of_matcher=="BF"){
std::vector<KeyPoint> keypoints_img1 = keyfeatures.compute_Keypoints(img1);
std::vector<KeyPoint> keypoints_img2 = keyfeatures.compute_Keypoints(img2);
cv::Mat descriptor_img1 = keyfeatures.compute_Descriptors(img1);
cv::Mat descriptor_img2 = keyfeatures.compute_Descriptors(img2);
std::cout << "Size keyPoint1 " << keypoints_img1.size() << "\n" << std::endl;
std::cout << "Size keyPoint2 " << keypoints_img2.size() << "\n" << std::endl;
//Flann with sift or surf
if (type_of_matcher=="FLANN"){
Debug::info("USING Matcher FLANN");
fLmatcher.match(descriptor_img1,descriptor_img2,matches);
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptor_img1.rows; i++ ){
double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptor_img1.rows; i++ )
{ if( matches[i].distance <= max(2*min_dist, 0.02) )
{ good_matches.push_back( matches[i]); }
}
std::cout << "Size of good match : " << (int)good_matches.size() << std::endl;
//-- Draw only "good" matches
if (!good_matches.empty()){
drawMatchPoints(img1,keypoints_img1,img2,keypoints_img2,good_matches);
}
else {
Debug::error("Flann Matcher : Pas de match");
cv::Mat img_matches;
drawMatches( img1, keypoints_img1, img2, keypoints_img2,
matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
cv::imshow( "No match", img_matches );
cv::waitKey(5000);
}
}
//BruteForce with sift or surf
else if (type_of_matcher=="BF"){
Debug::info("USING Matcher Brute Force");
bFmatcher.match(descriptor_img1,descriptor_img2,matches);
if (!matches.empty()){
std::nth_element(matches.begin(),//Initial position
matches.begin()+24, //Position of the sorted element
matches.end());//End position
matches.erase(matches.begin()+25,matches.end());
drawMatchPoints(img1,keypoints_img1,img2,keypoints_img2,matches);
//drawMatchPoints(img2,keypoints_img2,img1,keypoints_img1,matches);
}
else {
Debug::error("Brute Force matcher : Pas de match");
cv::Mat img_matches;
drawMatches( img1, keypoints_img1, img2, keypoints_img2,
matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
cv::imshow( "No match", img_matches );
cv::waitKey(5000);
}
}
Do you have any suggestions or advises ?
EDIT : i solved my problem. I had a c++ problem, because i had two classes . One about matching and another about finding keyFeature. I have wrote on my .h std::vector and the same for descriptors.
class keyFeatures{
public:
...
std::vector<keyPoint> keypoints;
...
I delete this attribute and i did a function that take in argument std::vector keypoints
cv::Mat descriptor_img1 = keyfeatures.compute_Descriptors(img1,keypoints_img1);
instead of
cv::Mat descriptor_img1 = keyfeatures.compute_Descriptors(img1);
I think there was a conflict when i did the matching... But i don't know why i shouldn't have to write it on my .h and do a local parameter on my function.
Thank you !
For somebody like me who searched for this but couldn't find the solution.
Assertion failed (i2 >= 0 && i2 < static_cast(keypoints2.size()))
This means that assertion failed due to i2 being less than 0 or i2 being less than the keypoints2 size. But what is i2?
From the link that rbaleksandar provided in a comment
int i2 = matches1to2[m].trainIdx;
trainIdx here is an index in keypoints2. The check i2 < static_cast(keypoints2.size()) makes sure that the index is less than keypoints2.size().
For me it occured because I discarded some keypoints before calling drawMatches but after the descriptors were computed i.e. DescriptorExtractor#compute was called. This meant that the drawMatches referred to old keypoints through the descriptors while I changed those keypoints. The end result was that some keypoints had large idx but the keypoints size was small hence the error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With