本文將介紹Surf特徵匹配得到的特徵匹配點提純方法
surf匹配代碼:
cv::Ptr<Feature2D> p_ex1 = xfeatures2d::SURF::create();//生成對應描述符
p_ex1->detect(thisFHalf_1, thisFrameKeypoints);
p_ex1->detect(nextFHalf_2, nextFrameKeypoints);
p_ex1->compute(thisFHalf_1, thisFrameKeypoints, thisFrameDescriptor);
p_ex1->compute(nextFHalf_2, nextFrameKeypoints, nextFrameDescriptor);
std::vector< cv::DMatch > matches_1;
//std::vector< cv::DMatch > matches_2;
std::vector<cv::DMatch> good_matches;
std::vector<cv::DMatch> good_matches2;
BFMatcher matcher;
//FlannBasedMatcher matcher;
//matcher.knnMatch()
matcher.match(thisFrameDescriptor, nextFrameDescriptor, matches_1);
獲得匹配點對matches_1,但是surf獲得的匹配點對中存在相當多的誤匹配,如何剔除誤匹配,提取精度較高的匹配點對。
(一)通過距離判斷來提純,這也是常用的方法
//消除錯配點
double min_dist = 100;
double max_dist = 0;
for (int i = 0; i < matches_1.size(); i++)
{
double dist = matches_1[i].distance;
if (dist < min_dist)
{
min_dist = dist;
}
if (dist > max_dist)
{
max_dist = dist;
}
}
//std::vector<cv::DMatch> good_matches;
for (int i = 0; i < matches_1.size(); i++)
{
if (matches_1[i].distance < (3 * min_dist))
{
good_matches.push_back(matches_1[i]);
//surfgoodnum++;
}
}
通常設置3*min_dist,距離越小精度也高,但數量也少。
(二)正反匹配提純
cv::Mat img_match;
int num = 0;
for (int a = 0; a < matches_1.size(); a++)
{
for (int b = 0; b < matches_2.size();b++)
{
if (thisFrameKeypoints[matches_1[a].queryIdx].pt == thisFrameKeypoints[matches_2[b].trainIdx].pt && nextFrameKeypoints[matches_1[a].trainIdx].pt == nextFrameKeypoints[matches_2[b].queryIdx].pt)
{
if (fabs(thisFrameKeypoints[matches_1[a].queryIdx].pt.x - thisFrameKeypoints[matches_1[a].trainIdx].pt.x)<20 && fabs(thisFrameKeypoints[matches_1[a].queryIdx].pt.y - thisFrameKeypoints[matches_1[a].trainIdx].pt.y)<20)
{
good_matches.push_back(matches_1[a]);
}
}
}
}
如果前後都能匹配則認爲該點對爲匹配點對。(效果不佳,只能去除部分)
(三)單應消除錯誤匹配點
//單應去除匹配錯點
<span style="white-space:pre"> </span>std::vector<cv::Point2f> srcPoints_1, dstPoints_1;
<span style="white-space:pre"> </span>for (std::vector< cv::DMatch >::iterator it = matches_1.begin(); it != matches_1.end(); it++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span> srcPoints_1.push_back(thisFrameKeypoints[it->queryIdx].pt);//ThisFrame
<span style="white-space:pre"> </span> dstPoints_1.push_back(nextFrameKeypoints[it->trainIdx].pt);//NextFrame
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>cv::Mat H_1;
<span style="white-space:pre"> </span>float reprojectionThreshold = 0.1;
std::vector<cv::DMatch> inliers;
<span style="white-space:pre"> </span>std::vector<unsigned char> inliersMask(srcPoints_1.size());
<span style="white-space:pre"> </span>H_1 = findHomography(
<span style="white-space:pre"> </span> srcPoints_1, dstPoints_1,
<span style="white-space:pre"> </span> CV_FM_RANSAC, reprojectionThreshold,
<span style="white-space:pre"> </span> inliersMask);
<span style="white-space:pre"> </span> for (size_t i = 0; i < inliersMask.size(); i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span> if (inliersMask[i])
<span style="white-space:pre"> </span>inliers.push_back(matches_1[i]);
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span>matches_1.swap(inliers);
<span style="white-space:pre"> </span>std::cout << matches_1.size() << std::endl;
匹配點對根據RANSAC計算單應矩陣,再根據單應矩陣提純。