您好,欢迎访问三七文档
当前位置:首页 > IT计算机/网络 > 数据库 > OpenCV2学习笔记
一:Opencv2与opencv1的区别:Opencv1.0版本于2006年面世,主要基于C语言。2009年发布opencv2,主要基于C++。此时opencv库被划分成多个模块,这些模块被编译成库文件后,位于lib文件夹中。主要有以下模块(版本1的结构见我的这篇blog:):Opencv_core模块:包含核心功能,尤其是底层数据结构和算法函数。Opencv_improc模块:包含图像处理函数。Opencv_highgui模块:包含读写图像及视频的函数,以及操作图形用户界面函数。Opencv_features2d模块:包含兴趣点检测子,描述子以及兴趣点匹配框架。Opencv_calib3d模块:包含相机标定,双目几何估计以及立体视觉函数。Opencv_video模块:包含运动估算,特征跟踪以及前景提取函数与类。Opencv_objdetect模块:包括物体检测函数,如脸部和行人检测。库中还包含其它的工具模块,如机器学习(opencv_ml),计算几何(opencv_flann),第三方代码(opencv_contrib)等。这些模块都对有一个单独的头文件(位于include文件夹)。推荐的声明方式如下:#includeopencv2\core\core.hpp#includeopencv2\highgui\highgui.hpp#includeopencv2\imgproc\imgproc.hpp而#includecv.h这是旧的代码方式,那是库还没有被划分为模块。二:读取、显示和保存图片(1)代码:[cpp]viewplaincopyprint?#includeopencv2\core\core.hpp#includeopencv2\highgui\highgui.hpp#includeopencv2\imgproc\imgproc.hpp#includeiostreamusingnamespacestd;usingnamespacecv;intmain(){Matimage=imread(F:\\tongtong.jpg,1);//读取图片if(!image.data)//data指向已分配内存块的指针{coutfailtoloadimageendl;}coutimagesize:image.size().height,image.size().widthendl;//size()返回的是一个结构体namedWindow(show);imshow(show,image);//显示图片imwrite(F:\\tongtong2.jpg,image);spanstyle=white-space:pre/spanMatresult;flip(image,result,0);namedWindow(result,0);imshow(result,result);waitKey(0);return0;}(2)Explaination:1opencv2中用于存储图像数据为Mat类型,而在opencv1中用IplImage(详细见我的这篇blog:)。优点在于Mat是一个类,定义的类类型可以自动分配和释放内存空间,而IplImage需手动为其分配和释放内存空间,当图像较多时,可能会有偏差,造成内存泄露。2image.data是指向已分配的内存块的指针,当图片没有加载进来,则为NULL。3image.size()返回的是一个结构体,实际上包括width和height这两个成员变量。4flip(image,result,0);//其中正数表示水平反转,0表示垂直反转,负数表示既有水平又有垂直反转。3)结果:三:深浅拷贝(1)浅拷贝:MatB;B=image;//第一种方式MatC(image);//第二种方式这两种方式称为浅copy,是由于它们有不同的矩阵头,但是它们共享内存空间,即指向一个矩阵。当图像矩阵发生变化时,两者相关联,都会变化。(2)深拷贝:MatB,C;B=image.clone();//第一种方式image.copyTo(C);//第二种方式深拷贝是真正的copy了一个新的图像矩阵,此时image,B,C三者相互没有影响。四:IplImage装换为MatIplImage*iplImage=cvLoadImage(F:\\11.jpg,1);Matimage2(iplImage,false);//其中false为浅拷贝,而true为深拷贝,默认为false。此时注意需要释放iplImage当然opencv提供了另外一种指针类,无需手动释放,但现在已经不用了,可以使用它来封装IplImage指针:PtrIplImageiplImage=cvLoadImage(F:\\11.jpg,1);图像遍历主要有三种方法,本节主要介绍和比较这三种方法。一:简单存取像素值首先介绍一个名词—椒盐噪点:它是一种特殊的噪点,它随机的将图像中的部分像素设置为白色或者黑色。Code:[cpp]viewplaincopyprint?#includeopencv2\highgui\highgui.hpp#includeopencv2\imgproc\imgproc.hpp#includeopencv2\core\core.hpp#includeiostreamusingnamespacestd;usingnamespacecv;voidsalt(Mat&image,intn){for(intk=0;kn;k++){rand();inti=rand()%image.cols;intj=rand()%image.rows;if(image.channels()==1){image.atuchar(j,i)=255;}elseif(image.channels()==3){image.atVec3b(j,i)[0]=255;image.atVec3b(j,i)[1]=255;image.atVec3b(j,i)[2]=255;}}}voidsalt2(Mat_Vec3bimage,intn)//这个只针对彩色三通道的图片{for(intk=0;kn;k++){rand();inti=rand()%image.cols;intj=rand()%image.rows;if(image.channels()==3){image(j,i)[0]=255;image(j,i)[1]=255;image(j,i)[2]=255;}}}intmain(){Matimage=imread(F:\\huangrong.jpg,1);salt(image,3000);namedWindow(image);imshow(image,image);waitKey(0);return0;}Explaination:(1)rand()是随机数生成函数。(2)image.atVec3b(j,i)[0]=255;成员函数at(inty,intx)可以用来存取图像元素,但必须在编译时期知道它的数据类型,这样的函数被称为模板函数,即需要指定操作成员的类型atuchar(y,x)Opencv中的类型Vec3b是由三个uchar组成的向量,可以通过操作符[]来获取。(3)Mat_Vec3bimage;image(j,i)[0]=255;Mat_是Mat的一个模板子类。在事先知道矩阵类型的情况下,使用Mat_可以带来一些便利。这个类定义了一些额外的成员方法,但没有定义成员变量。它重载了操作符(),允许我们可以通过它直接存取矩阵元素。Result:二:通过指针遍历图像需要说明的是:一个宽为W,高为H的三通道图像需要填补一个大小由W*H*3个uchar构成的内存块。但是,出于效率的考虑,图像会在每行行尾填补一些额外的像素。这是因为,如果行的长度是4或8的倍数,一些多媒体处理芯片可以更高效的处理图像。Mat中的成员函数isContinuous()可以判断这幅图像是否对行进行了填补。如果为真,则没有填补。Code:[cpp]viewplaincopyprint?/*通过指针遍历图像*/#includeopencv2\highgui\highgui.hpp#includeopencv2\imgproc\imgproc.hpp#includeopencv2\core\core.hpp#includeiostreamusingnamespacestd;usingnamespacecv;voidcolorReduce(Mat&image,intdiv=64)//颜色缩减函数{/*if(image.isContinuous()){image.reshape(3,image.cols*image.rows);coutimage.rowsendl;coutimage.colsendl;}*/intn1=image.rows;intnc=image.cols*image.channels();if(image.isContinuous()){nc=n1*nc;n1=1;}for(intj=0;jn1;j++){uchar*data=image.ptr(j);//uchar*data=image.data+j*image.step;//得到指向第i行的地址有两种方法ptr是成员函数,而data是成员变量,不推荐使用data,易出错for(inti=0;inc;i++){data[i]=data[i]/div*div+div/2;}}cout一行含有的字节数:image.stependl;cout一个像素所含有的字节:image.elemSize()endl;cout通道数:image.channels()endl;cout总像素个数:image.total()endl;coutwidth:image.size().widthendl;coutwidth:image.colsendl;coutheight:image.rowsendl;}voidcolorReduce2(constMat&image,Mat&result,intdiv=64){intn1=image.rows;//intnc=image.cols*image.channels();intnc=image.cols;for(intj=0;jn1;j++){//uchar*data=image.ptr(j);//uchar*data_in=image.data+j*image.step;//得到指向第i行的地址有两种方法ptr是成员函数,而data是成员变量//uchar*data_out=result.data+j*result.step;for(inti=0;inc;i++){uchar*data=image.data+j*image.step+i*image.elemSize();//这种方式不推荐使用,一方面容易出错,还不适用于带有感兴趣区域//data_out[i]=data_in[i]/div*div+div/2;data[0]=0;data[1]=0;data[2]=0;}}}intmain(){Matimage=imread(F:\\huangrong.jpg,1);Matresult;result.create(Size(image.cols,image.rows),image.type());//create函数为result创建一个与输入图像的尺寸
本文标题:OpenCV2学习笔记
链接地址:https://www.777doc.com/doc-5857170 .html