购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第1章
OpenCV简介与安装

本章主要介绍OpenCV(Open Source Computer Vision Library,开源计算机视觉库)的历史与发展、主要模块构成、Windows平台下OpenCV的安装与配置,以及如何使用OpenCV读取与显示图像和视频文件。对有OpenCV开发经验的读者来说,本章可以直接跳过。

本书将以OpenCV4.5.x+Visual Studio 2017完成全部代码的构建与程序演示。本章旨在帮助初次接触OpenCV的读者搭建好开发环境,完成OpenCV框架中Hello World级别的入门程序。本章将会介绍几个简单的函数,为后续内容的学习打下良好基础。

下面就让我们一起开启这段OpenCV的学习之旅。

1.1 OpenCV简介

OpenCV提供了一系列的图像处理模块与计算机视觉算法模块。自OpenCV4.x版本开始,其开源许可协议从BSD改为Apache2(商业应用授权),这使开发者可以在商业领域应用开发中更好地使用授权的专利算法,避免专利纠纷,从而进一步扩展了OpenCV商业应用的范围。

1.1.1 OpenCV历史

OpenCV自发布第一个版本至今已超过20年,其间经过了几次大的版本调整。其中OpenCV2、OpenCV3、OpenCV4等都是里程碑式的版本。OpenCV每次进行大的版本调整都会带给开发者一些新的功能与惊喜,这也体现了OpenCV团队主动拥抱技术变革的精神,并始终保持开发框架的实用性。

OpenCV早期一直由Intel支持,后来转由开源社区维护与支持。其源码与模块分为正式的Release模块和扩展模块。Release模块中以早期开发的模块居多,都是一些比较成熟的算法实现。扩展模块中以新开发的模块居多,这些模块大多数不够稳定,在商业项目中直接使用会有一定的技术风险,使用者最好能对模块本身与相关算法有一定程度的了解。同时,因为受到算法专利的影响,可能偶尔会发生上一版本Release模块中支持的函数到了下一版本被放到扩展模块中的情况,但这种情况并不常见,而且如果发生了也会在release log文件中进行说明。

OpenCV发展至今,已经从单纯支持C/C++接口,变成支持Java、JavaScript、Python、C++、C#等多种语言,并支持Windows、Linux、macOS等主流操作系统。

1.1.2 OpenCV的模块与功能

OpenCV最初包含500多个相关的算法实现,截至2023年,OpenCV已经收录了2000多个相关的算法实现。OpenCV官方发布版本中的算法模块经过时间沉淀与项目检验,不断得到优化,稳定性与易用性超高,基于底层支持的加速机制,速度与性能均达到了工业级应用水准。

OpenCV中的常用模块如图1-1所示。(注意,并不是全部模块。)

图1-1 OpenCV模块结构

在图1-1中,横向显示的模块主要如下。

1)最下面一层是图像编解码与视频编解码,OpenCV加载图像与视频文件必须依赖这两个模块。它们是OpenCV基于其他开源库构建而来的,这样OpenCV4就实现了自己的图像数据结构—Mat对象。

2)数据计算模块主要用于一些常见的图像像素处理与操作。

3)数据计算模块之上的图像处理模块与高阶GUI模块是OpenCV中最常用也是最重要的基础模块。传统数字图像处理中的大部分常见算法与功能收录在图像处理模块中,毫不夸张地说,熟练掌握此模块,可以完成常见的图像处理和预处理任务。高阶GUI模块中常用的只有imshow函数。

在图1-1中,竖向的模块都依赖横向的模块。每个竖向模块基本上代表的是视觉领域的一个细分方向,它们也是开发者最常用的模块,主要包括2D特征提取、对象检测、视频分析、机器学习等模块。

本书将主要介绍这些常用模块的使用方法,读者在掌握这些常用模块使用方法的基础上,再去拓展学习其他模块会比较容易。

此外,图1-1最右侧的竖条表示扩展模块,扩展模块必须在单独编译之后方可使用。扩展模块中往往会收录一些最新的算法实现,但它们不是很成熟,没有经过项目的充分验证,所以使用扩展模块的开发者需要有一定的相关知识积累。

1.1.3 OpenCV4里程碑

OpenCV4是OpenCV最新的里程碑版本,其版本命名格式为OpenCV4.x,其中x表示小版本号。OpenCV4是在深度学习与人工智能兴起的背景下发布的,其中加入了对深度学习推理模块与加速模块的支持。同时,OpenCV4的易用性、稳定性、可靠性都达到了一个新的高度。本书将围绕OpenCV4.x版本展开相关知识点的学习,并完成代码实现与程序演示,选择该版本主要出于以下3个方面的考量。

1)OpenCV4与之前的版本存在很大的不同,用官方宣传的话说就是“OpenCV4 is more than OpenCV”。

2)OpenCV4版本的SDK与接口更加人性化,学习曲线平缓,初学者更容易入门,即使没有C++基础也能很快上手。

3)OpenCV4支持丰富的第三方加速库集成,无论是在端侧还是云侧,都可以加速程序运行。

1.1.4 OpenCV发展现状与应用趋势

经过多年的发展,OpenCV因其可靠、开源、支持多种语言、免费集成商业产品等优势,得到了开发者与知名商业公司的青睐。应用场景覆盖全面,对图像处理、机器视觉、工业机器人、智慧农业、无人驾驶等领域都有涉及。随着未来对人工智能与视觉技术需求的不断增加,OpenCV作为开源免费的视觉框架,具有比较明显的竞争优势,必将成为很多商业公司产品开发的首选。相信掌握OpenCV开发框架的技术型人才也会获得丰厚的回报。

1.2 OpenCV源码项目

本节内容是目前市面上很多OpenCV类图书所缺失的。笔者认为对于OpenCV这样一个开源项目,学习者必须了解它的目录结构与代码结构,以确保在开发过程中遇到问题时能够快速地从源码中找到答案。OpenCV源码托管在GitHub上,下载安装包之后解压缩即可查看源码目录,从源码目录可以更好地了解OpenCV项目。此外,源码也是文档的一部分,想要利用好这个“文档”,了解一下它的目录结构与模块分布是很有必要的。

OpenCV的GitHub源码托管地址为https://github.com/opencv/opencv,源码的相关文件夹主要涉及如下几个方面。

❑3rdparty:主要是OpenCV自身依赖的第三方库。

❑apps:主要是OpenCV自身功能相关的应用演示。

❑cmake:主要是CMake相关的脚本。

❑data:数据部分,主要是一些模型的XML数据文件。

❑doc:主要介绍基本语法的使用方法和各个模块的基本功能。

❑include:头文件目录。

❑modules:模块源码目录。

❑platforms:各个平台编译的支持配置等相关内容。

❑samples:官方提供的源码演示。

本书中使用的OpenCV官方图像资源与视频资源在samples/data文件夹中均可以找到,此外,如果你要自学一些模块,也可以随时查看samples中的源码文件,从中获取有用的信息。

1.3 OpenCV4开发环境搭建

很多人学习OpenCV时遇到的第一个棘手问题就是如何搭建OpenCV的开发环境,不同计算机的系统和设置偏好可能都不一样,对IDE的选择也不尽相同,这里就以本书代码演示的开发环境设置来搭建OpenCV4的开发环境。

第1步:安装好Visual Studio 2017(推荐安装专业版)。OpenCV4.5.4的下载地址为https://github.com/opencv/opencv/releases/download/4.5.4/opencv-4.5.4-vc14_vc15.exe。下载之后解压缩到D盘,将文件夹改名为opencv-4.5.4。

第2步:打开Visual Studio 2017,新建一个控制台应用,依次选择“视图”→“其他窗口”→“属性管理器”命令,在弹出的“属性管理器”窗口中右击图1-2所示的矩形框,并从弹出的快捷菜单中选择“属性”命令(截图略)。

图1-2 “属性管理器”窗口

在弹出的项目属性窗口中选择Visual C++目录,完成下面的配置即可。

1)添加包含目录:D:\opencv-4.5.4\opencv\build\include和D:\opencv-4.5.4\opencv\build\include\opencv2。

2)添加库目录:D:\opencv-4.5.4\opencv\build\x64\vc15\lib。

3)依次选择“链接器”→“输入”→“附加依赖性”命令,以添加opencv_world454.lib。

4)然后单击“确定”按钮保存设置,并在Windows的系统环境变量path中添加D:\opencv-4.5.4\opencv\build\x64\vc15\bin。

重新启动Visual Studio 2017,打开刚刚你新建的项目,新建一个cpp文件,并输入如下代码:

选择“配置管理器”命令,在弹出的“配置管理器”窗口中将配置模式设置为Release、x64,然后进行编译。环境测试的运行结果如图1-3所示。

图1-3 环境测试运行结果

如果看到此图,那么恭喜你已经迈出了学习OpenCV4最重要的一步,环境搭建顺利完成。

1.4 第一个OpenCV开发程序

本节将从代码层面带读者认识OpenCV版本的Hello World演示程序。下面通过一张图像的加载过程来讲解OpenCV程序中最常用的几个函数。

1)imread:读取一张图像并返回图像数据,该图像数据以Mat对象形式存在。

2)namedWindow:创建窗口。它有两个参数:第一个参数表示窗口名称;第二个参数表示窗口属性。

3)imshow:显示图像。它有两个参数:第一个参数表示图像显示窗口名称;第二个参数表示图像数据。

4)waitKey:当参数为0时,表示一直阻塞,直到用户按任意键结束;当参数大于0时,表示阻塞的毫秒数。

5)destroyAllWindows:表示销毁之前创建的所有窗口。

了解上面所用函数的功能之后,再回头去看之前测试程序的代码,就很容易理解了。要想完成一个简单的图像加载与显示程序,只需要如下几行代码即可:

这段代码虽然简单,但是后续内容会基于它来增加代码,以实现各种图像处理功能,所以说它是OpenCV演示程序的基本结构。正所谓“千里之行,始于足下”。

1.5 图像加载与保存

本节将重新审视OpenCV中的图像加载函数imread,同时学习如何通过imwrite函数保存图像。

1.5.1 加载图像

OpenCV使用imread函数实现图像的加载,该函数支持灰度图像、彩色图像、原始图像的加载。在默认情况下,通过imread加载的图像都是三通道BGR彩色图像。实际上,OpenCV支持加载灰度图像与带有透明通道的图像。imread函数原型如下所示:

在不修改第二个参数flags默认值的情况下,经常像如下这样使用该函数:

如果需要把图像以灰度图像的形式进行加载,则可以进行以下设置:

如果需要把具有透明通道的图像加载进来但不做任何改变,则可以进行以下设置:

1.5.2 保存图像

一般情况下,通过imwrite函数保存图像只需设置保存文件路径与Mat对象两个参数,但是实际上该函数还有第三个默认参数可以设置。第三个参数主要用于调整保存图像的压缩质量、位图深度和通道数目。如果需要修改默认保存的三通道彩色图像,开发者就要使用第3个参数对要保存的图像进行有针对性的写入图像文件操作。首先需要重新认识一下imwrite函数:

参数解释如下。

❑filename:表示保存文件的路径与名称,必须带图像文件扩展名。

❑img:内存中的Mat对象。

❑params:保存图像文件时需要优化的参数,默认为空。

对第3个参数params来说,当以不同的格式保存图像时,params参数的内容也是不一样的。

1)如果保存图像的格式为PNG,则调整压缩质量的参数为IMWRITE_PNG_COMPR-ESSION。该参数等级取值范围为0~9,默认值为1。值越大,压缩时间越长,图像大小越小。

2)如果保存图像的格式为JPG,则调整压缩质量的参数为IMWRITE_JPEG_QUALITY:等级取值范围为0~100,默认值为95。值越大,图像质量越高,图像大小也越大。

常见的不同通道与格式的图像保存代码如下。

1)保存为单通道灰度图像:

2)保存为默认的彩色BGR图像:

3)保存为PNG彩色压缩图像:

4)保存为JPG高压缩比图像:

5)保存为PNG格式,且带透明通道:

注意: 使用imread与imwrite两个函数进行图像读写的时候,特别需要注意默认的最后一个参数。这些参数可以帮助开发者有效实现各种图像加载与压缩保存需求。

1.6 加载视频

OpenCV不仅可以加载各种格式的图像文件,还支持加载主流格式的视频文件(如avi、mp4、wav等),支持直接读取视频流地址或者连接各种摄像头设备读取视频流。下面就来看一下OpenCV支持的视频读取函数:

其中,index表示摄像头的编号索引,默认从0开始。大家往往会忽视的是第二个参数apiPreference,它表示实际读取视频底层支持库。目前OpenCV支持CAP_FFMPEG、CAP_IMAGES和CAP_DSHOW这3种方式,默认表示自动检测支持库。当然,开发者也可以通过设置apiPreference参数实现强制支持。视频加载与显示的代码演示如下:

注意: 在处理视频的时候,在while循环的代码中,waitKey应该永远设置为waitKey(1),除非你对程序有特殊要求。比如,这里设置为waitKey(100)是为了让视频以正常速度播放。

(1)从摄像头中读取

要从摄像头中读取,只需要对上述演示代码中的capture.open进行修改即可,如下:

这样就可以实现从计算机自带的摄像头中读取视频流了。

注意: 这里声明了apiPreference参数实际使用的是CAP_DSHOW方式,当你不知道该用哪种方式的时候,CAP_ANY永远是你的第一选择。

(2)从视频URL地址中读取

从视频地址中读取信息的方式也很简单,只需要对上述演示代码中的capture.open进行修改即可,如下:

替换以后,编译运行,会播放高清电影的视频,真是一个惊喜,但很遗憾的是,没有声音。这里需要特别说明一下,OpenCV只对视频进行处理,没有处理音频,这是因为OpenCV是视觉库而不是音频处理库,不能处理音频相关的编解码。这一点后续将不再赘述。

(3)获取视频属性

OpenCV中的VideoCapture类还提供了一个get函数,该函数可以获取视频的常用属性,具体如下。

1)帧高度:对应get函数的属性为CAP_PROP_FRAME_HEIGHT。

2)帧宽度:对应get函数的属性为CAP_PROP_FRAME_WIDTH。

3)帧率(FPS):表示1秒内播放/处理的帧数,对应get函数的属性为CAP_PROP_FPS。

4)总帧数:视频文件总的帧数,对应get函数的属性为CAP_PROP_FRAME_COUNT。

从视频文件中获取上述4个属性的代码如下:

(4)保存视频

有时,OpenCV需要用来保存一段经过处理的视频片段,方便以后查看或者分析程序处理效果,这个时候就需要通过VideoWriter类来实现视频保存的功能。关键问题是,如何初始化VideoWriter类的实例,实现代码如下:

完成初始化以后,就可以在为每帧调用writer.write(frame)时完成视频文件的写入操作了。

完整的加载和保存视频的示例代码如下:

这里需要特别说明的是,在初始化VideoWriter对象的时候,强烈建议通过代码读取视频文件的方式直接调用capture.get(CAP_PROP_FOURCC),避免手动设置编码导致出现不支持问题。另外,在程序正常结束之前,需要调用release方法释放capture对象与writer对象。

1.7 小结

本章介绍了OpenCV框架、开发环境的搭建,以及图像读取、视频读取、图像与视频文件的显示及保存。读者还需要掌握这些操作相关的函数知识,特别是参数的意义,以方便后续的学习与实践。同时,特别指出了一些初学者应该注意的地方,希望初次接触OpenCV的读者能够认真体会并牢记。 0o6lzDRPH7o2Uj6a5PTm2KswoNXNG0657jUBhVRB4p88zGM/5+SmfD14dukz3ghk

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开