OpenCV深度学习应用与性能优化实践
上QQ阅读APP看书,第一时间看更新

1.1 OpenCV处理流程

在数字的世界中,一幅图像由多个点(像素)组成。图像处理就是对其中一个像素或者一个区域内的像素(块)进行处理。无论是初学者还是富有经验的研发人员,他们都需要借助软件工具来分析这些像素和图像块,OpenCV则是其中最常用、最重要的一个软件工具。OpenCV成为最主要的图像处理工具包,是因为它功能齐全,支持目前主流的图像、视频处理算法,而且对外提供C++、Python和Java的接口,用户调用方便。本书的代码分析、示例程序及环境搭建基于OpenCV 4.1版本,源代码位于GitHub的OpenCV仓库 参见https://github.com/opencv/opencv/tree/4.1.0。

[1] 参见https://github.com/opencv/opencv/tree/4.1.0。

1.1.1 OpenCV库

OpenCV由各种不同组件组成。OpenCV源代码主要由OpenCV core(核心库)、opencv_contrib和opencv_extra等子仓库组成。近些年,OpenCV的主仓库增加了深度学习相关的子仓库:OpenVINO(即DLDT,Deep Learning Deployment Toolkit) 参见https://github.com/opencv/dldt。、open_model_zoo,以及标注工具CVAT等。

下面分别介绍3个主要的代码库:OpenCV core、opencv_contrib、opencv_extra。

1.核心库OpenCV core

核心库是OpenCV的主要算法来源。OpenCV采用模块化结构设计,包含了多个共享或者静态库。目前OpenCV核心库提供了很多组件,参见表1-1。

表1-1 OpenCV库分类

2.opencv_contrib

opencv_contrib代码库主要用于管理新功能模块的开发。该库的设计主要基于以下考虑:处于初始开发阶段的功能模块,它的API定义会经常变化,各种测试也不够全面。为了不影响OpenCV核心模块的稳定性,这些新功能模块会发布到opencv_contrib中。等到模块足够成熟并且在社区得到了足够的关注和使用之后,这个模块便会被移到OpenCV核心库,这意味着核心库开发团队将会对该模块进行全面的测试,保证这个模块具有产品级的质量。例如,对于DNN这个模块,OpenCV 3.1开始出现在opencv_contrib中,到了3.3版本才移到了OpenCV核心库。

opencv_contrib需要和OpenCV核心库一同编译。下载好opencv_contrib的源代码并在CMake执行时传入参数:-DOPENCV_EXTRA_MODULES_PATH=<opencv_contrib源码路径>/modules。如果编译时遇到问题,则可以在OpenCV核心库和opencv_contrib库的问题汇报页面 参见https://github.com/opencv/opencv/issues。 参见https://github.com/opencv/opencv_contrib/issues。查看一下是否有现成的解决方案,如果没有,则读者可新建一个问题。OpenCV是一个活跃的社区,只要问题描述清晰、完整,一般会很快得到反馈。

3.opencv_extra

opencv_extra仓库存放了运行测试和示例程序时需要使用的一些测试数据和脚本。例如,运行DNN模块测试程序或者示例程序时需要用到预训练模型,这些模型可以通过opencv_extra中的脚本 参见https://github.com/opencv/opencv_extra/blob/master/testdata/dnn/download_models.py。来自动下载。近些年添加的opencv/open_model_zoo仓库也增加了很多预训练好的深度学习模型,这些模型大多做过性能和速度上的调优。

[1] 参见https://github.com/opencv/dldt。

[2] 参见https://github.com/opencv/opencv/issues。

[3] 参见https://github.com/opencv/opencv_contrib/issues。

[4] 参见https://github.com/opencv/opencv_extra/blob/master/testdata/dnn/download_models.py。

1.1.2 OpenCV深度学习应用的典型流程

OpenCV是一个自包含库,可以不依赖于任何第三方库而运行,这个特性给开发调试带来了很大的便利。另外,OpenCV还提供了硬件加速功能,使得算法能够在各种平台高效地执行。

下面以一个识别性别和年龄的深度学习应用为例,展现OpenCV深度学习应用的典型流程。该应用使用C++语言,总共只需要百来行代码便可实现人脸检测、性别和年龄的识别功能,还可以方便地使用硬件的加速能力,提高程序的运行效率。此处展示核心流程,故以伪代码为例,完整的源代码由本书的参考代码库提供。

该应用的核心流程如下:首先读取两个网络模型参数(分别是性别和年龄),然后检测人脸,转换输入图像,最后运行网络前向预测。伪代码如下:


// 引入OpenCV DNN模块的命名空间
using namespace cv::dnn;
// 创建人脸检测器
CascadeClassifier cascade;

// 导入性别和年龄深度神经网络模型
Net gender_net=dnn::readNetFromCaffe(gender_modelTxt, gender_modelBin);
Net age_net=dnn::readNetFromCaffe(age_modelTxt, age_modelBin);
// 人脸检测
cascade.load(cascadeName);
cascade.detectMultiScale(input_gray_file, output_faces_data);

// 准备深度神经网络的输入数据
Mat inputBlob=blobFromImage(input.getMat(ACCESS_READ));
gender_net.setInput(inputBlob, "data");
age_net.setInput(inputBlob, "data");

// 执行模型的前向运算,即模型推理
Mat gender_prob=gender_net.forward("prob");
Mat age_prob=age_net.forward("prob");

应用识别效果如图1-1所示。

以上伪代码很好地展示了OpenCV深度学习应用的典型流程,如图1-2所示。

图1-1 应用识别效果图

图1-2 OpenCV深度学习应用的典型流程