bmp测试图像分辨率491*640
算法参考《opencv图像处理编程实例》第八章8-3
David G. Lowe在1999年提出了尺度不变的特征(Scale-Invariant Feature),用来进行物体的识别和图像匹配等,并于2004年进行了更深入的发展和并加以完善。SIFT(Scale-Invariant Feature Transform)算子是一种图像的局部描述子,具有尺度、旋转、平移的不变性,而且对光照变化、仿射变换和3维投影变换具有一定的鲁棒性。在Mikolajczyk对包括SIFT算子在内的十种局部描述子所做的不变性对比实验中,SIFT及其扩展算法已被证实在同类描述子中具有最强的健壮性。
算法的主要思想是在尺度空间寻找极值点(注意不是平面上的极值点,因此需要过滤掉平面上的极值点),然后对极值点进行过滤,找出稳定的特征点。最后在每个稳定的特征点周围提取图像的局部特性,形成局部描述子并将其用在以后的匹配中。SIFT算法是基于Lindeberg的理论解决了尺度不变性的问题。
关于理论,在网上有很多,现粘贴代码及注释帮助理解。后面给出测试图。
#include "stdafx.h"
#include "PerformaceTimer.h"
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/legacy/legacy.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
cv::Mat srcImage1 = cv::imread("C:\\Users\\lenovo\\Desktop\\设备图片\\3.bmp");
cv::Mat srcImage2 = cv::imread("C:\\Users\\lenovo\\Desktop\\设备图片\\5.jpg");
if (srcImage1.empty() || srcImage2.empty())
return -1;
//计算耗时(自写函数)
CPerformaceTimer Timer;
Timer.Begin();
cv::Mat grayMat1, grayMat2;
cv::cvtColor(srcImage1, grayMat1, CV_RGB2GRAY);
//归一化处理
cv::normalize(grayMat1, grayMat1, 0, 255, cv::NORM_MINMAX);
cv::cvtColor(srcImage2, grayMat2, CV_RGB2GRAY);
cv::normalize(grayMat2, grayMat2, 0, 255, cv::NORM_MINMAX);
//定义SIFT算子
cv::SiftFeatureDetector detector;
cv::SiftDescriptorExtractor extractor;
//特征点检测
std::vector<cv::KeyPoint>keypoints1;
detector.detect(grayMat1, keypoints1);
std::vector<cv::KeyPoint>keypoints2;
detector.detect(grayMat2, keypoints2);
//计算特征点描述子
cv::Mat descriptors1;
extractor.compute(grayMat1, keypoints1, descriptors1);
cv::Mat descriptors2;
extractor.compute(grayMat2, keypoints2, descriptors2);
//特征点匹配
std::vector<cv::DMatch>matches;
cv::BruteForceMatcher<cv::L2<float>>matcher;
//BruteForce匹配
matcher.match(descriptors1, descriptors2, matches);
//二分排列
int N = 80;
nth_element(matches.begin(), matches.begin() + N - 1, matches.end());
//去除特征点不匹配情况
matches.erase(matches.begin() + N, matches.end());
//绘制检测结果
cv::Mat matchMat;
cv::drawMatches(srcImage1, keypoints1, srcImage2, keypoints2, matches, matchMat);
//计算耗时(自写函数)
Timer.End();
double dTime = Timer.GetTime();
printf("算法耗时:%f毫秒", dTime);
cv::imshow("matchMat", matchMat);
cv::waitKey();
return 0;
}
算法耗时约为6000毫秒-左右;第二幅测试图经过了旋转,变形,缩放