opencv基础学习笔记

来源:互联网 发布:php淘宝客系统 编辑:程序博客网 时间:2024/06/05 15:55

注:如果opencv编译之后codeblocks提示not found -lippcv,那么在编译的时候取消掉所有和ippcv相关的即可。


OpenCV具有模块化结构,这意味着程序包中包含着一些动态和静态的库。以下列出的是可用的模块:


core(核心)——这个紧凑的模块定义了一些基础的数据结构,包括密集型多维数组Mat和一些其他模块将会用到的基础函数。

imgproc(图像处理)——在图像处理模块中包括了线性和非线性的图像滤波功能,几何变换(调整大小、仿射、透视、重映射等),色彩空间变换,以及直方图操作等等。

video(视频)——视频分析模块包括了包括了运动估计、背景提取、对象追踪等功能。

calib3d(3D标定)——基本的多视角几何算法、相机标定、目标姿势估计、立体对应算法和3D重构等。

features2d(2D特征)——特征检测、描述和模式匹配。

objdetect(目标检测)——对预先定义好的的物体和实例进行检测(例如人脸、眼睛、被子、人、汽车等等)。

highgui——一个简单易用的视频捕捉、图片和视频编码接口,以及简单的UI实现。

gpu——区别于其他OpenCV模块的GPU加速算法。

……一些其他的帮助模块,例如函数链接型神经网络、Google测试封装、Python绑定等等。



均值滤波:使用邻域像素均值计算替代。采用加权平均值计算,算法简单快速,但不能保护好图像细节,高斯滤波(正态)

中值滤波:使用邻域像素中间值替代。在去除脉冲噪声、椒盐噪声的同时又能保留图像边缘细节,比均值慢好几倍。

双值滤波:结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。

膨胀与腐蚀(Dilation与Erosion):

  • 消除噪声

  • 分割(isolate)出独立的图像元素,在图像中连接(join)相邻的元素。

  • 寻找图像中的明显的极大值区域或极小值区域

  • 求出图像的梯度

开运算(Opening Operation),其实就是先腐蚀后膨胀

闭运算:先膨胀后腐蚀

形态学梯度(Morphological Gradient)为膨胀图与腐蚀图之差,数学表达式如下:


顶帽运算(Top Hat),原图与开运算之差

黑帽(Black Hat)运算为”闭运算“的结果图与原图像之差



边缘检测的一般步骤

1)滤波:边缘检测的算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此必须采用滤波器来改善与噪声有关的边缘检测器的性能。常见的滤波方法主要有高斯滤波,即采用离散化的高斯函数产生一组归一化的高斯核(具体见“高斯滤波原理及其编程离散化实现方法”一文),然后基于高斯核函数对图像灰度矩阵的每一点进行加权求和(具体程序实现见下文)。

2)增强:增强边缘的基础是确定图像各点邻域强度的变化值。增强算法可以将图像灰度点邻域强度值有显著变化的点凸显出来。在具体编程实现时,可通过计算梯度幅值来确定。

3)检测:经过增强的图像,往往邻域中有很多点的梯度值比较大,而在特定的应用中,这些点并不是我们要找的边缘点,所以应该采用某种方法来对这些点进行取舍。实际工程中,常用的方法是通过阈值化方法来检测。

Canny算子,Sobel算子(检测直线较好),Laplace算子以及Scharr滤波器(canny算子本身就是一个高斯滤波的函数,应该不用滤波,改变两个参数阈值可设置频率范围)

漫水填充:功能类似ps魔术棒,相似颜色填充颜色

角点检测:可用于特征检测
重映射:就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。


SURF特征点检测

SURF是尺度不变特征变换算法(SIFT算法)的加速版。SURF最大的特征在于采用了harr特征以及积分图像的概念,这大大加快了程序的运行时间。SURF可以应用于计算机视觉的物体识别以及3D重构中。

  • 使用 FeatureDetector 接口来发现感兴趣点。

  • 使用 SurfFeatureDetector 以及其函数 detect 来实现检测过程

  • 使用函数 drawKeypoints 绘制检测到的关键点。


仿射变换


仿射变换(Affine Transformation或 Affine Map),又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。它保持了二维图形的“平直性”(即:直线经过变换之后依然是直线)和“平行性”(即:二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变)。

一个任意的仿射变换都能表示为乘以一个矩阵(线性变换)接着再加上一个向量(平移)的形式。

那么, 我们能够用仿射变换来表示如下三种常见的变换形式:


  • 旋转,rotation (线性变换)

  • 平移,translation(向量加)

  • 缩放,scale(线性变换)

  • 使用OpenCV函数warpAffine 来实现一些简单的重映射.

  • 使用OpenCV函数getRotationMatrix2D 来获得旋转矩阵。



SURF特征匹配示例程序


这个示例程序中,我们利用SurfDescriptorExtractor类进行特征向量的相关计算。

程序利用了SURF特征的特征描述办法,其操作封装在类SurfFeatureDetector中,利用类内的detect函数可以检测出SURF特征的关键点,保存在vector容器中。第二步利用SurfDescriptorExtractor类进行特征向量的相关计算。将之前的vector变量变成向量矩阵形式保存在Mat中。最后强行匹配两幅图像的特征向量,利用了类BruteForceMatcher中的函数match。

程序的核心思想是:


  • 使用 DescriptorExtractor 接口来寻找关键点对应的特征向量。

  • 使用 SurfDescriptorExtractor 以及它的函数 compute 来完成特定的计算。

  • 使用 BruteForceMatcher 来匹配特征向量。

  • 使用函数 drawMatches 来绘制检测到的匹配点。



vector<vector<Point>>contours; vector<Vec4i>hierarchy; 

contours被定义成二维浮点型向量,这里面将来会存储找到的边界的(x,y)坐标。vector<Vec4i>hierarchy是定义的层级。这个在找边界findcontours的时候会自动生成,这里只是给它开辟一个空间。将来findContours( src, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );就能算出边界的坐标,存在contours里面。


 

camShift跟踪算法介绍

http://blog.csdn.net/carson2005/article/details/7439125


利用HOG特征方向梯度直方图(Histogram of Oriented Gradient, HOG来进行行人检测

http://blog.csdn.net/zhonghuan1992/article/details/38789943


背景剪除和OpenCV中的实现(背景前景分离运动物体)

背景与前景的分离如果是纯静态则则上一张图片减当前图片的,背景此时应该为0(一定范围阀值可以容许),可以是均值

http://blog.csdn.net/zhonghuan1992/article/details/38621153


光流的概念:

是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。

需要提醒的是,利用光流法进行运动物体检测时,计算量较大,无法保证实时性和实用性。


OpenCV视频读取播放,视频转换为图片

http://blog.csdn.net/zhonghuan1992/article/details/38469315


车辆识别可以采用高斯混合模型区分前景和背景,找出运动车辆


几种转换图片成灰度图片的方式:

        //Mat bw = threshval < 128 ? (frame < threshval) : (frame > threshval);

//Mat src;

//bw.convertTo(src, CV_8UC1);


//Mat grey;

//cvtColor(img, gray, CV_BGR2GRAY);    //实测用这个生成的可以用于边缘检测


//threshold(src1, threshImg, thresh, 255, CV_THRESH_BINARY);

//自适应二值化,据说堪比边缘检测void cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,                          int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,                          int threshold_type=CV_THRESH_BINARY,                          int block_size=3, double param1=5 );

//void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst);

        cvConvertImage(src, dst, flags=0);    //可以旋转图片


使用级联分类器识别物体

使用 CascadeClassifier 类来检测视频流中的物体. 特别地, 我们将使用函数:

  • load 来加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.

  • detectMultiScale 来进行图像的多尺度检测.


三维重建

立体校正cvStereoRectify

cvReprojectTo3D


Qt中使用opencv:(目前无法使用)

将opencv库加入到qtcreator里
我的命令是 sudo gedit /usr/share/qt4/mkspecs/default/qmake.conf
此时如果编译下面的opencv测试程序仍然不行!因为下面的还没完成。
先新建一个qt工程,此时需要在testopencv.pro文件内添加:

# opencv configuration

INCLUDEPATH += /usr/local/include \

                /usr/local/include/opencv \

                /usr/local/include/opencv2


LIBS+=/usr/local/lib/libopencv_highgui.so\

            /usr/local/lib/libopencv_core.so\

            /usr/local/lib/libopencv_imgproc.so\

            /usr/local/lib/libopencv_imgcodecs.so

# end opencv configuration

这时就OK了!

我为求方便,直接将上面的添加的INCLUDEPATH和LIBS内容添加到
sudo gedit /usr/share/qt4/mkspecs/default/qmake.conf 里,
这样以后就不用在每个工程里配置了,不过移植的时候就需要注意了。


kalman滤波:

cvCreateKalman(int nDynamParams, int nMeasureParams, int nControlParams);

cvReleaseKalman(CvKalman** kalman);

第一个函数产生CvKalman结构体,第二个函数删除结构。CvKalman结构被赋值后,调用cvKalmanPredict(CvKalman* kalman, const CvMat*control = NULL);计算下一个时间点的预期值,调用cvKalmanCorrect(CvKalman* kalman, CvMat* measured);校正新的测量值,结果存储在state_post中,预测的结果存储在state_pre中。

        对于更高级的可以使用condensation滤波器



训练级联分类器:

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html

创建dat:

$ find positive_images/ -name '*.jpg' -exec echo {} 1 0 0 32 32 \; > pos.dat
$ ls neg/*.jpg
 > neg.dat

输入命令行:

./opencv_createsamples -vec pos.vec -info pos\pos.txt -num 2706 -w 20 -h 20        //创建pos.vec

./opencv_traincascade -data dt -vec pos/pos.vec -bg neg/neg.txt -numPos 100 -numNeg 300 -w 64 -h 64 -minHitRate 0.995 -maxFalseAlarmRate 0.5 -mode ALL

或者

./opencv_traincascade -data dt -vec pos/pos.vec -bg neg/neg.txt -numPos 100 -numNeg 300 -numStages 16 -precalcValbufSize 200 -precalcdxBufSize 1000 -featureType LBP -w 64 -h 64

遇到的问题:

    1.opencv_traincascade error : _img.rows * _img.cols == vecSize      这个错误如提示,图片宽高与输入的-w和-h不合

    2.Train dataset for temp stage can not be filled. Branch training terminated. 可能neg文件格式不对,可以尝试文件名前加上./或者加上//或者使用绝对路径(目前未解决)

----nstage  指定训练层数,推荐15~-nsplits 分裂子节点数目,选取默认值  ----在用来训练的这个参数一半设置为-w ---mode ALL指定haar特征的种类,BASIC仅仅使用垂直特征,ALL表示使用垂直以及45度旋转特征-sym或者-nonsym,后面不用跟其他参数,用于指定目标对象是否垂直对称,若你的对象是垂直对称的,比如脸,则垂直对称有利于提高训练速度
复制代码

其中要注意,负样本使用的是.dat文件,而不是.vec文件。训练结束后会在cascade目录下生成0-N的子目录。训练过程如下图,我的正样本20,负样本60,小试牛刀,毕竟数据量有限。

 

想让自己更强大,就应该知道这张图里面一些参数的意思。

1
2
3
4
5
6
7
BACKGROUNG PROCESSING TIME 是负样本切割时间,一般会占用很长的时间
N 为训练层数
%SMP 样本占总样本个数
ST.THR 阈值,
HR 击中率,
FA 虚警,<span style="background-color: #ff0000; color: #000000;"><strong>只有当每一层训练的FA低于你的命令中声明的maxfalsealarm数值才会进入下一层训练</strong></span>
EXP.ERR 经验错误率

 

2.合并子分类器生成xml文件

输入命令:

1
haarconv.exe ./cascade haar_adaboost.xml 25 25

若你使用的是convert_cascade.exe则是另外一种格式:

1
convert_cascade.exe --size="20x20" ..\cascade haar_adaboost.xml

想知道用法可以输入xxx.exe  usage,用法以及参数说明一目了然

 

3.总结以及注意事项

看起来很简单是不是,你错了!真正做起来会有各种各样的错误发生让你措手不及。以下是我总结的问题及分析:

1)训练时间非常久,少则秒钟,多则几天甚至一礼拜。具体的时间跟你样本的选取、样本数量、机器的性能有着直接联系。举个例子,有人正样本7097负样本2830,在8核3.2Ghz的机器上,开启了多核并行加速(MP)的情况下训练了一周时间,跑到19层。链接http://blog.csdn.net/liulina603/article/details/8197889 。这个真心有点久了,有点夸张。举这个例子是想跟你说明,这是一件耗时间的事情,所以请你耐心等待。

2)卡死在某一层,好像进入死循环。这种情况一般跟样本的选择有关,尤其是负样本。当剩下所有的negtive样本在临时的cascade Classifier中evaluate的结果都是0(也就是拒绝了),随机取样本的数目到几百万都是找不到误检测的neg样本了,因而没法跳出循环!

解决方法是,增大负样本数目,增大负样本之间的变化!

3)训练带某一层出错,报错提示下图。查看cascade目录下发现确实走到第5层。这种情况跟上一种情况其实有点类似,都是opencv_haartraining.exe无法正常terminate。而我们的关注点在于,所生成的这些子分类器能用吗?要依实际情况而定。拿下图来说,在第5层的时候FA已经很低了,0.125000,说明效果已经够用。2)中也是这个道理。

在QT中配置opencv

编辑QT工程中的配置文件添加或者修改qmake参数

    sudo gedit /usr/share/qt4/mkspecs/default/qmake.conf

添加头文件和库文件    (如果不知道可以使用 pkg-config --libs --cflags opencv 查询)

QMAKE_INCDIR = /usr/include/opencv 

QMAKE_LIBS = -L/usr/local/lib -lopencv_cudabgsegm -lopencv_cudaobjdetect -lopencv_cudastereo -lopencv_shape -lopencv_stitching -lopencv_cudafeatures2d -lopencv_superres -lopencv_cudacodec -lopencv_videostab -lippicv -lopencv_cudaoptflow -lopencv_cudalegacy -lopencv_calib3d -lopencv_features2d -lopencv_objdetect -lopencv_highgui -lopencv_videoio -lopencv_photo -lopencv_imgcodecs -lopencv_cudawarping -lopencv_cudaimgproc -lopencv_cudafilters -lopencv_video -lopencv_ml -lopencv_imgproc -lopencv_flann -lopencv_cudaarithm -lopencv_core -lopencv_cudev


INCLUDEPATH += /usr/local/include \

                /usr/local/include/opencv \

                /usr/local/include/opencv2


LIBS+=/usr/local/lib/libopencv_calib3d.so\

/usr/local/lib/libopencv_core.so\

/usr/local/lib/libopencv_cudaarithm.so\

/usr/local/lib/libopencv_cudabgsegm.so\

/usr/local/lib/libopencv_cudacodec.so\

/usr/local/lib/libopencv_cudafeatures2d.so\

/usr/local/lib/libopencv_cudafilters.so\

/usr/local/lib/libopencv_cudaimgproc.so\

/usr/local/lib/libopencv_cudalegacy.so\

/usr/local/lib/libopencv_cudaobjdetect.so\

/usr/local/lib/libopencv_cudaoptflow.so\

/usr/local/lib/libopencv_cudastereo.so\

/usr/local/lib/libopencv_cudawarping.so\

/usr/local/lib/libopencv_cudev.so\

/usr/local/lib/libopencv_features2d.so\

/usr/local/lib/libopencv_flann.so\

/usr/local/lib/libopencv_highgui.so\

/usr/local/lib/libopencv_imgcodecs.so\

/usr/local/lib/libopencv_imgproc.so\

/usr/local/lib/libopencv_ml.so\

/usr/local/lib/libopencv_objdetect.so\

/usr/local/lib/libopencv_photo.so\

/usr/local/lib/libopencv_shape.so\

/usr/local/lib/libopencv_stitching.so\

/usr/local/lib/libopencv_superres.so\

/usr/local/lib/libopencv_videoio.so\

/usr/local/lib/libopencv_video.so\

/usr/local/lib/libopencv_videostab.so\

/usr/local/lib/libtbb.so


0 0
原创粉丝点击