#include <iostream>
#include<opencv2\highgui.hpp>
#include<opencv2\xfeatures2d\nonfree.hpp>
#include<opencv2\opencv.hpp>
#include<opencv2\xfeatures2d.hpp>
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
//角点匹配
void harrismatch(Mat img1, Mat img2, vector<KeyPoint> keyImg1, vector<KeyPoint> keyImg2, int matchnum)
{
Ptr<Feature2D> b = xfeatures2d::SIFT::create();
Ptr<DescriptorMatcher> descriptorMatcher;
// Match between img1 and img2
vector<DMatch> matches;
// Descriptor for img1 and img2
Mat descImg1, descImg2;
// and compute their descriptors with method compute
b->compute(img1, keyImg1, descImg1);
b->compute(img1, keyImg2, descImg2);
// Match method loop
descriptorMatcher = DescriptorMatcher::create("BruteForce-L1");
descriptorMatcher->match(descImg1, descImg2, matches, Mat());
// Keep best matches only to have a nice drawing.
// We sort distance between descriptor matches
Mat index;
int nbMatch = int(matches.size());
Mat tab(nbMatch, 1, CV_32F);
for (int i = 0; i<nbMatch; i++)
{
tab.at<float>(i, 0) = matches[i].distance;
}
sortIdx(tab, index, SORT_EVERY_COLUMN + SORT_ASCENDING);
vector<DMatch> bestMatches;
for (int i = 0; i<matchnum; i++)
{
bestMatches.push_back(matches[index.at<int>(i, 0)]);
}
Mat result;
drawMatches(img1, keyImg1, img2, keyImg2, bestMatches, result);
namedWindow("harris_sift_match", WINDOW_AUTOSIZE);
imshow("harris_sift_match", result);
}
//角点检测
void on_GoodFeaturesToTrack(Mat &g_srcImage, vector<KeyPoint>& keypoints, int g_maxCornerNumber)
{
Mat g_grayImage;
RNG g_rng(12345);//初始化随机数生成器
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
//【1】对变量小于等于1时的处理
if (g_maxCornerNumber <= 1) { g_maxCornerNumber = 1; }
//【2】Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备
vector<Point2f> corners;
double qualityLevel = 0.01;//角点检测可接受的最小特征值
double minDistance = 10;//角点之间的最小距离
int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围
double k = 0.04;//权重系数
Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量中,作为感兴趣区域
//【3】进行Shi-Tomasi角点检测
goodFeaturesToTrack(g_grayImage,//输入图像
corners,//检测到的角点的输出向量
g_maxCornerNumber,//角点的最大数量
qualityLevel,//角点检测可接受的最小特征值
minDistance,//角点之间的最小距离
Mat(),//感兴趣区域
blockSize,//计算导数自相关矩阵时指定的邻域范围
false,//不使用Harris角点检测
k);//权重系数
//【4】输出文字信息
cout << "\n\t>-------------此次检测到的角点数量为:" << corners.size() << endl;
//【5】绘制检测到的角点
int r = 4;
for (unsigned int i = 0; i < corners.size(); i++)
{
//以随机的颜色绘制出角点
circle(g_srcImage, corners[i], r, Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255),
g_rng.uniform(0, 255)), 1, 8, 0);
}
//【6】显示(更新)窗口
//imshow( WINDOW_NAME, copy );
//【7】亚像素角点检测的参数设置
Size winSize = Size(5, 5);
Size zeroZone = Size(-1, -1);
//此句代码的OpenCV2版为:
//TermCriteria criteria = TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001 );
//此句代码的OpenCV3版为:
TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);
//【8】计算出亚像素角点位置
cornerSubPix(g_grayImage, corners, winSize, zeroZone, criteria);
//【9】输出角点信息
// for( int i = 0; i < corners.size(); i++ )
// { cout<<" \t>>精确角点坐标["<<i<<"] ("<<corners[i].x<<","<<corners[i].y<<")"<<endl; }
KeyPoint::convert(corners, keypoints);
}
int main()
{
Mat image01 = imread("1.jpg", 1);
Mat image02 = imread("2.jpg", 1);
if (image01.empty() || image02.empty()) {
cout << "could not find the image..." << endl;
return 0;
}
imshow("p1", image01);
imshow("p2", image02);
Mat copy1 = image01.clone();
Mat copy2 = image02.clone();
//harris角点检测
std::vector<cv::KeyPoint> corners1, corners2;
on_GoodFeaturesToTrack(image01, corners1, 100);
on_GoodFeaturesToTrack(image02, corners2, 100);
imshow("harimage01", image01);
imshow("harimage02", image02);
//角点检测后进行sift特征匹配
int matchnum = corners1.size() > corners2.size() ? corners2.size() : corners1.size();
harrismatch(copy1, copy2, corners1, corners2, matchnum);
waitKey();
}