智慧交通day01-算法库03:cv.dnn

简介: 使用方便。DNN模块提供了内建的CPU和GPU加速,无需依赖第三方库,若项目中之前使用了OpenCV,那么通过DNN模块可以很方便的为原项目添加深度学习的能力。

815902569f6a467a99304f9ac1482386.png


1.DNN模块


1.1. 模块简介


OpenCV中的深度学习模块(DNN)只提供了推理功能,不涉及模型的训练,支持多种深度学习框架,比如TensorFlow,Caffe,Torch和Darknet。


d65f3f9d9cc24592ade9a820af7879d6.png


OpenCV那为什么要实现深度学习模块?


  • 轻量型。DNN模块只实现了推理功能,代码量及编译运行开销远小于其他深度学习模型框架。


  • 使用方便。DNN模块提供了内建的CPU和GPU加速,无需依赖第三方库,若项目中之前使用了OpenCV,那么通过DNN模块可以很方便的为原项目添加深度学习的能力。


  • 通用性。DNN模块支持多种网络模型格式,用户无需额外的进行网络模型的转换就可以直接使用,支持的网络结构涵盖了常用的目标分类,目标检测和图像分割的类别,如下图所示:


608b52d2cb1e42038068fddd8c526fe7.png


DNN模块支持多种类型网络层,基本涵盖常见的网络运算需求。


d8d20a7d3b5b48a2b0f8b9f98e72f5a0.png


也支持多种运算设备(CPU,GPU等)和操作系统(Linux,windows,MacOS等)。


1.2.模块架构


DNN模块的架构如下图所示:


774db591cf3f492a87666f6f81de7e74.png


从上往下依次是:


  • 第一层:语言绑定层,主要支持Python和Java,还包括准确度测试、性能测试和部分示例程序。
  • 第二层:C++的API层,是原生的API,功能主要包括加载网络模型、推理运算以及获取网络的输出等。
  • 第三层:实现层,包括模型转换器、DNN引擎以及层实现等。模型转换器将各种网络模型格式转换为DNN模块的内部表示,DNN引擎负责内部网络的组织和优化,层实现指各种层运算的实现过程。
  • 第四层:加速层,包括CPU加速、GPU加速、Halide加速和Intel推理引擎加速。CPU加速用到了SSE和AVX指令以及大量的多线程元语,而OpenCL加速是针对GPU进行并行运算的加速。Halide是一个实验性的实现,并且性能一般。Intel推理引擎加速需要安装OpenVINO库,它可以实现在CPU、GPU和VPU上的加速,在GPU上内部会调用clDNN库来做GPU上的加速,在CPU上内部会调用MKL-DNN来做CPU加速,而Movidius主要是在VPU上使用的专用库来进行加速。


除了上述的加速方法外,DNN模块还有网络层面的优化。这种优化优化分两类,一类是层融合,还有一类是内存复用。


  • 层融合


层融合通过对网络结构的分析,把多个层合并到一起,从而降低网络复杂度和减少运算量。


c39a56da76e24af7963ed69a12b701df.png


如上图所示,卷积层后面的BatchNorm层、Scale层和RelU层都被合并到了卷积层当中。这样一来,四个层运算最终变成了一个层运算。



0e6ef3d84e3147a2a9ad17c085564864.png


如上图所示,网络结构将卷积层1和Eltwise Layer和RelU Layer合并成一个卷积层,将卷积层2作为第一个卷积层新增的一个输入。这样一来,原先的四个网络层变成了两个网络层运算。


4094986e31214cf8a99df6522f720887.png


如上图所示,原始的网络结构把三个层的输出通过连接层连接之后输入到后续层,这种情况可以把中间的连接层直接去掉,将三个网络层输出直接接到第四层的输入上面,这种网络结构多出现SSD类型的网络架构当中。


  • 内存复用


深度神经网络运算过程当中会占用非常大量的内存资源,一部分是用来存储权重值,另一部分是用来存储中间层的运算结果。我们考虑到网络运算是一层一层按顺序进行的,因此后面的层可以复用前面的层分配的内存。


下图是一个没有经过优化的内存重用的运行时的存储结构,红色块代表的是分配出来的内存,绿色块代表的是一个引用内存,蓝色箭头代表的是引用方向。数据流是自下而上流动的,层的计算顺序也是自下而上进行运算。每一层都会分配自己的输出内存,这个输出被后续层引用为输入。


64271d3b73104ddeafd0d30ac37ad98c.png


对内存复用也有两种方法:


第一种内存复用的方法是输入内存复用。


0ab9f226ab4844c1a7d388c670e80006.png


如上图所示,如果我们的层运算是一个in-place模式,那么我们无须为输出分配内存,直接把输出结果写到输入的内存当中即可。in-place模式指的是运算结果可以直接写回到输入而不影响其他位置的运算,如每个像素点做一次Scale的运算。类似于in-place模式的情况,就可以使用输入内存复用的方式。


第二种内存复用的方法是后续层复用前面层的输出。


3d55976d875a441194b8721e6f313f94.png


如上图所示,在这个例子中,Layer3在运算时,Layer1和Layer2已经完成了运算。此时,Layer1的输出内存已经空闲下来,因此,Layer3不需要再分配自己的内存,直接引用Layer1的输出内存即可。由于深度神经网络的层数可以非常多,这种复用情景会大量的出现,使用这种复用方式之后,网络运算的内存占用量会下降30%~70%。


2.常用方法简介


DNN模块有很多可直接调用的Python API接口,现将其介绍如下:


2.1.dnn.blobFromImage


作用:根据输入图像,创建维度N(图片的个数),通道数C,高H和宽W次序的blobs


原型:


blobFromImage(image, 
                  scalefactor=None, 
                  size=None, 
                  mean=None, 
                  swapRB=None, 
                  crop=None, 
                  ddepth=None):


参数:


  • image:cv2.imread 读取的图片数据


  • scalefactor: 缩放像素值,如 [0, 255] - [0, 1]


  • size: 输出blob(图像)的尺寸,如 (netInWidth, netInHeight)


  • mean: 从各通道减均值. 如果输入 image 为 BGR 次序,且swapRB=True,则通道次序为 (mean-R, mean-G, mean-B).


  • swapRB: 交换 3 通道图片的第一个和最后一个通道,如 BGR - RGB


  • crop: 图像尺寸 resize 后是否裁剪. 如果crop=True,则,输入图片的尺寸调整resize后,一个边对应与 size 的一个维度,而另一个边的值大于等于 size 的另一个维度;然后从 resize 后的图片中心进行 crop. 如果crop=False,则无需 crop,只需保持图片的长宽比


  • ddepth: 输出 blob 的 Depth. 可选: CV_32F 或 CV_8U


示例:


import cv2
from cv2 import dnn
import numpy as np 
import matplotlib.pyplot as plt
img_cv2 = cv2.imread("test.jpeg")
print("原图像大小: ", img_cv2.shape)
inWidth = 256
inHeight = 256
outBlob1 = cv2.dnn.blobFromImage(img_cv2,
                                scalefactor=1.0 / 255,
                                size=(inWidth, inHeight),
                                mean=(0, 0, 0),
                                swapRB=False,
                                crop=False)
print("未裁剪输出: ", outBlob1.shape)
outimg1 = np.transpose(outBlob1[0], (1, 2, 0))
outBlob2 = cv2.dnn.blobFromImage(img_cv2,
                                scalefactor=1.0 / 255,
                                size=(inWidth, inHeight),
                                mean=(0, 0, 0),
                                swapRB=False,
                                crop=True)
print("裁剪输出: ", outBlob2.shape)
outimg2 = np.transpose(outBlob2[0], (1, 2, 0))
plt.figure(figsize=[10, 10])
plt.subplot(1, 3, 1)
plt.title('输入图像', fontsize=16)
plt.imshow(cv2.cvtColor(img_cv2, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.subplot(1, 3, 2)
plt.title('输出图像 - 未裁剪', fontsize=16)
plt.imshow(cv2.cvtColor(outimg1, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.subplot(1, 3, 3)
plt.title('输出图像 - 裁剪', fontsize=16)
plt.imshow(cv2.cvtColor(outimg2, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.show()


输出结果为:


56473983ea2f4f58995e8fe5d79f1b5b.png


另外一个API与上述API类似,是进行批量图片处理的,其原型如下所示:


blobFromImages(images, 
                   scalefactor=None, 
                   size=None, mean=None, 
                   swapRB=None, 
                   crop=None, 
                   ddepth=None):


作用:批量处理图片,创建4维的blob,其它参数类似于 dnn.blobFromImage。


2.2.dnn.NMSBoxes


作用:根据给定的检测boxes和对应的scores进行NMS(非极大值抑制)处理


原型:


NMSBoxes(bboxes, 
             scores, 
             score_threshold, 
             nms_threshold, 
             eta=None, 
             top_k=None
        )


参数:


  • boxes: 待处理的边界框 bounding boxes
  • scores: 对于于待处理边界框的 scores
  • score_threshold: 用于过滤 boxes 的 score 阈值
  • nms_threshold: NMS 用到的阈值
  • indices: NMS 处理后所保留的边界框的索引值
  • eta: 自适应阈值公式中的相关系数:


ca57b3be2b97459e9839b18d0e80c479.png


  • top_k: 如果 top_k>0,则保留最多 top_k 个边界框索引值.


2.3. dnn.readNet


作用:加载深度学习网络及其模型参数


原型:


readNet(model, config=None, framework=None)


参数:


  • model: 训练的权重参数的模型二值文件,支持的格式有:*.caffemodel(Caffe)、*.pb(TensorFlow)、*.t7 或 *.net(Torch)、 *.weights(Darknet)、*.bin(DLDT).


  • config: 包含网络配置的文本文件,支持的格式有:*.prototxt (Caffe)、*.pbtxt (TensorFlow)、*.cfg (Darknet)、*.xml (DLDT).


  • framework: 所支持格式的框架名


该函数自动检测训练模型所采用的深度框架,然后调用 readNetFromCaffe、readNetFromTensorflow、readNetFromTorch 或 readNetFromDarknet 中的某个函数完成深度学习网络模型及模型参数的加载。


下面我们看下对应于特定框架的API:


1.Caffe


readNetFromCaffe(prototxt, caffeModel=None)


作用:加载采用Caffe的配置网络和训练的权重参数


1.Darknet


readNetFromDarknet(cfgFile, darknetModel=None)


作用:加载采用Darknet的配置网络和训练的权重参数


2.Tensorflow


readNetFromTensorflow(model, config=None)


作用:加载采用Tensorflow 的配置网络和训练的权重参数


参数:


1.model: .pb 文件

2.config: .pbtxt 文件


3.Torch


readNetFromTorch(model, isBinary=None)


作用:加载采用 Torch 的配置网络和训练的权重参数


参数:


1.model: 采用 torch.save()函数保存的文件


4.ONNX


readNetFromONNX(onnxFile)


作用:加载 .onnx 模型网络配置参数和权重参数


总结


1.DNN模块是OPenCV中的深度学习模块


优势:轻量型,方便,通用性


架构:语言绑定层,API层,实现层,加速层


加速方法:层融合、内存复用


2.常用API


1.dnn.blobfromImage


利用图片创建输入到模型中的blobs


2.dnn.NMSBoxes


根据boxes和scores进行非极大值抑制


3.dnn.readNet


加载网络模型和训练好的权重参数

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
4月前
|
算法 数据处理 C++
【C++ 20 新特性 算法和迭代器库的扩展和泛化 Ranges】深入浅出C++ Ranges库 (Exploring the C++ Ranges Library)
【C++ 20 新特性 算法和迭代器库的扩展和泛化 Ranges】深入浅出C++ Ranges库 (Exploring the C++ Ranges Library)
573 1
|
22小时前
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
24 6
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
4月前
|
缓存 算法 C语言
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
68 0
|
3月前
|
存储 算法 数据可视化
算法金 | D3blocks,一个超酷的 Python 库
D3Blocks是一个基于d3.js的Python图形库,用于创建吸引人的数据可视化图表,如D3graph、Elasticgraph和Sankey图。拥有超过470个Star,其特点包括简易性、功能丰富、易用性、可定制性和及时更新。通过pip安装后,用户能轻松创建粒子图和其他图表。文中展示了实战应用,如能源数据集的网络图,通过调整节点和边的属性实现个性化展示。关注作者,享受智能乐趣。
89 8
算法金 | D3blocks,一个超酷的 Python 库
|
3月前
|
机器学习/深度学习 编译器 算法框架/工具
OpenCV算法库
numba是一个用于编译Python数组和数值计算函数的编译器,这个编译器能够大幅提高直接使用Python编写的函数的运算速度。
|
4月前
|
数据采集 人工智能 自然语言处理
综述170篇自监督学习推荐算法,港大发布SSL4Rec:代码、资料库全面开源!
【5月更文挑战第20天】港大团队发布SSL4Rec,一个全面开源的自监督学习推荐算法框架,基于170篇相关文献的深入分析。SSL4Rec利用未标记数据提升推荐系统性能,解决了传统方法依赖大量标记数据的问题。开源代码与资料库促进研究复现与交流,为推荐系统领域带来新思路和工具。尽管面临数据需求大和依赖数据质量的挑战,但SSL4Rec展现出巨大的发展潜力和跨领域应用前景。[链接:https://arxiv.org/abs/2404.03354]
126 1
|
4月前
|
算法 定位技术 Windows
R语言最大流最小割定理和最短路径算法分析交通网络流量拥堵问题
R语言最大流最小割定理和最短路径算法分析交通网络流量拥堵问题
|
4月前
|
机器学习/深度学习 算法 数据挖掘
机器学习--K近邻算法,以及python中通过Scikit-learn库实现K近邻算法API使用技巧
机器学习--K近邻算法,以及python中通过Scikit-learn库实现K近邻算法API使用技巧
|
4月前
|
存储 算法 程序员
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
|
4月前
|
算法 搜索推荐 程序员
C++标准库算法指南:从线性到复杂度 — 选择最佳工具
C++标准库算法指南:从线性到复杂度 — 选择最佳工具
99 0