You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
3.8 KiB
138 lines
3.8 KiB
#include "Arith_FeaMatch.h"
|
|
#include "Arith_GeoSolver.h"
|
|
using std::vector;
|
|
using cv::KeyPoint;
|
|
|
|
// 构造函数
|
|
FeatureMatcher::FeatureMatcher(DetectorType detectorType, MatcherType matcherType)
|
|
: detectorType_(detectorType), matcherType_(matcherType)
|
|
{
|
|
initDetector();
|
|
initMatcher();
|
|
}
|
|
|
|
// 提取特征点和描述符
|
|
void FeatureMatcher::extractFeatures(cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, cv::Mat& descriptors)
|
|
{
|
|
detector_->detectAndCompute(image, cv::noArray(), keypoints, descriptors);
|
|
}
|
|
|
|
// 匹配特征点
|
|
void FeatureMatcher::matchFeatures(cv::Mat& descriptors1, cv::Mat& descriptors2, std::vector<cv::DMatch>& matches)
|
|
{
|
|
if (matcherType_ == FLANN)
|
|
{
|
|
flannMatcher_->match(descriptors1, descriptors2, matches);
|
|
}
|
|
else
|
|
{
|
|
bfMatcher_->match(descriptors1, descriptors2, matches);
|
|
}
|
|
}
|
|
|
|
void FeatureMatcher::matchFeatures_WithH(vector<KeyPoint> keypoints1, cv::Mat& descriptors1, vector<KeyPoint> keypoints2, cv::Mat& descriptors2, cv::Mat H1, cv::Mat H2, std::vector<cv::DMatch>& matches)
|
|
{
|
|
std::vector<cv::DMatch> _matches;
|
|
if (matcherType_ == FLANN)
|
|
{
|
|
flannMatcher_->match(descriptors1, descriptors2, _matches);
|
|
}
|
|
else
|
|
{
|
|
bfMatcher_->match(descriptors1, descriptors2, _matches);
|
|
}
|
|
|
|
int i, j;
|
|
double minimaDsit = 99999;
|
|
for (i = 0; i < _matches.size(); i++)
|
|
{
|
|
double dist = _matches[i].distance;
|
|
if (dist < minimaDsit)
|
|
{
|
|
minimaDsit = dist;
|
|
}
|
|
}
|
|
double fitedThreshold = minimaDsit * 10;
|
|
|
|
for (size_t i = 0; i < _matches.size(); i++)
|
|
{
|
|
cv::DMatch mc = _matches[i];
|
|
|
|
if (mc.distance > fitedThreshold)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
auto warp_pt1 = warpPointWithH(H1, keypoints1[mc.queryIdx].pt);
|
|
auto warp_pt2 = warpPointWithH(H2, keypoints2[mc.trainIdx].pt);
|
|
|
|
if (fabs(warp_pt1.x - warp_pt2.x) + fabs(warp_pt1.y - warp_pt2.y) < 15)
|
|
{
|
|
matches.push_back(mc);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 计算单应性矩阵
|
|
cv::Mat FeatureMatcher::computeHomography(std::vector<cv::KeyPoint>& keypoints1, std::vector<cv::KeyPoint>& keypoints2,
|
|
std::vector<cv::DMatch>& matches, double ransacReprojThreshold)
|
|
{
|
|
std::vector<cv::Point2f> points1, points2;
|
|
for (const auto& match : matches)
|
|
{
|
|
points1.push_back(keypoints1[match.queryIdx].pt);
|
|
points2.push_back(keypoints2[match.trainIdx].pt);
|
|
}
|
|
return cv::findHomography(points1, points2, cv::RANSAC, ransacReprojThreshold);
|
|
}
|
|
|
|
// 初始化特征检测器
|
|
void FeatureMatcher::initDetector()
|
|
{
|
|
switch (detectorType_)
|
|
{
|
|
case SIFT:
|
|
detector_ = cv::SIFT::create(FEA_NUM_MAX);
|
|
break;
|
|
case SURF:
|
|
//detector_ = cv::xfeatures2d::SURF::create();
|
|
#ifdef HAVE_OPENCV_XFEATURES2D
|
|
detector_ = cv::xfeatures2d::SURF::create();
|
|
#else
|
|
throw std::runtime_error("SURF is not supported in this OpenCV build.");
|
|
#endif
|
|
break;
|
|
case ORB:
|
|
detector_ = cv::ORB::create(FEA_NUM_MAX);
|
|
break;
|
|
default:
|
|
throw std::invalid_argument("Unsupported feature detector type");
|
|
}
|
|
}
|
|
|
|
// 初始化匹配器
|
|
void FeatureMatcher::initMatcher()
|
|
{
|
|
if (matcherType_ == FLANN)
|
|
{
|
|
if (detectorType_ == SIFT || detectorType_ == SURF)
|
|
{
|
|
flannMatcher_ = cv::FlannBasedMatcher::create();
|
|
}
|
|
else
|
|
{
|
|
flannMatcher_ = cv::makePtr<cv::FlannBasedMatcher>(cv::FlannBasedMatcher(cv::makePtr<cv::flann::LshIndexParams>(12, 20, 2)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (detectorType_ == SIFT || detectorType_ == SURF)
|
|
{
|
|
bfMatcher_ = cv::BFMatcher::create(cv::NORM_L2);
|
|
}
|
|
else
|
|
{
|
|
bfMatcher_ = cv::BFMatcher::create(cv::NORM_HAMMING);
|
|
}
|
|
}
|
|
} |