opencv中sift特征提取的步驟
- 使用SiftFeatureDetector 的detect方法檢測特征存入一個向量里拷泽,并使用drawKeypoints在圖中標識出來
- SiftDescriptorExtractor 的compute方法提取特征描述符振湾,特征描述符是一個矩陣
- 使用匹配器matcher對描述符進行匹配,匹配結果保存由DMatch的組成的向量里
- 設置距離閾值,使得匹配的向量距離小于最小距離的2被才能進入最終的結果准颓,用DrawMatch可以顯示
代碼
// 使用Flann進行特征點匹配.cpp : 定義控制臺應用程序的入口點食磕。
//
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <highgui/highgui.hpp>
#include <features2d/features2d.hpp>
#include <nonfree/nonfree.hpp>
#include <vector>
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Mat input1 = imread("E://code//test//image//box.png", 1);
Mat input2 = imread("E://code//test//image//box_in_scene.jpg", 1);
if (input1.empty()||input2.empty())
{
cout << "不能正常加載圖片" << endl;
system("pause");
return -1;
}
/************************************************************************/
/*下面進行提取特征點*/
/************************************************************************/
SiftFeatureDetector feature;
vector<KeyPoint> kerpoints1;
feature.detect(input1, kerpoints1);
Mat output1;
drawKeypoints(input1, kerpoints1, output1);
vector<KeyPoint> kerpoints2;
feature.detect(input2, kerpoints2);
Mat output2;
drawKeypoints(input2, kerpoints2, output2);
imshow("提取特征點后的box.png", output1);
imshow("提取特征點后的box_in_scene.png", output2);
imwrite("提取特征點后的box.png", output1);
imwrite("提取特征點后的box_in_scene.png", output2);
cout << "box提取的特征點數(shù)為:" << kerpoints1.size() << endl;
cout << "box_in_scene的特征點數(shù)為:" << kerpoints2.size() << endl;
/************************************************************************/
/* 下面進行特征向量提取 */
/************************************************************************/
SiftDescriptorExtractor descript;
Mat description1;
descript.compute(input1, kerpoints1, description1);
Mat description2;
descript.compute(input2, kerpoints2, description2);
/************************************************************************/
/* 下面進行特征向量臨近匹配 */
/************************************************************************/
vector<DMatch> matches;
FlannBasedMatcher matcher;
Mat image_match;
matcher.match(description1, description2, matches);
/************************************************************************/
/* 下面計算向量距離的最大值與最小值 */
/************************************************************************/
double max_dist = 0, min_dist = 100;
for (int i = 0; i < description1.rows; i++)
{
if (matches.at(i).distance>max_dist)
{
max_dist = matches[i].distance;
}
if (matches[i].distance<min_dist)
{
min_dist = matches[i].distance;
}
}
cout << "最小距離為" << min_dist << endl;
cout << "最大距離為" << max_dist << endl;
/************************************************************************/
/* 得到距離小于而V誒最小距離的匹配 */
/************************************************************************/
vector<DMatch> good_matches;
for (int i = 0; i < matches.size(); i++)
{
if (matches[i].distance<2*min_dist)
{
good_matches.push_back(matches[i]);
cout <<"第一個圖中的"<< matches[i].queryIdx<<"匹配了第二個圖中的"<<matches[i].trainIdx<<endl;
}
}
drawMatches(input1, kerpoints1, input2, kerpoints2, good_matches, image_match);
imshow("匹配后的圖片", image_match);
imwrite("匹配后的圖片.png", image_match);
cout << "匹配的特征點數(shù)為:" << good_matches.size() << endl;
waitKey(0);
return 0;
}
程序運行前的原始圖片
box.png
box_in_scene.png
提取特征點后
box提取特征后.png
box_in_scene提取特征后
進行匹配后
匹配特征后.png
Paste_Image.png
Paste_Image.png
相關代碼介紹
double max_dist = 0, min_dist = 100;
for (int i = 0; i < description1.rows; i++)
{
if (matches.at(i).distance>max_dist)
{
max_dist = matches[i].distance;
}
if (matches[i].distance<min_dist)
{
min_dist = matches[i].distance;
}
}
設置閾值,當特征向量的距離在最小距離的二倍范圍內的戚哎,匹配為好的匹配;
本博文由時尚時尚最時尚的markdown編輯器編寫.