FLANN matcher-OPENCV 3-min max disatance
I have some code which uses the Flann matcher and ORB detector to find features between two images of a person. I'm using opencv 3 on ubuntu. I have a few doubts.. The Code is as follows:
#include <iostream>
#include </home/sruthi/opencv/include/opencv2/opencv.hpp>
using namespace cv;
//void readme();
/** @function main */
int main(int argc, char** argv)
{
if( argc != 3 )
{ //readme();
return -1; }
Mat img_object = imread( argv[1], IMREAD_GRAYSCALE );
Mat img_scene = imread( argv[2], IMREAD_GRAYSCALE );
if (!img_object.data || !img_scene.data)
{
std::cout << " --(!) Error reading images " << std::endl; return -1;
}
//-- Step 1: Detect the keypoints using ORB Detector
Ptr<FeatureDetector> detector = ORB::create();
std::vector<KeyPoint> keypoints_object, keypoints_scene;
detector->detect(img_object, keypoints_object);
detector->detect(img_scene, keypoints_scene);
//-- Step 2: Calculate descriptors (feature vectors)
Ptr<DescriptorExtractor> extractor = ORB::create();
Mat descriptors_object, descriptors_scene;
extractor->compute(img_object, keypoints_object, descriptors_object);
extractor->compute(img_scene, keypoints_scene, descriptors_scene);
descriptors_object.convertTo(descriptors_object,CV_32F);
descriptors_scene.convertTo(descriptors_scene,CV_32F);
//-- Step 3: Matching descriptor vectors using FLANN matcher
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
std::vector< DMatch > matches;
matcher->match(descriptors_object, descriptors_scene, matches);
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for (int i = 0; i < descriptors_object.rows; i++)
{
double dist = matches[i].distance;
if (dist < min_dist) min_dist = dist;
if (dist > max_dist) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist);
printf("-- Min dist : %f \n", min_dist);
//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
std::vector< DMatch > good_matches;
for (int i = 0; i < descriptors_object.rows; i++)
{
if (matches[i].distance < 3 * min_dist)
{
good_matches.push_back(matches[i]);
}
}
Mat img_matches;
drawMatches(img_object, keypoints_object, img_scene, keypoints_scene, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
//-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for (int i = 0; i < good_matches.size(); i++)
{
//-- Get the keypoints from the good matches
obj.push_back(keypoints_object[good_matches[i].queryIdx].pt);
scene.push_back(keypoints_scene[good_matches[i].trainIdx].pt);
}
//-- Show detected matches
imshow( "Good Matches", img_matches );
for( int i = 0; i < (int)good_matches.size(); i++ )
{ printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }
waitKey(0);
return 0;
}
double max_dist = 0; double min_dist = 100; Why do we declare these distances as 0 and 100 respectively? As output I get Max dist : 488.559113 Min dist : 100.000000. It seems wrong.
if (matches[i].distance < 3 * min_dist) { good_matches.push_back(matches[i]); } Why am I not able to change 3min_dist to 2min_dist? I get no matches if I do it.
Is it compulsory that there have to parallel lines as shown in the official documentation. I dont get parallel lines. I'm not able to post a screenshot.
ORB descriptors are binary, you must not use the Flann matcher, but BFMatcher(HAMMING). (also, the float conversion has to go).
it seems, you modified an example, that was using SIFT or SURF originally. the 0..100 values are heuristcal, you have to find your own for a different situation
@berak When I use surf.. I'm getting an error in spite of using the opencv 3 API.
I get the following error:
you need to build with opencv_contrib to get SIFT/SURF, and then it's
xfeatures2d::SURF::create();
@berak is it okay to have the contrib folder outside the opencv source folder?
sure, just put it next to the opencv folder, and point OPENCV_EXTRA_MODULES_PATH in cmake at it
@berak How do I compare an image of person with a set of images of the same person and give out a best match?
not like this. look here
@berak how do I modify //http://docs.opencv.org/modules/contrib/doc/facerec/tutorial/facerec_video_recognition.html to take an image as input?
ahh, cmon, just use imread()