how to improve orb feature matching? - c++

I am trying to register two binary images. I used opencv orb detector and matcher to generate and match feature points. However, the matching result looks bad. Can anybody tell me why and how to improve? Thanks.
Here are the images and matching result.
Here is the code
OrbFeatureDetector detector; //OrbFeatureDetector detector;SurfFeatureDetector
vector<KeyPoint> keypoints1;
detector.detect(im_edge1, keypoints1);
vector<KeyPoint> keypoints2;
detector.detect(im_edge2, keypoints2);
OrbDescriptorExtractor extractor; //OrbDescriptorExtractor extractor; SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( im_edge1, keypoints1, descriptors_1 );
extractor.compute( im_edge2, keypoints2, descriptors_2 );
//-- Step 3: Matching descriptor vectors with a brute force matcher
BFMatcher matcher(NORM_L2, true); //BFMatcher matcher(NORM_L2);
vector< DMatch> matches;
matcher.match(descriptors_1, descriptors_2, matches);
vector< DMatch > good_matches;
vector<Point2f> featurePoints1;
vector<Point2f> featurePoints2;
for(int i=0; i<int(matches.size()); i++){
good_matches.push_back(matches[i]);
}
//-- Draw only "good" matches
Mat img_matches;
imwrite("img_matches_orb.bmp", img_matches);

ORB descriptors are, unlike SURF, binary descriptors. The HAMMING distance is suited for binary descriptors comparison. Use NORM_HAMMING when initializing your BFMatcher.

Some answers there may be helpful:
Improve matching of feature points with OpenCV
It's for SIFT descriptor, but we can also use them for ORB matching:)

Related

Want to detect features and match the feature in 2 different frames

I'm currently using OpenCV 3.4.0, c++ in QT creator.
I've tried sample code in this page
https://docs.opencv.org/2.4/doc/tutorials/features2d/feature_description/feature_description.html
int minHessian = 400;
cv::xfeatures2d::SurfFeatureDetector detector(minHessian);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// computing descriptors
cv::xfeatures2d::SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
// matching descriptors
BFMatcher matcher(NORM_L2);
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
// drawing the results
namedWindow("matches", 1);
Mat img_matches;
drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
imshow("matches", img_matches);
waitKey(0);
but the code kept returning error
no matching function for call to 'cv::xfeatures2d::SURF::SURF(int&)(2nd line)
cannot declare variable 'detector' to be of abstract type 'cv::xfeatures2d::SURF'(2nd line)
cannot declare variable 'extractor' to be of astract type 'cv::xfeatures2d::SURF'(7th line)
I have imported all the necessary modules I think including xfeatures2d
What is the problem?
And are there any other sample codes that I can try?
Your coding reflects an older version of OpenCV which is not compatible with OpenCV 3.4.0. You can try like so. It is better to convert the template image to a grayscale image for better matching:
cv::Ptr<Feature2D> detector = cv::xfeatures2d::SurfFeatureDetector::create();
detector->detect(img1, keypoints1);
cv::Ptr<DescriptorExtractor> extractor = cv::xfeatures2d::SurfFeatureDetector::create();
extractor->compute(img1, keypoints1, descriptors1);

how to compare size of kepoints matching in opencv

I'm going compare images with SURF detector in opencv. for this work,I need size and Orientation of keypoints that must be compare them. for example, I have to extract keypoints matching of second image larger than keypoints matching of first image. (keypoint 1.size > keypoint 2.size).
question:
how to extract size of keypoints matching in opencv?
I'm not sure if I quite understand your question.
What I understood was that:
You will compare images using keypoints
You want to compare the size of matched keypoints
First u want at least 2 images:
Mat image1; //imread stuff here
Mat image2; //imread stuff here
Then detect keypoints in the two images using SURF:
vector<KeyPoint> keypoints1, keypoints2; //store the keypoints
Ptr<FeatureDetector> detector = new SURF();
detector->detect(image1, keypoints1); //detect keypoints in 'image1' and store them in 'keypoints1'
detector->detect(image2, keypoints2); //detect keypoints in 'image2' and store them in 'keypoints2'
After that compute the descriptors for detected keypoints:
Mat descriptors1, descriptors2;
Ptr<DescriptorExtractor> extractor = new SURF();
extractor->compute(image1, keypoints1, descriptors1);
extractor->compute(image2, keypoints2, descriptors2);
Then match the descriptors of keypoints using for example BruteForce with L2 norm:
BFMatcher matcher(NORM_L2);
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
After these steps matched keypoints were stored in the vector 'matches'
You can get the index of matched keypoints as follows:
//being idx any number between '0' and 'matches.size()'
int keypoint1idx = matches[idx].query; //keypoint of the first image 'image1'
int keypoint2idx = matches[idx].train; //keypoint of the second image 'image2'
Read this for further information:
http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_descriptor_matchers.html
Finally, to know the size of the matched keypoints u can do the following:
int size1 = keypoints1[ keypoint1idx ].size; //size of keypoint in the image1
int size2 = keypoints2[ keypoint2idx ].size; //size of keypoint in the image2
Further info: http://docs.opencv.org/modules/features2d/doc/common_interfaces_of_feature_detectors.html
And that's it! Hope this helps

OpenCV saving image, keypoints and descriptors to file

I'm using SURF/FLANN detector and I'm looking to save the image, points, descriptors to a file so I can then compare this image and it's points to a second image and points however I'm getting the following error when I try to write:
In file included from detectFlannPoints.cpp:4:0:
/usr/local/include/opencv2/features2d/features2d.hpp:112:17: note: void cv::write(cv::FileStorage&, const string&, const std::vector<cv::KeyPoint>&)
/usr/local/include/opencv2/features2d/features2d.hpp:112:17: note: candidate expects 3 arguments, 4 provided
This is the code I'm using to write:
FileStorage fs("Keypoints.yml", FileStorage::WRITE);
write(fs, "templateImageOne", keypoints_1, tempDescriptors_1);
fs.release();
I'm not sure where I can specify the extra argument (tempDescriptors_1) as it works fine with this arg removed.
Code immediatly above the write code:
//Detect the keypoints using SURF Detector
int minHessian = 400;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1;
detector.detect( img_1, keypoints_1 );
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat tempDescriptors_1;
extractor.compute( img_1, keypoints_1, tempDescriptors_1 );
//-- Draw keypoints
Mat img_keypoints_1;
drawKeypoints( img_1, keypoints_1, img_keypoints_1, Scalar::all(-1), DrawMatchesFlags::DEFAULT );
you have to write them one at a time:
FileStorage fs("Keypoints.yml", FileStorage::WRITE);
write(fs, "keypoints_1", keypoints_1);
write(fs, "descriptors_1", tempDescriptors_1);
...
fs.release();

OpenCV, feature matching with code from the tutorial

I copied the code of the Feature Matching with FLANN from the OpenCV tutorial page, and made the following changes:
I used the SIFT features, instead of SURF;
I modified the check for a 'good match'. Instead of
if( matches[i].distance < 2*min_dist )
I used
if( matches[i].distance <= 2*min_dist )
otherwise I would get zero good matches when comparing an image with itself.
Modified parameter in drawing the keypoints:
drawMatches( img1, k1, img2, k2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::DEFAULT);
I extracted the SIFT from all the images in the folder Ireland of the INRIA-Holidays dataset. Then I compared each image to all the others and draw the matches.
However there is a strange problem I have never experienced with any other SIFT/Matcher implementation I used in the past:
the matches for an image I matched against itself are good. Each keypoint is mapped onto itself except for some. See image above.
When I match I against another image J (with J not equal to I), many points are mapped onto the same one. Some examples are below.
Is there anyone who used the same code from the OpenCV tutorial and can report a different experience from mine?
Checkout the matcher_simple.cpp example. It uses a brute force matcher that seems to work pretty well. Here is the code:
// detecting keypoints
SurfFeatureDetector detector(400);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// computing descriptors
SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
// matching descriptors
BFMatcher matcher(NORM_L2);
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
// drawing the results
namedWindow("matches", 1);
Mat img_matches;
drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
imshow("matches", img_matches);
waitKey(0);

OpenCV Matcher - std::bad_alloc exception

I'm trying to stitch together some images to make a sort of panorama. I'm using OpenCV so first thing to do is detect keypoints and descriptors than matching them. To do that I'm following this tutorial: http://opencv.itseez.com/doc/user_guide/ug_features2d.html
But during debug I get a std::bad_alloc exception relative to this line:
matcher.match(descriptors1, descriptors2, matches);
Somebody can help me with that? Because I cutted & pasted the tutorial and there are no compilation errors.
Thanks.
G
Complete code:
Mat img1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat img2 = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
if(img1.empty() || img2.empty())
{
printf("Can't read one of the images\n");
return -1;
}
// detecting keypoints
SurfFeatureDetector detector(400);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img1, keypoints1);
detector.detect(img2, keypoints2);
// computing descriptors
SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img1, keypoints1, descriptors1);
extractor.compute(img2, keypoints2, descriptors2);
// matching descriptors
BruteForceMatcher<L2<float> > matcher;
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
// drawing the results
namedWindow("matches", 1);
Mat img_matches;
drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
imshow("matches", img_matches);
waitKey(0);
Update:
if I run this code, I get a:
Run-Time Check Failure #2 - Stack around the variable 'keypoints1' was corrupted.
Code:
#include "opencv\cv.h"
#include "opencv\highgui.h"
using namespace cv;
using namespace std;
int main()
{
Mat img1 = imread("Chessboard1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat img2 = imread("Chessboard3.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if(img1.empty() || img2.empty())
{
printf("Can't read one of the images\n");
return -1;
}
FastFeatureDetector detector(50);
vector<KeyPoint> keypoints1;
detector.detect(img1, keypoints1);
return 0;
}
You need ensure that the following "Additional Dependencies" under the the Properties->Linker->Input are referring to the correct OpenCV libraries with debugger support.
i.e.
C:\OpenCV2.2\lib\opencv_calib3d220d.lib
C:\OpenCV2.2\lib\opencv_core220d.lib
C:\OpenCV2.2\lib\opencv_features2d220d.lib
C:\OpenCV2.2\lib\opencv_highgui220d.lib
C:\OpenCV2.2\lib\opencv_imgproc220d.lib
instead of
C:\OpenCV2.2\lib\opencv_calib3d220.lib
C:\OpenCV2.2\lib\opencv_core220.lib
C:\OpenCV2.2\lib\opencv_features2d220.lib
C:\OpenCV2.2\lib\opencv_highgui220.lib
C:\OpenCV2.2\lib\opencv_imgproc220.lib