未完。。待续。
参考网址:
http://bbs.sciencenet.cn/blog-261330-540049.html 未完成的讲解博客。
http://www.cnblogs.com/frischzenger/p/3326790.html brisk的中文翻译。
http://www.asl.ethz.ch/people/lestefan/personal/BRISK/index brisk作者官网。
brisk算法可以不严格的实现实时运算。论文原文与现有的stat_of_the_art算法进行时间和效率比较图如下:
可以看出实现一次匹配需要39+29 = 68ms,每秒钟可以计算14张图片。
与freak 、orb算法相同,opencv也实现了brisk。也可以查看brisk作者提供的代码也可以查看opencv实现的代码,在看作者提供的代码的时候一定要使用opencv2.2,版本不能太高,因为高版本已经实现了brisk算法有些class会冲突,而导致不能使用。如果看代码,建议看作者提供的,作者提供的暴露了更多的接口;如果仅仅为了使用,建议使用opencv提供的,opencv提供的bug要少,更健壮些。
算法的粗略归纳:
1.生成图像金字塔。2.使用fast算法检测角点。3.对fast计算出的角点进行非最大值抑制,去掉不符合条件的角点。
使用opencv2.4.8运行自带的brisk算法的代码,从计算角点到匹配成功在我的图片上大概运行了172ms,不能满足实时条件:
#include "highgui.h" #include "cv.h" #include "vector" #include "opencv\cxcore.hpp" #include "iostream" #include "opencv.hpp" #include<opencv2/nonfree/features2d.hpp> #include<opencv2/nonfree/nonfree.hpp> using namespace cv; using namespace std; #include<Windows.h> int main()//(int argc, _TCHAR* argv[]) { //Load Image Mat c_src1 = imread( "hello.jpg"); Mat c_src2 = imread("hello2.jpg"); Mat src1 = imread( "hello.jpg", CV_LOAD_IMAGE_GRAYSCALE); Mat src2 = imread( "hello2.jpg", CV_LOAD_IMAGE_GRAYSCALE); if( !src1.data || !src2.data ) { std::cout<< " --(!) Error reading images " << std::endl; return -1; } //sift feature detect cv::BRISK detector; std::vector<KeyPoint> kp1, kp2; double start = GetTickCount(); detector.detect( src1, kp1 ); detector.detect( src2, kp2 ); //cv::BRISK extractor; Mat des1,des2;//descriptor detector.compute(src1,kp1,des1); detector.compute(src2,kp2,des2); Mat res1,res2; int drawmode = DrawMatchesFlags::DRAW_RICH_KEYPOINTS; drawKeypoints(c_src1,kp1,res1,Scalar::all(-1),drawmode);//在内存中画出特征点 drawKeypoints(c_src2,kp2,res2,Scalar::all(-1),drawmode); cout<<"size of description of Img1: "<<kp1.size()<<endl; cout<<"size of description of Img2: "<<kp2.size()<<endl; BFMatcher matcher(NORM_HAMMING); vector<DMatch> matches; matcher.match(des1,des2,matches); double end = GetTickCount(); cout<<end -start<<endl; Mat img_match; drawMatches(src1,kp1,src2,kp2,matches,img_match);//,Scalar::all(-1),Scalar::all(-1),vector<char>(),drawmode); cout<<"number of matched points: "<<matches.size()<<endl; imshow("matches",img_match); cvWaitKey(); cvDestroyAllWindows(); //cv::SIFT sift ; //sift. return 0; }
版本二:使用摄像头实时采集图像并进行brisk运算。
#include "highgui.h" #include "cv.h" #include "vector" #include "opencv\cxcore.hpp" #include "iostream" #include "opencv.hpp" #include<opencv2/nonfree/features2d.hpp> #include<opencv2/nonfree/nonfree.hpp> using namespace cv; using namespace std; #include<Windows.h> int main()//(int argc, _TCHAR* argv[]) { //Load Image Mat c_src1 = imread( "hello.jpg"); Mat src1 = imread( "hello.jpg", CV_LOAD_IMAGE_GRAYSCALE); cv::BRISK detector; std::vector<KeyPoint> kp1, kp2; detector.detect( src1, kp1 ); Mat des1,des2;//descriptor detector.compute(src1,kp1,des1); Mat res1,res2; int drawmode = DrawMatchesFlags::DRAW_RICH_KEYPOINTS; drawKeypoints(c_src1,kp1,res1,Scalar::all(-1),drawmode);//在内存中画出特征点 BFMatcher matcher(NORM_HAMMING); vector<DMatch> matches; Mat imgMatch; cv::VideoCapture cap(0); Mat frame; Mat frameGray; std::vector<KeyPoint> kpf; Mat desf; Mat img_match; while(1){ cap>>frame; cvtColor(frame,frameGray,CV_RGB2GRAY); detector.detect(frameGray,kpf); if(kpf.empty()) continue; drawKeypoints(frameGray,kpf,frame,Scalar::all(-1),drawmode); detector.compute(frame,kpf,desf); matcher.match(des1,desf,matches); imshow("frame",frame); drawMatches(src1,kp1,frame,kpf,matches,img_match); imshow("match",img_match); waitKey(2); } return 0; }