opencv4.0.1 的編譯完成版本已經沒有SIFT和SURF算法了, 一些算法因爲專利或者未成熟的原因,不在發佈的release版本中了,其中就包括SIFT和SURF,他們因爲專利的原因不能用於商業,在2.x版本中,放在在nofree中,而3.x版本開始,這些方法被放入了opencv_contrib中,如果想使用需要自己編譯到opencv中。
這裏需要自己編譯OpenCV4.0.1 + opencv_contrib4.0.1 具體方法可參考我的另一篇博客【OpenCV】opencv4.0.1+opencv_contrib4.0.1+VS2015的編譯
以下是實現的SUFR算法 如果使用SIFT稍微改下即可
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
int main()
{
cv::Mat imageL = cv::imread("imgL.bmp");
cv::Mat imageR = cv::imread("imgR.bmp");
//提取特徵點方法
//SIFT
//cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
//ORB
//cv::Ptr<cv::ORB> orb = cv::ORB::create();
//SURF
cv::Ptr<cv::xfeatures2d::SURF> surf = cv::xfeatures2d::SURF::create();
//特徵點
std::vector<cv::KeyPoint> keyPointL, keyPointR;
//單獨提取特徵點
surf->detect(imageL, keyPointL);
surf->detect(imageR, keyPointR);
//畫特徵點
cv::Mat keyPointImageL;
cv::Mat keyPointImageR;
drawKeypoints(imageL, keyPointL, keyPointImageL, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
drawKeypoints(imageR, keyPointR, keyPointImageR, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
//顯示窗口
cv::namedWindow("KeyPoints of imageL");
cv::namedWindow("KeyPoints of imageR");
//顯示特徵點
cv::imshow("KeyPoints of imageL", keyPointImageL);
cv::imshow("KeyPoints of imageR", keyPointImageR);
//特徵點匹配
cv::Mat despL, despR;
//提取特徵點並計算特徵描述子
surf->detectAndCompute(imageL, cv::Mat(), keyPointL, despL);
surf->detectAndCompute(imageR, cv::Mat(), keyPointR, despR);
//Struct for DMatch: query descriptor index, train descriptor index, train image index and distance between descriptors.
//int queryIdx –>是測試圖像的特徵點描述符(descriptor)的下標,同時也是描述符對應特徵點(keypoint)的下標。
//int trainIdx –> 是樣本圖像的特徵點描述符的下標,同樣也是相應的特徵點的下標。
//int imgIdx –>當樣本是多張圖像的話有用。
//float distance –>代表這一對匹配的特徵點描述符(本質是向量)的歐氏距離,數值越小也就說明兩個特徵點越相像。
std::vector<cv::DMatch> matches;
//如果採用flannBased方法 那麼 desp通過orb的到的類型不同需要先轉換類型
if (despL.type() != CV_32F || despR.type() != CV_32F)
{
despL.convertTo(despL, CV_32F);
despR.convertTo(despR, CV_32F);
}
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("FlannBased");
matcher->match(despL, despR, matches);
//計算特徵點距離的最大值
double maxDist = 0;
for (int i = 0; i < despL.rows; i++)
{
double dist = matches[i].distance;
if (dist > maxDist)
maxDist = dist;
}
//挑選好的匹配點
std::vector< cv::DMatch > good_matches;
for (int i = 0; i < despL.rows; i++)
{
if (matches[i].distance < 0.5*maxDist)
{
good_matches.push_back(matches[i]);
}
}
cv::Mat imageOutput;
cv::drawMatches(imageL, keyPointL, imageR, keyPointR, good_matches, imageOutput);
cv::namedWindow("picture of matching");
cv::imshow("picture of matching", imageOutput);
cv::waitKey(0);
return 0;
}