SIFT和SUFT算法是有相关专利的,所以在opencv中属于"nonfree"里的,在opencv2.x.x版本可能还有保留,但是在opencv3.x.x后就没有了,需要单独下载opencv_contrib库,然后自己Cmake;
相关算法的详解这里不做过多解释了,推举两个大神博客:
1.小魏的修行的博客:http://blog.youkuaiyun.com/xiaowei_cqu/article/details/8069548;
2.赵春江的源码详细分析:http://blog.youkuaiyun.com/zhaocj/article/details/42124473;
3.详细分析算法原理:http://blog.youkuaiyun.com/zddblog/article/details/7521424;
大家可以在网上再看看,相关解释等很多;
下面贴几个简单实例:
sift实例:
void imgSIFT()//SIFT算法
{
//sift算法不是开源的所以很多内容用起来很不方便
//Create SIFT class pointer
Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
//1、读入图片
Mat img_1 = imread("D:/ImageTest/source.png");//模板图片
Mat img_2 = imread("D:/ImageTest/222.JPG");//检测图片
//2、声明检测点;Detect the keypoints
vector<KeyPoint> keypoints_1, keypoints_2;
f2d->detect(img_1, keypoints_1);
f2d->detect(img_2, keypoints_2);
//3、计算描述符(特征向量);Calculate descriptors (feature vectors)
Mat descriptors_1, descriptors_2;
f2d->compute(img_1, keypoints_1, descriptors_1);
f2d->compute(img_2, keypoints_2, descriptors_2);
//4、使用BFMatcher匹配描述符向量;Matching descriptor vector using BFMatcher
BFMatcher matcher;
vector<DMatch> matches;
matcher.match(descriptors_1, descriptors_2, matches);
//5、绘制匹配出的关键点
Mat img_matches;
drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_matches);
imshow("match",img_matches);
//6、匹配结果筛选
nth_element(matches.begin(), matches.begin()+30, matches.end()); //提取出前最佳匹配结果
matches.erase(matches.begin()+30, matches.end()); //剔除掉其余的匹配结果
Mat img_matches2;
drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_matches2);
imshow("match2",img_matches2);
waitKey(0);
}
效果,未过滤:
过滤后:
SURF算法:
void imgSURF()//SURF算法
{
//1、加载图片
Mat img_1 = imread( "D:/ImageTest/source.png", IMREAD_GRAYSCALE );//模板图片
Mat img_2 = imread("D:/ImageTest/222.JPG", IMREAD_GRAYSCALE );//被查找图片
//2、使用SURF检测器检测关键点,计算描述符;Detect the keypoints using SURF Detector, compute the descriptors
int minHessian = 400;
Ptr<SURF> detector = SURF::create();
detector->setHessianThreshold(minHessian);
std::vector<KeyPoint> keypoints_1, keypoints_2;
Mat descriptors_1, descriptors_2;
detector->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1 );
detector->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2 );
//3、匹配描述符向量与一个蛮力匹配;Matching descriptor vectors with a brute force matcher
BFMatcher matcher(NORM_L2);
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
//4、绘制匹配结果;Draw matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2, matches, img_matches );
//5、显示检测到匹配; Show detected matches
imshow("SURF_Matches", img_matches );
//6、匹配结果筛选
nth_element(matches.begin(), matches.begin()+50, matches.end()); //提取出前最佳匹配结果
matches.erase(matches.begin()+50, matches.end()); //剔除掉其余的匹配结果
Mat img_matches2;
drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_matches2);
imshow("SURF_Matches2",img_matches2);
waitKey(0);
}
效果:
SURF算法计算匹配(opencv文档实例),并输出点信息:
void imgSURF2()//SURF算法2
{
Mat img_1 = imread( "D:/ImageTest/source.png", IMREAD_GRAYSCALE );
Mat img_2 = imread("D:/ImageTest/222.JPG", IMREAD_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ std::cout<< " --(!) Error reading images " << std::endl; }
//-- Step 1: Detect the keypoints using SURF Detector, compute the descriptors
int minHessian = 400;
Ptr<SURF> detector = SURF::create();
detector->setHessianThreshold(minHessian);
std::vector<KeyPoint> keypoints_1, keypoints_2;
Mat descriptors_1, descriptors_2;
detector->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1 );
detector->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2 );
//-- Step 2: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_1.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 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.
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_1.rows; i++ )
{ if( matches[i].distance <= max(2*min_dist, 0.02) )
{ good_matches.push_back( matches[i]); }
}
//-- Draw only "good" matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- 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 ); }
cout<<"key:"<<keypoints_1[0].pt.x<<endl;
waitKey(0);
}
效果: