Freak特征描述+BruteForceMatcher匹配+RANSAC剔除误匹配
来源:互联网 发布:魔兽世界月卡 知乎 编辑:程序博客网 时间:2024/04/28 06:53
Freak特征描述+BruteForceMatcher匹配+RANSAC剔除误匹配
时间一晃飞快,前几日的广州之行让人难忘,置身炎热的户外仿佛蒸桑拿一样。这一段时间一直在研究一种从一幅图片中找到给定目标的方法,而基于局部特征提取并且进行特征的匹配可以实现。
目前局部特征描述子有以下几种,
- 2004年发展成熟的SIFT
- 后来改进的SURF,它们的描述符是高维度整型的数字。
- 2010年出现的BRIEF是一种二进制的描述符,这种描述符在提高计算速度方面给出了不错的思路,但是不具备旋转不变,尺度不变,对噪声也比较敏感(虽然它采用了高斯平滑来抗噪声)
- 2011年出现的ORB算法同样是二进制,但是解决了旋转不变和噪声敏感的问题,但是不具备尺度不变性。
- 2011年同时出现了BRISK算法,解决旋转不变,尺度不变和抗噪声问题,网上有视频,实时性也不错,先有个直观认识,爽死。链接[(http://v.youku.com/v_show/id_XMTI5MzI3Mzk0OA==.html)]
- 2012年提出FREAK算法,其实是在BRISK上的改进。具备BRISK的优点。这篇论文中作者表示FREAK算法可以outperform以前所有的描述子。(注意:这里是特征描述子,因为论文中没有给出特征点检测方法,只有特征点的描述子)
看完了综述,我决定用FREAK来实现。足足耗了我15天,今天我这一段所得写下,勉励自己,服务他人。
先贴上代码
/************************************************************************* Copyright(c) 2016 唯疯* All rights reserved.** Brief: FAST特征点提取以及FREAK描述子的图像匹配,基于OpenCV2.4.8* Version: 1.0* Author: 唯疯* Date: 2016/07/21* Address: 广州&北京************************************************************************/#include <opencv2/core/core.hpp>#include <opencv2/features2d/features2d.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/nonfree/features2d.hpp>#include <opencv2/legacy/legacy.hpp>#include <iostream>#include <vector>using namespace std;using namespace cv;int main(){ Mat img1_src = imread("im5.jpg",0); Mat img2_src = imread("im6.jpg",0); //FastFeatureDetector fast(40); SurfFeatureDetector fast(2000,4); FREAK extractor; vector<KeyPoint> keypoints1,keypoints2; Mat descriptor1,descriptor2; vector<DMatch> final_matches; vector<DMatch> matches; double t = (double)getTickCount(); fast.detect(img1_src,keypoints1); fast.detect(img2_src,keypoints2); //drawKeypoints(img1_src,keypoints1,img1_src,Scalar(0,255,0)); //drawKeypoints(img2_src,keypoints2,img2_src,Scalar(0,255,0));//问题在这里!!!醉了,这里的问题,浪费了我5天,欧耶,就是整整5天,由于我想在这里看一看检测出来的特征点是啥样的,就跟父母想第一眼就立刻看到刚出生的婴儿是一个心情的。结果,后来特征匹配就几乎没有什么正确匹配,害我还以为是FREAK这个描述子有问题呢。于是就各种找问题,看论文,翻墙逛论坛。最后一个不经意间发现了。问题就是:这俩个语句是把特征点又原封不动的画到了img1_src中,也就是原图像里面,而后来我进行特征点描述的时候,就直接在画满了特征点的图片下进行描述,而不是原图!不是原图啊!是充满了特征点的图片!所以后期再进行匹配的时候,显然,各种乱匹配,就跟隔壁家小狗似的,见了猫都想干坏事。于是乎,我直接注释掉了这两句! extractor.compute(img1_src,keypoints1,descriptor1); extractor.compute(img2_src,keypoints2,descriptor2); BFMatcher matcher(NORM_HAMMING,true);//暴力匹配,并且进行crosscheck,就是说第二个参数选择true。 matcher.match(descriptor1,descriptor2,matches); final_matches=matches; cout<<"number of total_matches : "<<final_matches.size()<<endl;//接下来是RANSAC剔除误匹配 vector<Point2f> querymatches, trainmatches; vector<KeyPoint> p1,p2; for(int i=0;i<final_matches.size();i++) { p1.push_back(keypoints1[final_matches[i].queryIdx]); p2.push_back(keypoints2[final_matches[i].trainIdx]); } for(int i=0;i<p1.size();i++) { querymatches.push_back(p1[i].pt); trainmatches.push_back(p2[i].pt); } cout<<querymatches[1]<<" and "<<trainmatches[1]<<endl; vector<uchar> status; Mat h = findHomography(querymatches,trainmatches,status,CV_FM_RANSAC,10); int index=0; vector<DMatch> super_final_matches; for (int i=0;i<final_matches.size();i++) { cout<<status[i]; if (status[i] != 0) { super_final_matches.push_back(final_matches[i]); index++; } } cout<<"number of inlier_matches : "<<index<<endl; Mat imgMatch; drawMatches(img1_src,keypoints1,img2_src,keypoints2,super_final_matches,imgMatch); imshow("imgMatch",imgMatch); t = ((double)getTickCount()-t)/getTickFrequency(); cout<<" total time [s] : "<<t<<endl; waitKey(0); return 0;}
一:
首先说说特征点检测,为什么我用surf,而不用速度很快的fast或者Brisk,我自己做了测试,发现用fast和brisk的话,再用freak描述,最终匹配效果并不好,比sift要差…我其实不太明白为什么,因为有一些后期的论文对比效果说freak综合效果最好,然而我却得不到这样的结果。要继续钻研了,大家有想法欢迎交流,哦不,欢迎指点!
二:
RANSAC的这个算法,请用opencv库中的cvFindHomography,不要用cvFindFundamentalMat,因为这两个是不一样的,字面上简单看一个是找到单应性矩阵,一个是找到基础矩阵,这两个到底有神马区别???
《计算机视觉中的多视图几何》中这样描述:
- 2D单应:一幅2D图像中点集到另一幅图像中点集的射影变换。
- 基本矩阵:它使一个队所有的点都是的x`Fx=0成立的奇异矩阵F。这是一个3*3的奇异矩阵,而且秩为2,不可逆。它是2维图像上的点通过对极线束约束的映射,是2维到1维的映射。
具体的大家可以看书或者百度,或者等以后我有空了,再具体描述。其实我也没有太懂哈哈哈!还要再看看!慎言慎言!
之前,我曾经自己编写过一个RANSAC的算法啊,但是效果不是特别理想,由于RANSAC算法本身也比较耗时,各路大神们也都提出了很多改进方法,不知道opencv跟进这些改进算法没有?推荐综述型文章《A Universal Framework for Random
Sample Consensus》,里面提到的prosac,lo-ransac速度提升很多!大家自行汲取,我想以后再写一些关于RANSAC的博文。
三:
代码中用到BFMatcher这个类,对象的参数有两个BFMatcher::BFMatcher(int normType=NORM_L2, bool crossCheck=false )。第一个指的是距离,如果是sift或者surf描述的话,就选择NORM_L2和NORM_L2;ORB,BRISK,FREAK这种二进制的描述子就用汉明距离,也就是NORM_HAMMING;NORM_HAMMING2是用作ORB的。第二个参数是是否crossCheck,最好选择true,这个也经过我实验验证,选择true相当于knn匹配中将k置1,也就是只返回最好的那一组匹配,而不是多个近邻。(注意:如果要用knnmatch的话,这个crossCheck的参数就选择false)。这种只返回最好的一组匹配的方式可以作为ratio test的一种替代选择。实验证明,如果选择false,那么将会返回一对多匹配,和多对一的匹配,后期用ransac的效果可能非常不理想。crossCheck就是交叉匹配,剔除不好的匹配。有论文支撑,大家感兴趣可以去搜。
- Freak特征描述+BruteForceMatcher匹配+RANSAC剔除误匹配
- Freak特征描述+BruteForceMatcher匹配+RANSAC剔除误匹配
- Opencv实现:SIFT特征提取+RANSAC剔除误匹配点
- Opencv实现:SIFT特征提取+RANSAC剔除误匹配点
- FREAK特征匹配
- 【CS】尺度不变特征变换匹配算法SIFT(3):RANSAC剔除错误匹配点
- RANSAC用于SIFT特征匹配
- RANSAC 特征匹配算法解析
- OpenCV3.2 ORB特征点 FLANN BruteForceMatcher匹配
- SURF特征提取(MSAC算法剔除误匹配)
- 利用RANSAC算法筛选SIFT特征匹配
- 利用RANSAC算法筛选SIFT特征匹配
- 利用RANSAC算法筛选SIFT特征匹配
- 利用RANSAC算法筛选SIFT特征匹配
- 利用RANSAC算法筛选SIFT特征匹配
- 利用RANSAC算法筛选SIFT特征匹配
- 利用RANSAC算法筛选SIFT特征匹配
- 利用RANSAC算法筛选SIFT特征匹配
- 中间件漏洞
- CSS 外边距(margin)重叠及防止方法
- Git最简单操作介绍
- Chrome自定义CSS样式的方法
- HDU 1520 Anniversary party
- Freak特征描述+BruteForceMatcher匹配+RANSAC剔除误匹配
- C语言总复习第二阶段部分练习题
- HDU 2795 Billboard(线段树的另类应用)
- 【学习Linux】第一个shell脚本
- 【ASP.NET】——Application、Server和Session对象
- HDU1405
- Open-Source Virtual Reality --- summary1
- 在Unix和Linux的各种操作系统 chmod 777权限
- Android中图片的三层缓存详解