void CSIFTMatchingDlg::ImageShift()
{
初始化模块,使用SIFT或SURF时用到(注意需要包含头文件nonfree.hpp
cv::initModule_nonfree();
cv::MathTemplateImage = cv::imread("E:\\机器视觉测试样本图像\\201512\\电阻\\1-1.bmp");
cv::MathSrcImage = cv::imread("E:\\机器视觉测试样本图像\\201512\\电阻\\20151113-092950078-BW.bmp");
//检测特征点
cv::Ptr<cv::FeatureDetector>featureDetector = cv::FeatureDetector::create("SIFT");
if(featureDetector->empty())
{
AfxMessageBox("特征侦测器为空");
return;
}
cv::vector<cv::KeyPoint>hTemplateKeyPoint, hSrcKeyPoint;
featureDetector->detect(hTemplateImage,hTemplateKeyPoint);
featureDetector->detect(hSrcImage,hSrcKeyPoint);
//根据特征点计算特征描述子矩阵,即特征向量矩阵
cv::Ptr<cv::DescriptorExtractor>descriptorExtractor = cv::DescriptorExtractor::create("SIFT");
if(descriptorExtractor->empty())
{
AfxMessageBox("特征向量生成器为空");
return;
}
cv::MathTemplateDescriptors, hSrcTemplateDescriptors;
descriptorExtractor->compute(hTemplateImage,hTemplateKeyPoint, hTemplateDescriptors);
descriptorExtractor->compute(hSrcImage,hSrcKeyPoint, hSrcTemplateDescriptors);
//特征匹配
cv::Ptr<cv::DescriptorMatcher>descriptor_matcher = cv::DescriptorMatcher::create("BruteForce");
cv::vector<cv::DMatch>vdMatches;
descriptor_matcher->match(hTemplateDescriptors,hSrcTemplateDescriptors, vdMatches);
筛选匹配结果
intnMinDis = 100, nMaxDis = 0;
for(int i = 0; i < vdMatches.size(); i++)
{
if(nMinDis > vdMatches[i].distance)
nMinDis= vdMatches[i].distance;
if(nMaxDis < vdMatches[i].distance)
nMaxDis= vdMatches[i].distance;
}
cv::vector<cv::DMatch>vdGoodMatches;
for(int i = 0; i < vdMatches.size(); i++)
{
if(vdMatches[i].distance < nMaxDis * 0.3)
vdGoodMatches.push_back(vdMatches[i]);
}
//画出匹配结果
cv::MatmMatchResult;
cv::drawMatches(hTemplateImage,hTemplateKeyPoint, hSrcImage, hSrcKeyPoint, vdGoodMatches, mMatchResult,cv::Scalar::all(-1), CV_RGB(0, 255, 0), cv::Mat(),cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imshow("Matchingresult",mMatchResult);
}
代码解析
1、FeatureDetector
2D图像特征检测基类
classCV_EXPORTSFeatureDetector
{
public:
virtual~FeatureDetector();
void detect(const Mat& image, vector<KeyPoint>& keypoints,
const Mat& mask=Mat() ) const;
void detect(const vector<Mat>& images,
vector<vector<KeyPoint>>& keypoints,
const vector<Mat>& masks=vector<Mat>() )const;
virtualvoidread(const FileNode&);
virtualvoid write(FileStorage&)const;
static Ptr<FeatureDetector> create( const string& detectorType );
protected:
...
};
不能直接定义生成,只能通过调用create生成。
1.1 FeatureDetector::create
创建特征检测变量,例如:cv::Ptr<cv::FeatureDetector> featureDetector =cv::FeatureDetector::create("SIFT");
"FAST" – FastFeatureDetector
"STAR" – StarFeatureDetector
"SIFT" – SIFT (nonfree module)
"SURF" – SURF (nonfree module)
"ORB" – ORB
"BRISK" – BRISK
"MSER" – MSER
"GFTT" – GoodFeaturesToTrackDetector
"HARRIS" – GoodFeaturesToTrackDetector withHarris detector enabled
"Dense" – DenseFeatureDetector
"SimpleBlob" – SimpleBlobDetector
1.2 FeatureDetector::detect
检测图像或者图像集中的特征点
图像特征点计算描述符抽象基类。
classCV_EXPORTS DescriptorExtractor
{
public:
virtual~DescriptorExtractor();
void compute( const Mat& image, vector<KeyPoint>& keypoints,
Mat& descriptors ) const;
void compute( const vector<Mat>& images, vector<vector<KeyPoint>>& keypoints,
vector<Mat>& descriptors ) const;
virtualvoidread(const FileNode& );
virtualvoid write( FileStorage& ) const;
virtualint descriptorSize() const=0;
virtualint descriptorType() const=0;
static Ptr<DescriptorExtractor> create( const string& descriptorExtractorType );
protected:
...
};
不能直接定义生成,只能通过调用create生成。
2.1 DescriptorExtractor::create
创建描述符生成类,例如:cv::Ptr<cv::DescriptorExtractor>descriptorExtractor = cv::DescriptorExtractor::create("SIFT");
可传入参数如下:
"SIFT" – SIFT
"SURF" – SURF
"BRIEF" – BriefDescriptorExtractor
"BRISK" – BRISK
"ORB" – ORB
"FREAK" – FREAK
2.2 DescriptorExtractor::compute
计算特征点的描述符
匹配特征向量的抽象类
classDescriptorMatcher
{
public:
virtual~DescriptorMatcher();
virtualvoidadd(const vector<Mat>& descriptors );
const vector<Mat>& getTrainDescriptors() const;
virtualvoidclear();
bool empty() const;
virtualbool isMaskSupported() const=0;
virtualvoidtrain();
/*
* Group of methods to match descriptors from an image pair.
*/
void match( const Mat& queryDescriptors, const Mat& trainDescriptors,
vector<DMatch>& matches, const Mat& mask=Mat() ) const;
void knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
vector<vector<DMatch>>& matches, int k,
const Mat& mask=Mat(),bool compactResult=false ) const;
void radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors,
vector<vector<DMatch>>& matches, float maxDistance,
const Mat& mask=Mat(),bool compactResult=false ) const;
/*
* Group of methods to match descriptors from one image to an image set.
*/
voidmatch(const Mat& queryDescriptors, vector<DMatch>& matches,
const vector<Mat>& masks=vector<Mat>() );
voidknnMatch(const Mat& queryDescriptors, vector<vector<DMatch>>& matches,
int k, const vector<Mat>& masks=vector<Mat>(),
bool compactResult=false );
voidradiusMatch(const Mat& queryDescriptors, vector<vector<DMatch>>& matches,
float maxDistance, const vector<Mat>& masks=vector<Mat>(),
bool compactResult=false );
virtualvoidread(const FileNode& );
virtualvoid write( FileStorage& ) const;
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const=0;
static Ptr<DescriptorMatcher> create( const string& descriptorMatcherType );
protected:
vector<Mat> trainDescCollection;
...
};
3.1 DescriptorMatcher::create
创建特征匹配类,例如:cv::Ptr<cv::DescriptorMatcher>descriptor_matcher = cv::DescriptorMatcher::create("BruteForce");
可传入的参数如下:
BruteForce (ituses L2 )
BruteForce-L1
BruteForce-Hamming
BruteForce-Hamming(2)
FlannBased
3.2 DescriptorMatcher::match
特征匹配计算
4、drawMatches
显示匹配结果
计算结果: