OpenCV 教程.docx
《OpenCV 教程.docx》由会员分享,可在线阅读,更多相关《OpenCV 教程.docx(22页珍藏版)》请在冰豆网上搜索。
OpenCV教程
OpenCV教程
C++版
FF团
2015/12/21
目录
1OpenCV的安装与配置2
1.1安装OpenCV2
1.2环境变量设置2
1.3在VS2015中配置OpenCV4
2Mat类8
2.1计算机中的图像8
2.2创建Mat类对象9
3图像显示与存储10
3.1图像显示10
3.2图像存储10
4扫描矩阵并着色12
4.1OpenCV坐标12
4.2at函数12
4.3使用指针高效扫描13
5矩阵区域选取14
5.1单行单列的选取14
5.2多行多列的选取14
6简单的图像处理16
6.1直方图均衡化16
6.2图像平滑处理16
本教程中会加入几张分形图填充空白,可无视。
1OpenCV的安装与配置
1.1安装OpenCV
首先,我们进入OpenCV的官网(http:
//opencv.org/)下载OpenCV3.0如图11所示。
图11
然后我们将下载下来的文件安装至D盘如图12所示,点击Extract按钮即可
图12
1.2环境变量设置
安装完OpenCV3.0之后,我们需要设置环境变量。
首先,我们进入系统属性(可从”此电脑”处点击鼠标右键,再点击属性)看到图13所示的界面,并点击左侧的”高级系统设置”按钮
图13
点击按钮后,我们看到如图14所示的界面,并点击”环境变量”按钮
图14
接着,我们会看到如图15所示的界面
图15
点击”系统变量”下的”新建(W)”按钮,添加如图16所示内容后点击确定
图16
回到图15所示界面,在”系统变量”中找到”Path”变量,双击该变量或点击”编辑”按钮添加图17中圈出的内容(32位系统不用添加x64那一行,64位系统最好全部添加)
注:
win7或win8系统,直接在原内容后加
;%OPENCV%\x86\vc12\bin;%OPENCV%\x64\vc12\bin分号不可省略,32位系统不用加x64
图17
确认进行完上述所有操作后,请重新启动电脑。
1.3在VS2015中配置OpenCV
首先,新建一个win32控制台应用或空项目
然后,如图18所示,点击”视图”->”其他窗口”->”属性管理器”
图18
之后,会在整个界面的右侧看到如图19所示的属性管理器
图19
点击红圈圈出的”添加新项目属性表”按钮,创建一个新的项目属性表,这里建议大家将新建的属性表命名为如opencv这样好记的名字,并存至一个自己能记住的地方(之后要用)
之后,我们从图110所示界面双击新的属性
图110
我们会看到如图111所示界面,在这个界面中,我们要设置”包含目录”,”库目录”和”输出”。
其中包含目录与库目录需点开左侧的VC++目录才能看到,输出在左侧的链接器下。
图111
包含目录中,我们要添加图112所示的内容
图112
库目录中,我们要添加图113所示内容,使用64位系统的同学们建议配置完这张表之后再单独配置一张64位所需的,只要把图113中的x86改为x64即可,不建议将x86与x64直接添加在一张属性表里,那样做可能会导致无法使用x86的debug和release
图113
点开链接器下的输入后,我们会看到图114所示的界面。
然后我们要设置附加依赖项
图114
附加依赖项中,我们要添加如图115所示内容
图115
完成上述所有配置之后,我们就完成了在VS2015中配置opencv
如果后面的其他项目也需要用到opencv,我们就不需重新配置,只要选择添加现有属性表,将这次配置好的属性表直接加入新项目即可。
下面给出几行测试用代码,大家也可用后面教程中的代码测试opencv是否配置成功
#include//注意,64位系统的同学们请用x64的debug或release
usingnamespacecv;
voidmain()
{
MatT(300,400,CV_8UC3,Scalar(0,0,255));
imshow(“Test”,T);
waitKey(0);}
2Mat类
2.1计算机中的图像
在现实世界中,我们能直接看到各种事物,那么,在计算机中,图像是什么样子呢。
图22是图21所示的一小块红色图像的一小部分在计算机中的样子
图21
图22
表21
……
……
……
……
……
……
……
……
……
……
……
……
……
……
……
表21较为直观地反映了大小为sxn的图像在计算机中的样子,不过实际上,在内存足够的情况下,一个图像一般是连成行的。
了解了图像在计算机中的存在形式后,我们可以进入下一节,学习如何创建一个图像。
2.2创建Mat类对象
Mat类是OpenCV中的图像类,同时也是一个矩阵类,下面我们将给出一些Mat类常用的构造函数。
1.Mat(introws,intcols,inttype)
2.Mat(Sizesize,inttype)
3.Mat(introws,intcols,inttype,constScaral&s)
4.Mat(Sizesize,inttype,constScaral&s)
5.Mat(constMat&m)
6.Mat(constMat&m,constRange&rowrage,constRange&colrange)
7.Mat(constMat&m,constRect&roi)
第6、7种构造函数与14页5.2节多行多列的选取相关,不在这一节介绍
下面我们将给出不同方式定义Mat类对象的例子大家可在VS2015中体验一下这些方式的异同,并选取对你们来说最方便的方式
#include
#include
usingnamespacestd;
usingnamespacecv;
voidmain()
{
MatP1(5,5,CV_8UC3);//方法一
Sizes(5,5);
MatP2(s,CV_8UC3);//方法二
Scalarp(0,0,255);
MatP3(5,5,CV_8UC3,p);//方法三
MatP4(s,CV_8UC3,p);//方法四
MatP5(P4);//方法五
cout<cout<cout<cout<cout<system(“pause”);
}
3图像显示与存储
3.1图像显示
在上一章中,我们已经学会了如何创建一个矩阵,但我们并不能直接直观地看见我们创建的图片。
这一节中,我们将学习使用imshow函数来显示我们的图像。
首先,我们给出imshow函数的函数原型
voidimshow(constchar*name,constCvArr*img)其中,第一个参数为我们显示图像用的窗口的名字,第二个参数为图像,也就是要显示的矩阵。
下面是一个例子
#include
usingnamespacecv;
voidmain()
{
MatP6(500,500,CV_8UC3,Scalar(0,0,255));
imshow(“PIC6”,P6);
waitKey(0);
}
这个例子中,大家会看到一张纯红色的图片。
waitKey函数的作用为等待按键,参数为0时一直等待到有键按下,是其他数字是则等待相应的时间(单位为ms)
3.2图像存储
这一节中,我们将学习用imwrite函数写图像文件,以便我们能记录下想要的数据和学习的过程
在介绍imwrite函数之前,我们先简单介绍三种常用的图像格式——BMP格式,JPEG格式和PNG格式
BMP格式即位图,它与现有的windows程序广泛兼容,但由于其不支持文件压缩,会造成较大的空间占用,我们并不推荐使用这种格式,除非你仅仅想画一张作为壁纸的图。
JPEG格式,大家对这种格式应该都并不陌生,这是一种应用很广泛的很流行的图像格式。
但是这是一种有损压缩格式,对于摄影作品或写实作品,我们可以放心地用这种格式压缩,但对于我们自己要画的分形图来说,这种格式造成的图像品质损失会比较严重。
PNG格式,这是一种较新的图像格式,同时也是一种无损压缩格式,而他与旧程序兼容性差的缺点并不影响分形图的绘制。
在这里我们推荐大家使用这种格式存储图片,本节中提供的例子也都是关于这种格式的。
下面,我们将开始imwrite函数的学习
首先,是imwrite函数的原型
boolimwrite(conststring&filename,InputArrayimg,constvector¶ms=vector())其中第一个参数是保存的路径与文件名,第二个参数是要保存的图像,第三个参数是含有保存类型与压缩程度的向量
我们将结合例子讲解该函数的使用
#include
#include
#include
usingnamespacestd;
usingnamespacecv;
voidmain()
{
MatP7(500,500,CV_8UC3,Scalar(255,0,0));
vectorpng{CV_IMWRITE_PNG_COMPRESSION,0}
//创建一个含有存储格式信息的向量,第一个分量为类型,第二个分量为压缩程度//在OpenCV中,PNG格式有0~9十级压缩程度可选,数字越大压缩率越大,耗时越长
imwrite(“D:
\\opencv\\P7.png”,P7,png);
//注意路径中所有的\斜线都要写两个
imshow(“P7”,P7);
waitKey(5000);
}
4扫描矩阵并着色
4.1OpenCV坐标
在开始画我们的分形图之前,我们还需了解一件事,OpenCV扫描图像的顺序和我们直觉上的平面直角坐标系是不一样的。
图41
图41中,红色的坐标系为OpenCV扫描图像时的x,y方向(右手系),而黑色的则是我们直觉上的坐标系(左手系)
在画图时请大家注意坐标系之间的转换
4.2at函数
at函数是OpenCV中最便捷也是最安全的访问像素点的方式,不足就效率相对较低
本节中,我们将结合例子讲解at函数的使用
#include
#include
usingnamespacestd;
usingnamespacecv;
voidmain()
{
MatP8(500,500,CV_8UC3);
for(inti=0;i<500,++i)
for(intj=0;j<500,++j)
{
Vec3bp;
p[0]=255;//Blue
p[1]=0;//Green
p[2]=0;//Red
P8.at(i,j)=p;
}
imshow(“P8”,P8);
waitKey(0);
}
4.3使用指针高效扫描
在第8页2.1节计算机中的图像中,我们提到,在内存中,图像其实是连成行存储的,因此使用at函数找矩阵中的某一位置需要计算在行中所在的位置,导致效率较低。
本节中,我们给出使用指针扫描图像的方法。
#include
#include
usingnamespacestd;
usingnamespacecv;
voidmain()
{
MatP9(500,500,CV_8UC3);
for(inti=0,i<500,++i)
{
Vec3b*c=P9.ptr(i);//获取指向每行第一个像素点的指针
for(intj=0;j<500;++j,++c)
{
Vec3bp{255,0,0};
*c=p;
}
}
imshow(“P9”,P9);
waitKey(0);
}
5矩阵区域选取
5.1单行单列的选取
在一些情况下,我们可能会需要矩阵中某一行或某一列的数据,这一节我们将介绍获取单行单列的函数
OpenCV提供了获取单行数据的row函数和获取单列数据的col函数
他们的原型如下
row(inti)const
col(intj)const
其中i,j是想要的行或者列。
下面是使用这两个函数的例子
#include
#include
usingnamespacestd;
usingnamespacecv;
voidmain()
{
MatP10(5,5,CV_8UC3,Scalar(0,255,0));
MatL1=P10.row
(2);
MatL2=P10.col
(2);
cout<cout<system(“pause”);
}
5.2多行多列的选取
在OpenCV中,我们也可以选取多行多列,在第9页第2.2节创建Mat类对象中,我们给出了使用构造函数选取多行多列的方法。
在本节中,我们还会结合例子给出用括号运算符的方式
#include
#include
usingnamespacestd;
usingnamespacecv;
voidmain()
{
MatP11(500,500,CV_8UC3,Scalar(0,255,0));
MatP12,P13,P14,P15;
MatP12(P11,Range(10,400),Range(20,350));//选取第10到400行,第20到350列的图像
MatP13=P11(Range(10,400),Range(20,350));//与上一种方法等效,使用了括号
MatP14(P11,Rect(10,20,400,350));//10,20为左上角坐标,400,350为右下角坐标
MatP15=P11(Rect(10,20,400,350));//与上一种效果相同
imshow(“P12”,P12);
waiKey(0);
}
6简单的图像处理
6.1直方图均衡化
直方图均衡化是一种通过拉伸像素强度分布范围来增强图像对比度的方式,在OpenCV中,我们可以使用equalizeHist函数对图像进行直方图均衡化。
本节中我们不详细阐述该方法的原理,只讲解如何使用函数进行直方图均衡化。
equalizeHist函数不能直接在原图像上进行处理,因此它需要两个参数——原图像和新的图像。
这里假设我们已经得到了一张需要加强对比度的图像P16则我们需要再定义一个Mat类对象P17用于绘制新图像然后可用equalizeHist(P16,P17);完成直方图均衡化;
需注意的是,该函数只能对灰度图进行均衡化,对于彩图,我们可以直接将其拆分成R,G,B三张灰度图分别进行均衡化,或者将图像转换为HSV颜色空间,再对分离出的V层进行均衡化。
对于照片等应选用第二种方式,第一种方式会导致错误的颜色变化
6.2图像平滑处理
OpenCV提供了四种滤波器用于图像的平滑处理,以及写自己的滤波器所用的函数,这一节中,我们简单地展示两种OpenCV自带的滤波器的使用
首先,滤波器同样不能再原图上处理,需要一个新的图片,现在假设我们已经得到了一个需要进行平滑处理的图像P18,我们需要再定义一个Mat类对象P19用于存放新产生的图像。
归一化滤波器是最简单的一种滤波器,他的原理是用一块区域内像素值的均值代替区域内某一点的像素值
示例如下
blur(P18,P19,Size(3,3),Point(-1,-1));
其中size为求均值区域的大小,point为像素点所在区域内的位置,若为-1,-1则默认为区域的中心点
下面是另一种滤波器,中值滤波器,他的原理是用以某像素点为中心的正方形区域像素值的中值替代该像素值
示例如下
medianBlur(P18,P19,3);
其中,最后一个参数为正方形的边长,因为涉及到取中心,所以该长度必须为奇数