opencv2随书自带的代码,如果直接有会报错,头文件部分需要加些东西才行。
robustmatch.cpp:
}
matcher.h
#if !defined MATCHER
#define MATCHER
#include
#include
#include
#include
#include
class RobustMatcher {
private:
// pointer to the feature point detector object特征点检测对象的指针
cv::Ptr
// pointer to the feature descriptor extractor object特征描述符提取器对象的指针
cv::Ptr
float ratio; // max ratio between 1st and 2nd NN
bool refineF; // if true will refine the F matrix
double distance; // min distance to epipolar
double confidence; // confidence level (probability)
public:
RobustMatcher() : ratio(0.65f), refineF(true), confidence(0.99), distance(3.0) {
// SURF is the default feature SURF是默认的算法
detector= new cv::SurfFeatureDetector();
extractor= new cv::SurfDescriptorExtractor();
}
// Set the feature detector设置特征检测器
void setFeatureDetector(cv::Ptr
detector= detect;
}
// Set descriptor extractor设置描述符提取器
void setDescriptorExtractor(cv::Ptr
extractor= desc;
}
// Set the minimum distance to epipolar in RANSAC设置最小距离RANSAC核线
void setMinDistanceToEpipolar(double d) {
distance= d;
}
// Set confidence level in RANSAC设置RANSAC信心水平
void setConfidenceLevel(double c) {
confidence= c;
}
// Set the NN ratio设置NN比
void setRatio(float r) {
ratio= r;
}
// if you want the F matrix to be recalculated如果你想要重新计算F矩阵
void refineFundamental(bool flag) {
refineF= flag;
}
// Clear matches for which NN ratio is bigger than threshold清除NN比大于阈值的匹配
// return the number of removed points 返回移除的点的数目
// (corresponding entries being cleared, i.e. size will be 0)
int ratioTest(std::vector
int removed=0;
// for all matches对于所有的匹配
for (std::vector
matchIterator!= matches.end(); ++matchIterator) {
// if 2 NN has been identified如果2NN已经被确认
if (matchIterator->size() > 1) {
// check distance ratio检查距离比
if ((*matchIterator)[0].distance/(*matchIterator)[1].distance > ratio) {
matchIterator->clear(); // remove match清除匹配
removed++;
}
} else { // does not have 2 neighbours//没有两个邻居
matchIterator->clear(); // remove match清除匹配
removed++;
}
}
return removed;
}
// Insert symmetrical matches in symMatches vector插入对称匹配symMatches向量
void symmetryTest(const std::vector
const std::vector
std::vector
// for all matches image 1 -> image 2 对于所有图1到图2的匹配
for (std::vector
matchIterator1!= matches1.end(); ++matchIterator1) {
if (matchIterator1->size() < 2) // ignore deleted matches
continue;
// for all matches image 2 -> image 1 对于所有图2到图1的匹配
for (std::vector
matchIterator2!= matches2.end(); ++matchIterator2) {
if (matchIterator2->size() < 2) // ignore deleted matches
continue;
// Match symmetry test 对称性匹配测试
if ((*matchIterator1)[0].queryIdx == (*matchIterator2)[0].trainIdx &&
(*matchIterator2)[0].queryIdx == (*matchIterator1)[0].trainIdx) {
// add symmetrical match添加对称匹配
symMatches.push_back(cv::DMatch((*matchIterator1)[0].queryIdx,
(*matchIterator1)[0].trainIdx,
(*matchIterator1)[0].distance));
break; // next match in image 1 -> image 2
}
}
}
}
// Identify good matches using RANSAC确定好使用RANSAC匹配
// Return fundemental matrix返回基本矩阵
cv::Mat ransacTest(const std::vector
const std::vector
const std::vector
std::vector
// Convert keypoints into Point2f 关键点转换成Point2f
std::vector
for (std::vector
it!= matches.end(); ++it) {
// Get the position of left keypoints得到左图关键点的位置
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints得到右图关键点的位置
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}
// Compute F matrix using RANSAC使用RANSAC计算F矩阵
std::vector
cv::Mat fundemental= cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matching points
inliers, // match status (inlier ou outlier)
CV_FM_RANSAC, // RANSAC method
distance, // distance to epipolar line
confidence); // confidence probability
// extract the surviving (inliers) matches提取存在的(内窗层)匹配
std::vector
std::vector
// for all matches对于所有的匹配
for ( ;itIn!= inliers.end(); ++itIn, ++itM) {
if (*itIn) { // it is a valid match这是一个有效匹配
outMatches.push_back(*itM);
}
}
std::cout << "Number of matched points (after cleaning): " << outMatches.size() << std::endl;
if (refineF) {
// The F matrix will be recomputed with all accepted matchesF矩阵根据所有已接收到匹配重新计算
// Convert keypoints into Point2f for final F computation关键点转换成Point2f 以计算最终的F
points1.clear();
points2.clear();
for (std::vector
it!= outMatches.end(); ++it) {
// Get the position of left keypoints得到左图关键点的位置
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints得到右图关键点的位置
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}
// Compute 8-point F from all accepted matches从所有接收到匹配计算8个点的 F
fundemental= cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matching points
CV_FM_8POINT); // 8-point method
}
return fundemental;
}
// Match feature points using symmetry test and RANSAC使用对称测试和RANSAC匹配特征点
// returns fundemental matrix返回基本矩阵
cv::Mat match(cv::Mat& image1, cv::Mat& image2, // input images
std::vector
std::vector
// 1a. Detection of the SURF features SURF 特征检测
detector->detect(image1,keypoints1);
detector->detect(image2,keypoints2);
std::cout << "Number of SURF points (1): " << keypoints1.size() << std::endl;
std::cout << "Number of SURF points (2): " << keypoints2.size() << std::endl;
// 1b. Extraction of the SURF descriptors提取SURF描述符
cv::Mat descriptors1, descriptors2;
extractor->compute(image1,keypoints1,descriptors1);
extractor->compute(image2,keypoints2,descriptors2);
std::cout << "descriptor matrix size: " << descriptors1.rows << " by " << descriptors1.cols << std::endl;
// 2. Match the two image descriptors匹配两幅图像的描述符
// Construction of the matcher 构建匹配
cv::BruteForceMatcher
// from image 1 to image 2从图像1到图像2
// based on k nearest neighbours (with k=2)基于k个最近的邻居
std::vector
matcher.knnMatch(descriptors1,descriptors2,
matches1, // vector of matches (up to 2 per entry) 匹配向量
2); // return 2 nearest neighbours返回两个最近的邻居
// from image 2 to image 1从图像1到图像2
// based on k nearest neighbours (with k=2)
std::vector
matcher.knnMatch(descriptors2,descriptors1,
matches2, // vector of matches (up to 2 per entry)
2); // return 2 nearest neighbours
std::cout << "Number of matched points 1->2: " << matches1.size() << std::endl;
std::cout << "Number of matched points 2->1: " << matches2.size() << std::endl;
// 3. Remove matches for which NN ratio is bigger than threshold删除NN比大于阈值的匹配
// clean image 1 -> image 2 matches删除图像1到图像2的匹配
int removed= ratioTest(matches1);
std::cout << "Number of matched points 1->2 (ratio test) : " << matches1.size()-removed << std::endl;
// clean image 2 -> image 1 matches删除图像2到图像1的匹配
removed= ratioTest(matches2);
std::cout << "Number of matched points 1->2 (ratio test) : " << matches2.size()-removed << std::endl;
// 4. Remove non-symmetrical matches删除不对称匹配
std::vector
symmetryTest(matches1,matches2,symMatches);
std::cout << "Number of matched points (symmetry test): " << symMatches.size() << std::endl;
// 5. Validate matches using RANSAC 使用RANSAC验证匹配
cv::Mat fundemental= ransacTest(symMatches, keypoints1, keypoints2, matches);
// return the found fundemental matrix返回找到的基本矩阵
return fundemental;
}
};
#endif