无奈返回到opencv的头文件中去寻找关于匹配部分的函数。返回查找KeyPoint类下的函数,发现一个非常有意思的函数。如下:
- CV_WRAP static void convert(const std::vector<Point2f>& points2f,
- CV_OUT std::vector<KeyPoint>& keypoints,
- float size=1, float response=1, int octave=0, int class_id=-1);
不多说了,直接上代码!
1.主函数
main.cpp文件
- //--------------------------------------【程序说明】-------------------------------------------
- // 程序说明:参考了《OpenCV3编程入门》OpenCV3版书本配套示例程序88
- // 程序描述:亚像素级角点检测匹配
- // 开发测试所用操作系统: Windows 7 64bit
- // 开发测试所用IDE版本:Visual Studio 2010
- // 开发测试所用OpenCV版本: 3.0 betarExtra
- // 2014年11月 Created by @yiweixianyi
- // 2014年12月 Revised by @yiweixianyi
- //------------------------------------------------------------------------------------------------
- //---------------------------------【头文件、命名空间包含部分】----------------------------
- // 描述:包含程序所使用的头文件和命名空间
- //------------------------------------------------------------------------------------------------
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- #include <iostream>
- #include "harris.h"
- #include "harrismatch.h"
- using namespace cv;
- using namespace std;
- //-----------------------------------【宏定义部分】--------------------------------------------
- // 描述:定义一些辅助宏
- //----------------------------------------------------------------------------------------------
- #define WINDOW_NAME "【亚像素级角点检测】" //为窗口标题定义的宏
- //-----------------------------------【ShowHelpText( )函数】----------------------------------
- // 描述:输出一些帮助信息
- //----------------------------------------------------------------------------------------------
- static void ShowHelpText( )
- {
- //输出欢迎信息和OpenCV版本
- printf("\n\n ----------------------------------------------------------------------------\n");
- //输出一些帮助信息
- printf("\n\t欢迎来到【亚像素级角点检测】示例程序\n\n");
- printf("\n\t请调整滑动条观察图像效果\n\n");
- }
- //--------------------------------------【main( )函数】-----------------------------------------
- // 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
- //-----------------------------------------------------------------------------------------------
- int main( )
- {
- int keypointnum=300;
- int matchnum=50;
- Mat g_srcImage1, g_srcImage2;
- vector<KeyPoint> keypoints1,keypoints2;
- //【0】改变console字体颜色
- system("color 2F");
- //【0】显示帮助文字
- ShowHelpText();
- //【1】载入源图像并将其转换为灰度图
- g_srcImage1 = imread("1.jpg", 1 );
- g_srcImage2 = imread("1.jpg", 1 );
- //cvtColor( g_srcImage, g_grayImage, COLOR_BGR2GRAY );
- //【2】创建窗口和滑动条,并进行显示和回调函数初始化
- //namedWindow( WINDOW_NAME, WINDOW_AUTOSIZE );
- //createTrackbar( "最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack );
- on_GoodFeaturesToTrack( g_srcImage1, keypoints1,keypointnum );
- on_GoodFeaturesToTrack( g_srcImage2, keypoints2,keypointnum );
- //imshow( WINDOW_NAME, g_srcImage );
- harrismatch(g_srcImage1, g_srcImage2, keypoints1,keypoints2,matchnum);
- waitKey(0);
- return(0);
- }
harris.h文件
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- #include <iostream>
- using namespace cv;
- using namespace std;
- #define WINDOW_NAME "【亚像素级角点检测】" //为窗口标题定义的宏
- void on_GoodFeaturesToTrack(Mat g_srcImage, vector<KeyPoint>& keypoints,int g_maxCornerNumber );
harris.cpp文件
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- #include <iostream>
- #include "harris.h"
- using namespace cv;
- using namespace std;
- 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( copy, 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);
- }
3.角点匹配
harrismatch.h文件
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- #include <iostream>
- #include <opencv2/opencv.hpp>
- #include <vector>
- using namespace cv;
- using namespace std;
- void harrismatch(Mat img1, Mat img2, vector<KeyPoint> keyImg1,vector<KeyPoint> keyImg2,int matchnum);
harrismatch.cpp文件
- #include "opencv2/highgui/highgui.hpp"
- #include "opencv2/imgproc/imgproc.hpp"
- #include "opencv2/xfeatures2d/nonfree.hpp"
- #include <opencv2/xfeatures2d.hpp>
- #include <iostream>
- #include "harrismatch.h"
- using namespace cv;
- using namespace std;
- 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);
- waitKey();
- }