2.3 OpenCV系统开发

2.3.1 OpenCV开发包安装

图像处理是使用计算机对图像分析获得有意义信息的一种技术手段。图像处理包括图像压缩,增强和复原,匹配、描述和识别等部分。OpenCV是一个基于开源的计算机平台视觉开发库,能够实现图像处理以及计算机视觉方面的很多通用算法。OpenCV官方网站为http://opencv.org,见图2-48。

图2-48

下载完后得到文件OpenCV 3.2.0,双击后会提示解压到某个地方,推荐放到D:\Program Files\,比如D:\Program Files(因为OpenCV项目文件打包的时候,根目录就是opencv,所以我们不需要额外的新建一个名为opencv的文件夹),然后单击“Extract”按钮,见图2-49。

图2-49

在解压的opencv文件夹中,build里面是使用OpenCV相关的文件,使用OpenCV的相关文件全部储存在build中,见图2-50。sources文件夹中存放着官方的实例集,可以删除。

图2-50

在“计算机”“属性”中单击“高级系统设置”,进入“高级”标签,单击“环境变量”按钮,在系统变量“PATH”后可以按下述情况添加,见图2-51。

图2-51

Opencv3.2.0官网只有x64,需要x86的读者需要自己编译。

对于64位系统,可以两个都添加上:“…… opencv\build\x64\vc\14\bin”。

本书将在vs2013中编译OpenCV,所以在使用前需要在vs2013中配置工程。打开visual studio,新建win32控制台项目,输入名字,选择文件路径,确定。在出现的对话框中勾选“空项目”。

在解决方案资源管理器的工程树中右击“源文件”,“添加”“新建项”,在工程中新建一个cpp源文件。

在菜单栏中单击“视图”“属性窗口”,在visual studio中会多出一个属性管理器工作区,见图2-52。

图2-52

在新出现的“属性管理器”工作区中,单击项目[Debug|x64][Microsoft.Cpp.x64.user]打开属性页面,见图2-53。

图2-53

在“通用属性”“VC++目录”“包含目录”中添加:

…\opencv\build\include

…\opencv\build\include\opencv

…\opencv\build\include\opencv2

配置库目录:在库目录中添加…\opencv\build\x64\vc14\lib路径,见图2-54。

图2-54

链接库的配置:在“属性管理器”工作区中,单击“项目”|“Debug|x64Microsoft.Cpp.x64.user”打开属性页面。在对话框中单击“通用属性”|“链接器”|“输入”|“附加的依赖项”将lib中的文件添加到“附加的依赖项”中,见图2-55。

图2-55

在OpenCV开发包安装过程中,可能会出现以下几种情况。

①找不到core.h:出现这个问题是因为include的时候,opencv根文件夹下面就有个include,但配置的时候,包含的应该是build中的include。

②无法解析的外部命令:是因为编译器与配置文件不符合,与系统无关,只与编译器的类型有关。使用32位编译器选择x86位配置文件,64位编译器选择x64位配置文件。

③关于形如-error LNK2005:xxx已经在msvcrtd.lib(MSVCR90D.dll)中定义,不包含静态库。

④应用程序无法正常启动0xc000007b:这属于Lib包含的问题。也许同时包含了x86和x64的,或者包含出错了。或者是对于windows 8 64位,.dll文件要放在和System32文件夹同级的SysWOW64文件夹中。

2.3.2 OpenCV开发实例:载入图像

在OpenCV中,所有的C++类和函数都是定义在cv命名空间内的,可以通过以下两种方法访问。第一种是在编写程序代码的开头位置,加上“usingnamespace cv;”。另外一种是在每次需要使用OpenCV类和函数时,都在类和函数前加上“cv::”。

Mat类:在OpenCV中,Mat类是用于保存图像以及其他矩阵数据的数据结构。Mat类的初始大小为0,也可以用户自己定义Mat类的空间大小。

例2-2 imread()函数:

Mat tupian=imread(“mao.jpg”)

表示将工程目录下的mao.jpg图片导入到Mat类tupain中。

Mat imread(const string& filename,intflags=1);

imread()函数中,第一个参数为需要载入的文件名,第二个参数为载入图像的颜色类型。

取值为0时,将图像转换从灰度图像再返回;取1时,将图像转换为彩色再返回;取2时,如果载入图像为16位或者32位,就返回对应深度的图像,否则,会将图形转换为8位图像再返回。

namedWindow()函数:

namedWindow()函数用于创建一个窗口。这个窗口可以作为图像和进度条的容器。但是如果相同名字的窗口已经创建,那么函数将不会做任何事情。当编写的程序量较大时,可以使用destroyWindow()或者destroyAllWindows()函数来关闭窗口。在退出时,所有的窗口都将被系统关闭。

void namedWindow(const string& winname,int flags=WINDOW_AUTOSIZE);

第一个参数为需要创建的窗口名称。

第二个参数是所创建的出口的类型标识,可以填如下的值。

WINDOW_NORMAL:用户可以自由改变窗口的大小。

WINDOW_AUTOSIZE:窗口能够根据图片大小自动调整大小,但是用户不能手动调整窗口大小,为函数的默认值。

WINDOW_OPENGL:创建的窗口支持OpenGL。

imshow()函数:在指定的窗口中显示一幅图像。在显示时,如果窗口的创建标识为默认格式,图片将以原始尺寸显示。否则图片将会被适度缩放,以适应窗口的大小。

void imshow(const string& winname,InputArray mat);

第一个参数中填写需要显示的窗口名称,第二个参数中填写需要显示的图像名称,见图2-56。

图2-56

imshow函数测试程序:

imwrite()函数是将图像保存到指定的文件的函数,图像格式由文件扩展名决定。

bool imwrite(const string& filename,InputArray img,const vector<int>&params=vector<int>());

第一个参数中填写需要写入的文件名,需要带上后缀,例如“1.jpg”。第二个参数中填写需要输出的图像名。第三个参数中为特定格式保存的参数编码,它有默认值,所以一般情况下可以省略,但是在以下地方可能用到:对于JPEG图片格式,参数表示图片质量,0~100,默认值为95;对于PNG图片格式,参数表示图片的压缩级别,0~9,值越大,压缩的尺寸越小,并且占用更多的压缩时间,默认值为3;对于PPM、PGM和PBM图片格式,参数表示二进制标志,取值为0/1,默认值为1。

ROI为设置感兴趣区域,即选定一块区域作为图像处理与分析的重点,这样可以减少处理时间,增加处理精度。

ROI创建函数[cv::Rect()和cv::Range()]

cv::Rect:创建一个矩形区域,需要指定矩形区域的左上角坐标和矩形长和宽。

Mat tp;

tp=image(Rect(300,200,200,100));

cv::Range:创建一个区域范围,从开始点到结束点的连续序列。

定义一个左上角坐标为(300,200),宽为200,高100的矩形窗口。

Mat tp;

tp=srcImage3(Range(100,150),Range(150,200));

这里截取的就是原图第100行至第149行,第150列到第199列的图像。Range的两个参数范围分别为左包含和右不包含。

2.3.3 OpenCV开发实例:图像叠加

混合是将2幅图像的像素值进行加权,形成新的图像,见图2-57、图2-58。其理论公式为:

gx)=(1-αf0x)+αf1x

addWeighted()函数:将2个图像阵列加权求和。

void addWeighted(InputArray src1,double alpha,InputArray src2,double beta,double gamma,OutputArray dst,int dtype=-1);

图2-57

图2-58

第一个参数中填写第一幅需要混合的图像名称;第二个参数表示第一幅图像权重;第三个参数表示第二副图像名称,需要和第一幅拥有相同的尺寸和通道数;第四个参数表示第二幅图像的权重值;第五个参数需要填写输出的图像名称,它的大小和输入的两个图像拥有相同的尺寸和通道数;第六个参数表示一个加到权重总和上的标量值;第七个参数为输出阵列的深度值,默认值为-1。当两个输入图像具有相同的深度时,这个参数设置为-1。

图像线性混合测试程序:

运行以上代码,得到最终融合的效果,如图2-59所示。

图2-59

2.3.4 OpenCV开发实例:边缘识别

  

在本例中采用霍夫圆变换算法,提取图像中圆的边以及半径。先读取图片,将图片转化为灰度图片。使用HoughCircles()函数不需要使用二值图像作为源图。然后采用高斯低通滤波,平滑图像,去除噪声。使用霍夫圆变换提取零件的边缘及中心,并将边缘和中心在图中绘制出来,效果如图2-60所示。

图2-60