未完。。待续。
参考网址:
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;
}