【周末送书】使用OpenCV和OpenVINO轻松创建深度学习应用(附实现方式和代码出处)

简介: 【周末送书】使用OpenCV和OpenVINO轻松创建深度学习应用(附实现方式和代码出处)

OpenCV 是业界使用最为广泛的计算机视觉库,随着深度学习在计算机视觉领域的广泛应用,OpenCV 自3.3开始加入对深度学习推理的支持,即OpenCV DNN模块。


它支持TensorFlow、Caffe、Torch、DarkNet、ONNX 和 OpenVINO 格式的网络模型,开发者无需考虑模型格式的差异,直接调用DNN模块相关接口即可快速创建深度学习应用。


OpenVINO是英特尔推出的视觉推理加速工具包。OpenCV 3.4.1版本加入了英特尔推理引擎后端(英特尔推理引擎是OpenVINO中的一个组件),为英特尔平台的模型推理进行加速。


本文将以MobileNet-SSD模型为例,展示如何使用OpenCV和OpenVINO快速创建深度学习应用。


在深入代码之前,让我们了解一下OpenVINO工具包以及OpenCV是如何跟OpenVINO交互的。


OpenVINO工具包


2018 年 5 月 Intel 发布了 OpenVINO(Open Visual Inferencing and Neural Network Optimization, 开放视觉推理和神经网络优化)工具包,旨在为运行于 Intel 计算平台的基于神经网络的视觉推理任务提供高性能加速方案。


OpenVINO 提供了一整套在 Intel 计算设备上完成深度学习推理计算的解决方案,它支持 Intel CPU、 GPU、FPGA 和 Movidius 计算棒等多种设备。


OpenVINO 工具包的主要组件是 DLDT(Deep Learning Deployment Toolkit,深度学习部署工具包)。DLDT主要包括模型优化器(Model Optimizer)和推理引擎(Inference engine,IE)两部分。


模型优化器负责将各种格式的深度神经网络模型转换成统一的自定义格式,并在转换过程中进行模型优化;推理引擎接受经过模型优化器转换并优化的网络模型,为Intel的各种计算设备提供高性能的神经网络推理运算。


使用 DLDT 进行神经网络模型的部署,典型工作流程如图所示。



1)训练一个DLDT 支持的深度学习框架网络模型(Train a Model) ;


2)使用模型优化器对网络模型进行编译和优化(Run Model Optimizer),生成Openvino IR(Intermediate Representation,中间表示)格式的网络配置文件(.xml 文件)和模型参数文件(.bin 文件);


3)调用 Inference Engine(即 Intel 推理引擎)进行网络运算,并将结果返回给 User Application(应用程序)。


OpenCV如何使用OpenVINO


OpenCV的推理引擎后端使用OpenVINO的推理引擎API完成推理任务。推理引擎后端有两种工作模式:模型优化器模式和构建器模式,如下图所示。



模型优化器模式直接使用DLDT模型优化器编译后的OpenVINO格式(.xml和.bin)的网络模型进行推理计算,这种模式下,网络模型将被直接加载到推理引擎中,创建出一个推理引擎网络对象。而构建器模式则需要在DNN模块内部将网络模型逐层转换成内部表示,并通过推理引擎后端建立内部推理引擎网络。


相比构建器模式,模型优化器模式支持网络中所有的层,不需要逐层建立DNN网络,而是直接加载OpenVINO模型到推理引擎,能够减少在网络加载和运算推理过程中报错的情况。


了解了OpenCV 和 OpenVINO 相关内容之后,接下来详细讲解如何基于OpenCV和OpenVINO构建深度学习应用。


基于OpenCV和OpenVINO创建深度学习应用


第一步:安装OpenVINO


这里我们以 Ubuntu 18.04 上安装 OpenVINO 为例。从官网注册并下载OpenVINO开发包的Linux版本,


官网下载地址:

https://software.intel.com/content/www/us/en/develop/tools/openvino-toolkit/choose-download/linux.html 


如果下载顺利,你将得到文件名为 l_openvino_toolkit_p_< 版本号>.tgz 的压缩包,为了兼容更多的网络模型,我们选择安装目前最新的OpenVINO版本(OpenVINO-2020.3.194)。


OpenVINO开发包中包含了相应版本的OpenCV,安装OpenVINO时会默认安装OpenCV,因此无需额外安装OpenCV


1. 解压并安装 OpenVINO 开发包核心组件

$ tar -xvzf l_openvino_toolkit_p_2020.3.194.tgz$ cd l_openvino_toolkit_p_2020.3.194

运行图形化安装命令:

$ sudo ./install_GUI.sh

然后一路选择“Next”安装默认组件即可。如果一切顺利,安装文件将位于/opt/intel/openvino_2020.3.194/,同时会生成一个符号链接/opt/intel/openvino 指向最新的安装目录。至此,OpenVINO 核心组件安装完成,接下来安装依赖包。


2. 安装依赖包

使用 OpenVINO 写一个完整的视觉类应用,除了 OpenVINO 本身之外,还需要安装一些依赖包,包括但不限于 FFMpeg视频框架、CMake 编译工具、libusb(Movidius 神经计算棒 插件需要用到)等,安装步骤如下:


$ cd /opt/intel/openvino/install_dependencies

运行以下命令安装必要的依赖包:


$ sudo -E ./install_openvino_dependencies.sh

设置环境变量:


$ source /opt/intel/openvino/bin/setupvars.sh

建议将以上环境变量设置命令加入到用户的环境脚本当中,方法如下:


$ vi <用户目录>/.bashrc

在其中加入以内容:


$ source /opt/intel/openvino/bin/setupvars.sh

按 Esc 键,然后输入“:wq”保存并退出。接下来配置模型优化器,依次运行以下命令:



$ cd /opt/intel/openvino/deployment_tools/model_optimizer/install_prerequisites$ sudo ./install_prerequisites.sh

上面这条命令会安装所有的深度学习框架的支持,如果只希望安装某一个框架的支持,以安装Caffe 框架支持为例,可以这么做:


$ sudo ./install_prerequisites_caffe.sh

至此,安装工作结束,下面验证安装好的 OpenVINO 环境是否可以工作。


3. 验证 OpenVINO 环境

进入推理引擎示例程序目录:


$ cd /opt/intel/openvino/deployment_tools/demo

运行图片分类示例程序的验证脚本:


$ ./demo_squeezenet_download_convert_run.sh

如果一切顺利,输出结果将如图所示。

确保 OpenVINO 安装成功后,重新启动电脑:


$ reboot

检查OpenCV版本:

$ python> import cv2 as cv> print(cv.__version__)

如果安装成功,可以看到如下输出:

4.3.0-openvino-2020.3.0


第二步:模型准备

首先下载MobileNet-SSD的caffe模型:


• 模型参数文件MoblieNetSSD_deploy.caffemodel下载地址:https://drive.google.com/open?id=0B3gersZ2cHIxRm5PMWRoTkdHdHc


• 网络结构文件MoblieNetSSD_deploy.prototxt下载地址:https://raw.githubusercontent.com/chuanqi305/MobileNet-SSD/daef68a6c2f5fbb8c88404266aa28180646d17e0/MobileNetSSD_deploy.prototxt 


模型下载好后,将caffe模型转换成OpenVINO格式:


1. 进入OpenVINO安装目录下的模型优化器目录:


cd <INSTALL_DIR>/deployment_tools/model_optimizer

2. 使用OpenVINO模型优化器脚本mo.py将caffe模型转换成OpenVINO格式的模型:


python3 mo.py --input_model <working_dir>/MobileNetSSD_deploy.caffemodel --input_proto <working_dir>/MobileNetSSD_deploy.prototxt -o <output_path>


通过input_model和input_proto 两个参数指明模型的参数和结构,并指定转换后网络的存储路径。


通过这一步,我们可以得到OpenVINO格式的MobileNet-SSD网络模型,包括MobileNetSSD_deploy.xml文件和MobileNetSSD_deploy.bin 文件。


第三步:使用OpenVINO模型进行目标检测


接下来开始进入我们的最后一步,使用转换好的OpenVINO格式的MobileNet-SSD模型进行实时目标检测。下面是整个目标检测过程的流程图。


流程图



程序代码

为方便起见,我们采用Python语言来创建应用。首先导入必要的Python库,包括numpy、argparse和cv2(OpenCV)。

# 导入必要的库
import numpy as np
import argparse
import cv2

接下来使用argparse对命令行输入参数进行解析。

# 组建参数parse
parser = argparse.ArgumentParser(
    description='Script to run MobileNet-SSD object detection network ')
parser.add_argument("--video", help="path to video file. If empty, camera's stream will be used")
parser.add_argument("--model", type=str, default="MobileNetSSD_deploy",
                               help="path to trained model")
parser.add_argument("--thr", default=0.2, type=float, help="confidence threshold to filter out weak detections")
args = parser.parse_args()


程序执行命令行只需输入下列 3 个参数。

• video:图片或视频路径,不设置则从摄像头读取数据。

• model:训练好的模型路径。

• thr:分类阈值。


定义一个变量classNames,存储分类标签。注意,我们下载的模型是基于20分类数据集训练出来的,因此这里的类别标签有20个(加上背景是21个)。也有针对90分类数据集训练的模型,此处需要使用相对应的标签定义。

# 类别标签变量.
classNames = { 0: 'background',
    1: 'aeroplane', 2: 'bicycle', 3: 'bird', 4: 'boat',
    5: 'bottle', 6: 'bus', 7: 'car', 8: 'cat', 9: 'chair',
    10: 'cow', 11: 'diningtable', 12: 'dog', 13: 'horse',
    14: 'motorbike', 15: 'person', 16: 'pottedplant',
    17: 'sheep', 18: 'sofa', 19: 'train', 20: 'tvmonitor' }

定义模型输入大小,MobileNet-SSD接受的输入图片大小为300*300

input_size = (300, 300)

接下来通过cv2.dnn.Net_readFromModelOptimizer()函数读取转换好的OpenVINO模型文件,初始化网络对象 net,并设置加速后端:

# 加载模型 
net = cv2.dnn.Net_readFromModelOptimizer(args.model+".xml", args.model+".bin")
# 设置推理引擎后端
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_INFERENCE_ENGINE)

注意,这里cv2.dnn.DNN_BACKEND_INFERENCE_ENGINE指明使用的是推理引擎后端。


# 设置运算设备
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)

推理引擎后端支持多种类型的运算设备,这里指定使用CPU作为运算设备。如果平台有英特尔集成显卡,也可以设置成cv2.dnn.DNN_TARGET_OPENCL,使用GPU来进行加速。

下一步设置图像输入设备,根据参数video选择可用输入设备或者输入路径:

# 打开视频文件或摄像头 
if args.video:
    cap = cv2.VideoCapture(args.video)
else:
    cap = cv2.VideoCapture(0)

现在进入程序关键步骤,开始循环处理输入设备读到的帧图像,将读取到的图像转换成网络输入:

while True:
    # 读取一帧图像
    ret, frame = cap.read()
    # 将图片转换成模型输入
    blob = cv2.dnn.blobFromImage(frame, 0.007843, input_size, (127.5, 127.5, 127.5), False)

这一步参数比较多,也比较重要,做一下重点讲解:


1)frame是输入图像,0.007843是缩放因子,

2)input_size是模型所接受的输入大小,(127.5, 127.5, 127.5)是图像均值,它结合前面的缩放因子,在函数内部对输入图像做正规化处理。

3)False表示不进行R和B通道置换。当模型接受的通道顺序和图像均值的通道顺序不一致时,swapRB 需要设置成 true。


接下来是设置网络输入和运行网络推理:

# 转换后的待输入对象blob设置为网络输入
    net.setInput(blob)
# 开始进行网络推理运算
    detections = net.forward()

然后是结果解析。


MobileNet-SSD 模型的检测结果detections是一个4维数组,数组的4个维度大小分别是[1,1,N,7]。

N表示检测出的对象数目,7表示每个对象用一个含有7个元素的数组描述,7个元素分别代表图片id、类型id、置信度、对象框左上角x坐标,对象框左下角y坐标、对象框右下角x坐标、对象框右下角y坐标,接下来根据这个4维数组绘制运行结果。


首先获取图像大小,根据再通过遍历所有检测出的对象,通过参数thr筛除部分置信度较低的对象:

# 获取输入图像尺寸(300x300)
cols = input_size[1]
rows = input_size[0]
    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2] # 目标对象置信度 
        if confidence > args.thr: # Filter prediction
            class_id = int(detections[0, 0, i, 1]) # 目标对象类别标签

获取被检测对象框的顶点坐标和图像的缩放比,并获取实际目标对象框的坐标:

# 目标位置
xLeftBottom = int(detections[0, 0, i, 3] * cols)
yLeftBottom = int(detections[0, 0, i, 4] * rows)
xRightTop   = int(detections[0, 0, i, 5] * cols)
yRightTop   = int(detections[0, 0, i, 6] * rows)
# 变换尺度
heightFactor = frame.shape[0]/300.0  
widthFactor = frame.shape[1]/300.0
# 获取目标实际坐标
xLeftBottom = int(widthFactor * xLeftBottom)
yLeftBottom = int(heightFactor * yLeftBottom)
xRightTop   = int(widthFactor * xRightTop)
yRightTop   = int(heightFactor * yRightTop)

最后将检测结果绘制到原始图像上:

# 框出目标对象
cv2.rectangle(frame, (xLeftBottom, yLeftBottom), (xRightTop, yRightTop),
                          (0, 255, 0))
# 标记标签和置信度
if class_id in classNames:
    label = classNames[class_id] + ": " + str(confidence)
    labelSize, baseLine = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
    yLeftBottom = max(yLeftBottom, labelSize[1])
    cv2.rectangle(frame, (xLeftBottom, yLeftBottom - labelSize[1]),
                          (xLeftBottom + labelSize[0], yLeftBottom + baseLine),
                          (255, 255, 255), cv2.FILLED)
    cv2.putText(frame, label, (xLeftBottom, yLeftBottom),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))
    print(label) # 输出类别和置信度
cv2.namedWindow("frame", cv2.WINDOW_NORMAL)
    cv2.imshow("frame", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"): # 按下q键退出程序
   break
if key == ord("s"): # 按下s键保存检测图像
   cv2.imwrite('detection.jpg', frame)

至此,整个目标检测应用的代码就完成了,接下来输入以下命令运行目标检测程序:


$ python mobilenet_ssd_python.py

这里我们使用的默认参数,通过摄像头直接采集图像,默认模型采用我们转换好的MobileNetSSD_deploy(.xml/.bin)文件,阈值设为0.2。


这时候我们可以看到终端中将输出检测到的目标置信度,同时在视频图像中框处检测到的目标,左上角为目标分类结果和分类置信度。


终端中的检测结果输出:

chair: 0.9978288
chair: 0.29011992
person: 0.9536861
tvmonitor: 0.6713625
tvmonitor: 0.26635352
...

实际检测图像如下:


相关文章
|
10小时前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习在自然语言处理中的应用与挑战
在人工智能领域,深度学习技术已成为推动自然语言处理(NLP)进步的关键力量。本文将深入探讨深度学习如何革新NLP领域,包括语音识别、机器翻译、情感分析等方面的应用,并讨论当前面临的主要挑战,如数据偏差和模型解释性问题。通过引用最新的研究成果和实例分析,本文旨在为读者提供深度学习在NLP中应用的全面视角,同时指出未来的研究方向。
|
10小时前
|
机器学习/深度学习 算法 计算机视觉
探索深度学习在图像识别中的应用与挑战
【7月更文挑战第4天】本文深入探讨了深度学习技术在图像识别领域的应用,并分析了其面临的主要挑战。通过介绍深度学习的基础原理和关键技术,我们揭示了其在图像处理任务中的强大能力,包括特征提取、对象检测和分类。同时,文章也指出了深度学习模型在泛化能力、数据依赖性以及计算资源需求方面存在的问题,并提出了可能的解决策略,旨在为未来图像识别技术的发展提供参考。
|
1天前
|
机器学习/深度学习 算法 自动驾驶
深度学习在图像识别中的应用与挑战
【7月更文挑战第3天】 本文深入探讨了深度学习技术在图像识别领域内的应用及其所面临的挑战。首先,文章概述了深度学习如何革新了图像处理的范式,接着详细讨论了卷积神经网络(CNN)在图像分类、目标检测及语义分割中的具体应用。然后转向挑战部分,分析了数据集偏差、模型泛化能力以及对抗性攻击等问题。最后,文章提出了未来研究方向,包括算法优化、跨域适应性学习以及隐私保护等议题。
|
1天前
|
机器学习/深度学习 自然语言处理 测试技术
深度学习在自然语言处理中的应用与挑战
本文深入探讨了深度学习技术在自然语言处理(NLP)领域的应用及其所面临的挑战。通过分析最新的研究数据和实验结果,文章揭示了深度学习模型如循环神经网络(RNN)、长短时记忆网络(LSTM)和Transformer架构在文本分类、机器翻译、情感分析等任务中的卓越表现。同时,讨论了深度学习在处理语言多样性、语境理解不足以及数据偏差等问题上的挑战,并提出了可能的解决方案。本文旨在为NLP领域的研究者和实践者提供深度学习技术的全面视角,促进其在实际应用中的创新与发展。
|
1天前
|
机器学习/深度学习 自然语言处理 算法
深度学习在自然语言处理中的应用与挑战
随着人工智能技术的飞速发展,深度学习已成为自然语言处理领域的核心技术之一。本文将深入探讨深度学习在自然语言处理中的应用及其面临的挑战。首先,我们将介绍深度学习的基本概念和关键技术;然后,我们将分析深度学习在自然语言处理中的应用领域,如语音识别、机器翻译和情感分析等;最后,我们将讨论深度学习在自然语言处理中面临的挑战,包括数据稀疏性、模型可解释性和跨领域适应性等问题。通过本文的研究,我们希望为深度学习在自然语言处理领域的进一步发展提供有益的启示。
9 0
|
1天前
|
机器学习/深度学习 算法 数据安全/隐私保护
深度学习在医疗影像分析中的应用与挑战
随着人工智能技术的飞速发展,深度学习已成为医疗影像分析领域的革命性工具。本文将深入探讨深度学习技术在医疗影像分析中的具体应用,包括疾病诊断、治疗规划和预后评估等方面。同时,也将分析当前面临的主要挑战,如数据隐私保护、算法透明度和跨域泛化能力等。通过引用最新的科研研究和权威统计数据,本文旨在提供一个科学严谨、逻辑严密的视角,以理解深度学习在医疗影像分析中的潜力与局限。
10 0
|
1天前
|
机器学习/深度学习 算法 搜索推荐
深度学习在医疗影像分析中的应用及其挑战
本文深入探讨了深度学习技术在医疗影像分析领域的应用,并详细分析了当前面临的主要挑战。通过综合研究数据和案例分析,本文揭示了深度学习如何提高诊断准确性,加速疾病检测流程,并辅助临床决策。同时,文章也指出了数据隐私、模型泛化能力以及跨域适应性等关键问题,为深度学习技术的未来发展提供了方向。
7 0
|
1天前
|
机器学习/深度学习 自动驾驶 安全
基于深度学习的图像识别技术在自动驾驶中的应用
随着人工智能技术的飞速发展,深度学习已成为推动自动驾驶技术进步的核心动力。本文深入探讨了深度学习在图像识别领域的应用,并分析了其在自动驾驶系统中的关键作用。通过引用最新的研究成果和实验数据,本文揭示了深度学习模型如何提高自动驾驶车辆对环境的感知能力,从而增强驾驶安全性和效率。
9 1
|
1天前
|
机器学习/深度学习 自动驾驶 算法
深度学习在图像识别中的应用与挑战
【7月更文挑战第3天】随着人工智能技术的飞速发展,深度学习已成为图像识别领域的核心技术之一。本文旨在探讨深度学习如何革新图像识别技术,分析其在处理复杂视觉数据方面的有效性,并指出当前面临的主要挑战。从理论到实践,我们不仅审视了深度学习模型的架构和训练技巧,还讨论了数据集偏差、过拟合问题以及对抗性攻击等现实问题对模型性能的影响。此外,文章还将展望未来图像识别技术的发展方向,为研究人员和实践者提供指导和启示。
|
2天前
|
机器学习/深度学习 人工智能 自动驾驶
深度学习在图像识别中的应用及其挑战
本文将探讨深度学习技术在图像识别领域的应用,以及在这一过程中遇到的挑战。我们将通过分析最新的研究成果和实验数据,深入理解深度学习如何改变图像识别的面貌,并讨论其面临的主要问题和可能的解决方案。
12 0