OpenCV学习笔记(四十六)——FAST特征点检测features2D
特征点检测和匹配是计算机视觉中一个很有用的技术。在物体检测,视觉跟踪,三维常年关键等领域都有很广泛的应用。这一次先介绍特征点检测的一种方法——FAST(features from accelerated segment test)。很多传统的算法都很耗时,而且特征点检测算法只是很多复杂图像处理里中的第一步,得不偿失。FAST特征点检测是公认的比较快速的特征点检测方法,只利用周围像素比较的信息就可以得到特征点,简单,有效。
FAST特征检测算法来源于corner的定义,这个定义基于特征点周围的图像灰度值,检测候选特征点周围一圈的像素值,如果候选点周围领域内有足够多的像素点与该候选点的灰度值差别够大,则认为该候选点为一个特征点。
其中I(x)为圆周上任意一点的灰度,I(p)为圆心的灰度,Ed为灰度值差得阈值,如果N大于给定阈值,一般为周围圆圈点的四分之三,则认为p是一个特征点。
为了获得更快的结果,还采用了额外的加速办法。如果测试了候选点周围每隔90度角的4个点,应该至少有3个和候选点的灰度值差足够大,否则则不用再计算其他点,直接认为该候选点不是特征点。候选点周围的圆的选取半径是一个很重要的参数,这里我为了简单高效,采用半径为3,共有16个周边像素需要比较。为了提高比较的效率,通常只使用N个周边像素来比较,也就是大家经常说的FAST-N。我看很多文献推荐FAST-9,作者的主页上有FAST-9、FAST-10、FAST-11、FAST-12,大家使用比较多的是FAST-9和FAST-12。上个图说明的更形象一些
OpenCV里对FAST的使用也非常简单,先声明一组特征点,构建FAST特征检测,接下来调用detect函数检测图像中的特征点,最后把特征点绘制到图片上。上代码说的清楚些
- #include <opencv2/core/core.hpp>
- #include <opencv2/features2d/features2d.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <vector>
- using namespace cv;
- void main()
- {
- Mat image;
- image = imread("church01.jpg");
- // vector of keyPoints
- std::vector<KeyPoint> keyPoints;
- // construction of the fast feature detector object
- FastFeatureDetector fast(40); // 检测的阈值为40
- // feature point detection
- fast.detect(image,keyPoints);
- drawKeypoints(image, keyPoints, image, Scalar::all(255), DrawMatchesFlags::DRAW_OVER_OUTIMG);
- imshow("FAST feature", image);
- cvWaitKey(0);
- }
最后上一张效果图
![](https://img-my.csdn.net/uploads/201203/30/1333097601_3417.png)
OpenCV学习笔记(四十七)——VideoWriter生成视频流highgui
首先要先纠正个误区,我见有人用OpenCV做多媒体开发,真的是很搞笑,OpenCV这东西再强大,这方面也不行的,之所以把视频读取写入这部分做的强大一些,也是为了方便大家做视频处理的时候方便些,而且这部分也是基于vfw和ffmpeg二次开发的,功能还是很弱的。一定要记住一点,OpenCV是一个强大的计算机视觉库,而不是视频流编码器或者解码器。希望大家不要走入这个误区,可以把这部分简单单独看待。目前,OpenCV只支持avi的格式,而且生成的视频文件不能大于2GB,而且不能添加音频。如果你想突破这些限制,我建议你最好还是看看ffMpeg,而不是浪费时间在OpenCV上。不过也可以利用视频后期合成工具制作。闲言少叙,进入重点VideoWriter类。
这个类是highgui交互很重要的一个工具类,可以方便我们容易的将图片序列保存成视频文件。类内成员函数有构造函数,open,isOpened,write(也可以用<<),使用还是很简单的。
使用很简单,先调用构造函数确定文件的名称,格式,帧率,帧大小,是否彩色。其中格式作为第二个参数,OpenCV提供的格式是未经过压缩的,目前支持的格式如下:
CV_FOURCC('P', 'I', 'M', '1') = MPEG-1 codec
CV_FOURCC('M', 'J', 'P', 'G') = motion-jpeg codecCV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
CV_FOURCC('U', '2', '6', '3') = H263 codec
CV_FOURCC('I', '2', '6', '3') = H263I codec
CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec
然后就<<不停的把image传进去就行啦,太简单了,我都不好意思写了。上代码:- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- using namespace cv;
- void main()
- {
- VideoCapture capture(0);
- VideoWriter writer("VideoTest.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25.0, Size(640, 480));
- Mat frame;
- while (capture.isOpened())
- {
- capture >> frame;
- writer << frame;
- imshow("video", frame);
- if (cvWaitKey(20) == 27)
- {
- break;
- }
- }
- }
OpenCV学习笔记(四十八)——PCA算法实现core
PCA(principal component analysis,主成分分析),我想是大家用的最多的降维手段,对于PCA的理解,我想大神们都各有各的绝招,可以应用的场合也非常多。下面就介绍一下OpenCV中PCA这个类,因为常用,所以这个类相对OpenCV而言显得比较独立,放在了core这部分中。
PCA类的成员函数包括构造函数、运算符重载()、project、backProject这几个函数,还包括成员变量eigenvectors、eigenvalues、mean。使用也很方便。比如我要计算一组向量的PCA,我们只需要定义个PCA实例,获得主成分,调用project测试新样本,也可以再调用backProject重建原始向量,是project的一个逆运算。
在实际使用我我发现了一个bug,构造函数和运算符重载()函数的第三个参数只能使用0或者1(分别对应CV_PCA_DATA_AS_ROW和CV_PCA_DATA_AS_COL),但调用对应的宏却编译无法通过,不知道大家是否也是一样的情况
下面结合一个实例分析:
2001年全国各地区消费情况指数
北京 101.5 100.4 97.0 98.7 100.8 114.2 104.2
天津 100.8 93.5 95.9 100.7 106.7 104.3 106.4
河北 100.8 97.4 98.2 98.2 99.5 103.6 102.4
山西 99.4 96.0 98.2 97.8 99.1 98.3 104.3
内蒙古 101.8 97.7 99.0 98.1 98.4 102.0 103.7
辽宁 101.8 96.8 96.4 92.7 99.6 101.3 103.4
吉林 101.3 98.2 99.4 103.7 98.7 101.4 105.3
黑龙江 101.9 100.0 98.4 96.9 102.7 100.3 102.3
上海 100.3 98.9 97.2 97.4 98.1 102.1 102.3
江苏 99.3 97.7 97.6 101.1 96.8 110.1 100.4
浙江 98.7 98.4 97.0 99.6 95.6 107.2 99.8
安徽 99.7 97.7 98.0 99.3 97.3 104.1 102.7
福建 97.6 96.5 97.6 102.5 97.2 100.6 99.9
江西 98.0 98.4 97.1 100.5 101.4 103.0 99.9
山东 101.1 98.6 98.7 102.4 96.9 108.2 101.7
河南 100.4 98.6 98.0 100.7 99.4 102.4 103.3
湖北 99.3 96.9 94.0 98.1 99.7 109.7 99.2
湖南 98.6 97.4 96.4 99.8 97.4 102.1 100.0
广东 98.2 98.2 99.4 99.3 99.7 101.5 99.9
广西 98.5 96.3 97.0 97.7 98.7 112.6 100.4
海南 98.4 99.2 98.1 100.2 98.0 98.2 97.8
重庆 99.2 97.4 95.7 98.9 102.4 114.8 102.6
四川 101.3 97.9 99.2 98.8 105.4 111.9 99.9
贵州 98.5 97.8 94.6 102.4 107.0 115.0 99.5
云南 98.3 96.3 98.5 106.2 92.5 98.6 101.6
西藏 99.3 101.1 99.4 100.1 103.6 98.7 101.3
陕西 99.2 97.3 96.2 99.7 98.2 112.6 100.5
甘肃 100.0 99.9 98.2 98.3 103.6 123.2 102.8
青海 102.2 99.4 96.2 98.6 102.4 115.3 101.2
宁夏 100.1 98.7 97.4 99.8 100.6 112.4 102.5
新疆 104.3 98.7 100.2 116.1 105.2 101.6 102.6
我们用PCA来分析这些向量的对消费水平的贡献,代码实现如下:
- #include <opencv2/core/core.hpp>
- #include <iostream>
- #include <fstream>
- using namespace cv;
- using namespace std;
- void main(int argc, char** argv)
- {
- const int SAMPLE_NUM = 31;
- const int VECTOR_NUM = 7;
- fstream fp;
- string temp;
- char* filename = argv[1];
- Mat pcaSet(SAMPLE_NUM, VECTOR_NUM, CV_32F);
- // 读取数据,生成pcaSet
- fp.open(filename, ios::in);
- for (int i=0; i<SAMPLE_NUM; i++)
- {
- getline(fp, temp, ' ');
- for (int j=0; j<VECTOR_NUM; j++)
- {
- fp >> pcaSet.at<float>(i, j);
- }
- }
- fp.close();
- // cout << pcaSet << endl;
- PCA pca(pcaSet, Mat(), 0/*CV_PCA_DATA_AS_ROW*/);
- cout << pca.eigenvalues << endl;
- cout << endl;
- cout << pca.eigenvectors << endl;
- }
我这里只把前3维的结果显示如下:
eigenvalues:[43.18,14.60,9.21]、
eigenvectors:[0.013,0.034,-.0.100, -0.130, 0.207,0.963,-0.020;
0.157,0.038,0.121,0.893,0.395,0.046,0.060;
0.214,0.018,-0.001,-0.404,0.813,-0.228,0.277]
OpenCV学习笔记(四十九)——号外!OpenCV-2.4.0 release 千呼万唤始出来
最近一直很忙,没有及时回复网友的咨询和疑问,有些回复也是寥寥数语。其实我也没有办法,面对大量的问题,有大部分都是可以通过网络和图书获得答案,我实在没有精力每个问题都详细具体的回答,希望大家谅解,还是一位老师说的好:“知之为知之,不知百度知”。
前阵子有些朋友已经发现了OpenCV-2.4.0beta已经放出了,又有重大改动,很是让人兴奋,我前一篇blog——OpenCV学习笔记(三十四)——OpenCV路在何方中提到的OpenCV下一步的改进在这次版本中很多都得到了实现。最让我欣慰的是OpenCV有了自己的主页code.opencv.org,之前的http://opencv.willowgarage.com终将退出历史。其实这个beta版我也下载下来看过了,其中的文档并没有跟上,所以我一直在等。
五一节日,OpenCV也给大家送上了大礼,2.4.0release出炉。下载地址还是在Sourceforge上,之前听说OpenCV要把项目主页挪到ROS上,看来还没有实施。这次的压缩包竟然有201M啊,有木有啊!可见这次版本添加了很多内容啊,由于有重大改动,接下来还是详细给大家说说,其实新主页上都有,大家英文好可以去那里看,免得我给翻译错了~~。还有就是OpenCV许诺大家下一个版本2.4.1将在五个月后出炉,看来只能是活到老学到老了。。。
首先提到的还是网站的事,code.opencv.org现在是OpenCV开发首要的网站,相信日后的最新消息都会从这里放出。而opencv.org将作为官网(现在还没有投入使用,期待一下)。
还有一个重要的消息是一部分imgproc, video, calib3d, features2d, objdetect模块中的函数将废弃,扔到legacy中去了。兴奋的同时又让我很期待,新版本的整合是如何重整这些模块的呢,看来我又得好好重新学习了。版本的重大变化肯定也导致了CMake脚本的改变,这部分不是太精通,这里不班门弄斧。
一个新的模块cv::Algorithm出炉。这个模块包含了众多算法,也是接下来研究的重点,有新研究再和大家分享,文档我目前才开始看。
之前被大家诟病的视频部分这次又有所加强,大家经常抱怨OpenCV对视频支持的不好,不知道这次的改动会不会打一个翻身仗,还有待大家实践。
feature2d模块之前使用还是很不方便的,现在都被整合到Algorithm模块中了。SURF和SIFT被挪到了nonfree模块,这又是什么模块,看来新版本的惊喜还不少。。。还有一些函数的增添和改进,这里由于没有使用过,还是不乱讲,有兴趣自己去看一下咯。
一个新模块photo出炉,是为了计算摄影学而设计的,目前该模块只有从imgproc中移植出来的inpainting算法,还有一个模块是videostab是用来稳定视频的(这个模块还是beta版的)?这都是神马啊!具体咋用我也不知道啊。。。
之前我blog里提到的对GPU的支持力度要加强,OpenCV兑现了它的诺言,把光流法和特征点的提取检测算法都在GPU模块中实现了。之前我提过的android模块也有所加强,但具体就不介绍了,我本身也不是搞移动开发的。新版本还特意提到了一个函数getBuildInformation,日后也要试试做啥的。
从今日起,我的学习笔记都将使用OpenCV-2.4.0开发,之前的blog都是用2.3.1写的,肯定有些东西,大家看看就乱了,给大家的学习带来了不便,还请大家包涵理解。
OpenCV学习笔记(五十)——Algorithm类介绍(core)
刚开始学习新的2.4.0,大概看了一遍使用手册,还是有些失望的,很多章节还是2.3.1的内容,文档上的代码也是漏洞很多。这里就简单介绍一下Algorithm这个新的基类。本来以为这部分是一个新模块的,看了referenceManual后才知道它只是一个基类,集成了一些相对复杂的算法,比如BM算法等立体匹配算法,前景背景分离的算法,光流法等模块都集成在其中。类内成员函数主要有get、set、writhe、read、getList、create这些函数。前4个是用来从字符串和XML文件中读取算法的参数用的,使用get,set要注意参数的名字对应的类型要和数据的类型对应,后果大家肯定懂的。有了Algorithm::write,以后SITF::wirte啊SURF::write啊,神马的都可以再见了。getList可以得到Algorithm支持的算法类型。我测试了一下getList目前getList的算法有:BRIEF、Dense、FAST、CFIT、HARRIS、MSER、ORB、SIFT、STAR、SURF,日后应该都会实现,在手册上只有SURF和SIFT的介绍,至少目前,我看来只支持这两个算法。create就是创建算法的函数。使用呢,也相对简单。这里还是要说明一下,新版的features2d模块有较大改动,反正我看文档中该部分大多剩下的都是一些公共接口,比如特征描述子、描述子的提取、特征的匹配等。只有FAST、MSER、ORB还在文档中坚挺的出现(估计日后也要移植走),以前的Star、randomTree、rTreeClassifer神马该被遗弃的一起,该放ml的去ml,SIFT、SURF啥的也被弄到nonfree这个新模块里去了,不过这个新模块好弱啊,目前只有SIFT和SURF算法,估计以后还要把其他的算法整合进去。
接下来我就根据文档中的一个示例实践一下新版本的SIFT特征点检测算法,并且对比下之前版本的SITF的写法,大家从中感受新结构的不同吧。
- #include <opencv2/opencv.hpp>
- #include <opencv2/nonfree/nonfree.hpp>
- #include <opencv2/nonfree/features2d.hpp>
- using namespace cv;
- void main()
- {
- Mat image = imread("church01.jpg");
- Mat imageGray = imread("church01.jpg", 0);
- Mat descriptors;
- vector<KeyPoint> keypoints;
- // 新版本2.4.0方法
- initModule_nonfree();
- Ptr<Feature2D> sift1 = Algorithm::create<Feature2D>("Feature2D.SIFT");
- sift1->set("contrastThreshold", 0.01f);
- (*sift1)(imageGray, noArray(), keypoints, descriptors);
- // 2.3.1方法
- // SiftFeatureDetector sift2(0.06f, 10.0);
- // sift2.detect(imageGray, keypoints);
- drawKeypoints(image, keypoints, image, Scalar(255,0,0));
- imshow("test", image);
- waitKey();
- }
注意initModule_<modulename>()函数,这个函数要在create前使用,才可以动态的创建算法,不然那个create的指针很野哦。大家都懂的。如果要使用SURF、SIFT算法,就要调用 inintModule_nonfree(),要使用EM算法,就要先调用 initModule_ml()。
其实在我看来,这个Algorithm类更重要的是为开发者的算法提供一个公共的接口,以后开发者开发的算法,想要增加到OpenCV中去,就按照Algorithm的接口做就OK了,以免以后算法越来越多,我们的OpenCV也要变得臃肿了。
创建自己的算法类现在也很容易了,用Algorithm类做基类,算法的参数作为成员变量,用get函数调用,添加AlgorithmInfo* info() const到自己的算法类中去,添加构造函数,AlgorithmInfo变量,可以参考EM算法的初始化看如何操作,添加其他函数。做好后就用create调用你自己的函数就ok啦,这次先简单介绍,以后有机会自己做个函数了,体会深了再详细写出来跟大家分享。
from: http://blog.csdn.net/yang_xian521/article/category/910716