本文主要是介绍OpenCV的SIFT特征点提取及RANSAC去除误检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
关于SIFT的讲解,参考:http://blog.csdn.net/zddblog/article/details/7521424
关于SANCAS的讲解,参考:http://blog.csdn.net/laobai1015/article/details/51682596
RANSAC(Random Sample Consensus)随机抽样一致算法在calib3d文件内集成。
主要的思路是:
(1)利用SiftFeatureDetector类对象提取SIFT特征点;
(2)利用SiftDescriptorExtractor类对象进行特征点的特征提取;
(3)利用BFMatcher类对象实现初步匹配;
(注意:在第3步中,实际上已经完成SIFT特征点的提取与匹配,但是会有较多的无匹配,因此后面的步骤主要思路是利用RANSAC方法去除误匹配)
(4)利用2-范数特征阈值初步筛选去除误匹配;
(6)利用findFundamentalMat函数实现RANSAC算法。
文件头如下:
- #include <opencv2/opencv.hpp>
- #include <iostream>
- #include <opencv2/nonfree/nonfree.hpp>
- #include <opencv2/features2d/features2d.hpp>
代码如下:
- Mat Limg = imread("Limage.png", CV_LOAD_IMAGE_ANYDEPTH);
- Mat Rimg = imread("Rimage.png", CV_LOAD_IMAGE_ANYDEPTH);
- // detecting keypoints
- SiftFeatureDetector detector(0, 3, 0.04, 10, 1.6);
- // (特征点数目-按sift特征质量排序,金字塔中每组的层数,过滤的阈值,边缘效应阈值,高斯滤波系数)
- vector<KeyPoint> Lkeypoints, Rkeypoints;
- detector.detect(Limg, Lkeypoints);
- detector.detect(Rimg, Rkeypoints);
- // computing descriptors
- // SiftDescriptorExtractor extractor;
- SiftDescriptorExtractor extractor;
- Mat Ldescriptors, Rdescriptors;
- extractor.compute(Limg, Lkeypoints, Ldescriptors);
- extractor.compute(Rimg, Rkeypoints, Rdescriptors);
- // matching descriptors
- BFMatcher matcher(NORM_L1); //> 对应sift
- vector<DMatch> matches;
- matcher.match(Ldescriptors, Rdescriptors, matches);
- //
- namedWindow("matches", CV_WINDOW_FREERATIO);
- Mat img_matches;
- drawMatches(Limg, Lkeypoints, Rimg, Rkeypoints, matches, img_matches);
- imshow("matches", img_matches);
- // coordination of match-feature-point
- vector<Point2f> Lp, Rp;
- for (size_t m = 0; m < matches.size(); m++)
- {
- int i1 = matches[m].queryIdx;
- int i2 = matches[m].trainIdx;
- Mat Ldesc = Ldescriptors.row(i1);
- Mat Rdesc = Rdescriptors.row(i2);
- double EuclideanDist = norm(Ldesc, Rdesc);
- if (EuclideanDist <= 50)
- {
- const KeyPoint &kp1 = Lkeypoints[i1], &kp2 = Rkeypoints[i2];
- Lp.push_back(kp1.pt);
- Rp.push_back(kp2.pt);
- }
- }
- // 用RANSAC方法计算基本矩阵&去除误匹配
- Mat Fundamental;
- vector<uchar> RANSACStatus;
- Fundamental = findFundamentalMat(Lp, Rp, RANSACStatus, CV_FM_RANSAC, 3.0, 0.995);
- // 筛选特征点
- vector<Point2f> Lpoint, Rpoint;
- vector<DMatch> m_match;
- int idxnum = 0;
- for (int i = 0; i < RANSACStatus.size(); i++)
- {
- if (RANSACStatus[i] != 0)
- {
- Lpoint.push_back(Lp[i]);
- Rpoint.push_back(Rp[i]);
- idxnum++;
- }
- }
- m_match.resize(idxnum);
- for (int idx = 0; idx < idxnum; idx++)
- {
- // 用于匹配验证
- m_match[idx].queryIdx = idx;
- m_match[idx].trainIdx = idx;
- }
- // 把内点转换为drawMatches可以使用的格式
- vector<KeyPoint> Lkp(idxnum);
- vector<KeyPoint> Rkp(idxnum);
- KeyPoint::convert(Lpoint, Lkp);
- KeyPoint::convert(Rpoint, Rkp);
- // 显示筛选后的特征点
- namedWindow("m_match", CV_WINDOW_FREERATIO);
- Mat m_matches;
- drawMatches(Limg, Lkp, Rimg, Rkp, m_match, m_matches);
- imshow("m_match", m_matches);
其中,
第20-23行展示的是SIFT特征点经过BFMatch之后的结果,一般来说误匹配较多,效果不理想;
第70-73行展示的是SIFT特征点经过RANSAC之后的结果,一般来说效果好很多。
这篇关于OpenCV的SIFT特征点提取及RANSAC去除误检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!