int method = 0;
std::vector<cv::KeyPoint> keypoints_object, keypoints_scene;
cv::Mat descriptors_object, descriptors_scene;
cv::ORB orb;
int minHessian = 500;
//cv::OrbFeatureDetector detector(500);
//ORB orb(25, 1.0f, 2, 10, 0, 2, 0, 10);
cv::OrbFeatureDetector detector(25, 1.0f, 2, 10, 0, 2, 0, 10);
//cv::OrbFeatureDetector detector(500,1.20000004768,8,31,0,2,ORB::HARRIS_SCORE,31);
cv::OrbDescriptorExtractor extractor;
//-- object
if( method == 0 ) { //-- ORB
orb.detect(img_object, keypoints_object);
//cv::drawKeypoints(img_object, keypoints_object, img_object, cv::Scalar(0,255,255));
//cv::imshow("template", img_object);
orb.compute(img_object, keypoints_object, descriptors_object);
} else { //-- SURF test
detector.detect(img_object, keypoints_object);
extractor.compute(img_object, keypoints_object, descriptors_object);
}
// http://stackoverflow.com/a/11798593
//if(descriptors_object.type() != CV_32F)
// descriptors_object.convertTo(descriptors_object, CV_32F);
//for(;;) {
cv::Mat frame = cv::imread("E:\\Projects\\Images\\2-134-2.bmp", 1);
cv::Mat img_scene = cv::Mat(frame.size(), CV_8UC1);
cv::cvtColor(frame, img_scene, cv::COLOR_RGB2GRAY);
//frame.copyTo(img_scene);
if( method == 0 ) { //-- ORB
orb.detect(img_scene, keypoints_scene);
orb.compute(img_scene, keypoints_scene, descriptors_scene);
} else { //-- SURF
detector.detect(img_scene, keypoints_scene);
extractor.compute(img_scene, keypoints_scene, descriptors_scene);
}
//-- matching descriptor vectors using FLANN matcher
cv::BFMatcher matcher;
std::vector<cv::DMatch> matches;
cv::Mat img_matches;
if(!descriptors_object.empty() && !descriptors_scene.empty()) {
matcher.match (descriptors_object, descriptors_scene, matches);
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min idstance 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< cv::DMatch >good_matches;
for( int i = 0; i < descriptors_object.rows; i++ )
{ if( matches[i].distance < (max_dist/1.6) )
{ good_matches.push_back( matches[i]); }
}
cv::drawMatches(img_object, keypoints_object, img_scene, keypoints_scene, \
good_matches, img_matches, cv::Scalar::all(-1), cv::Scalar::all(-1),
std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
//-- localize the object
std::vector<cv::Point2f> obj;
std::vector<cv::Point2f> scene;
for( size_t 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 );
}
if( !obj.empty() && !scene.empty() && good_matches.size() >= 4) {
cv::Mat H = cv::findHomography( obj, scene, cv::RANSAC );
//-- get the corners from the object to be detected
std::vector<cv::Point2f> obj_corners(4);
obj_corners[0] = cv::Point(0,0);
obj_corners[1] = cv::Point(img_object.cols,0);
obj_corners[2] = cv::Point(img_object.cols,img_object.rows);
obj_corners[3] = cv::Point(0,img_object.rows);
std::vector<cv::Point2f> scene_corners(4);
cv::perspectiveTransform( obj_corners, scene_corners, H);
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
cv::line( img_matches, \
scene_corners[0] + cv::Point2f(img_object.cols, 0), \
scene_corners[1] + cv::Point2f(img_object.cols, 0), \
cv::Scalar(0,255,0), 4 );
cv::line( img_matches, \
scene_corners[1] + cv::Point2f(img_object.cols, 0), \
scene_corners[2] + cv::Point2f(img_object.cols, 0), \
cv::Scalar(0,255,0), 4 );
cv::line( img_matches, \
scene_corners[2] + cv::Point2f(img_object.cols, 0), \
scene_corners[3] + cv::Point2f(img_object.cols, 0), \
cv::Scalar(0,255,0), 4 );
cv::line( img_matches, \
scene_corners[3] + cv::Point2f(img_object.cols, 0), \
scene_corners[0] + cv::Point2f(img_object.cols, 0), \
cv::Scalar(0,255,0), 4 );
}
}
t =(double) getTickCount() - t;
printf("Time :%f",(double)(t*1000./getTickFrequency()));
cv::imshow("match result", img_matches );
cv::waitKey();
return 0;
Here I am performing template matching between two Images. where I extract key points using ORB algorithm and matching that with BF Matcher but I am not getting good result. Here I am adding Image to understand problem
Here as you can see Dark Blue line on teddy which is actually a rectangle which would be drawn around object from frame Image when object will be recognized by matching key points. Here I am using Opencv 2.4.9, what changes should I make to get good result?
In any feature detection+extraction followed by a homography estimation, there are many parameters you can play with. However the main point to realise is that it's almost always the issue of Computation Time VS. Accuracy.
The most crucial fail point of your code is your ORB initialization:
cv::OrbFeatureDetector detector(25, 1.0f, 2, 10, 0, 2, 0, 10);
1.0f
means you don't change the scale between octaves, this makes no sense, especially since your third parameter is the number of levels which is 2 and not 1. The default is 1.2f
for scale and 8
levels, for less calculations, use a scaling of 1.5f
and 4
levels (again, just a suggestion, other parameters will work too).ORB::FAST_SCORE
instead of the ORB::HARRIS_SCORE
but it doesn't matter much.Last but not least, when you initialise the BruteForce Matcher object, you should remember to use the cv::NORM_HAMMING
type since ORB is a binary feature, this will make the norm calculations on the matching process actually mean something.