热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

OpenCV中DNN模块、DNN模块的常用API

日萌社人工智能AI:KerasPyTorchMXNetTensorFlowPaddlePaddle深度学习实战(不定时更新)2.4.cv
日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)



2.4. cv.dnn

学习目标

  • 了解OpenCV中DNN模块
  • 知道DNN模块的常用API

OPenCV自3.3版本开始,加入了对深度学习网络的支持,即DNN模块,它支持主流的深度学习框架生成与到处模型的加载。

1.DNN模块

1.1. 模块简介

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

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

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

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

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

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

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


1.2.模块架构

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

从上往下依次是:

  • 第一层:语言绑定层,主要支持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模块还有网络层面的优化。这种优化优化分两类,一类是层融合,还有一类是内存复用。

  • 层融合

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

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

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

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

  • 内存复用

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

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

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

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

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

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

  • 如上图所示,在这个例子中,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 pltimg_cv2 = cv2.imread("test.jpeg?s=#34;)
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()

输出结果为:

另外一个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: 自适应阈值公式中的相关系数:

  • 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: 所支持格式的框架名

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

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

  1. Caffe

readNetFromCaffe(prototxt, caffeModel=None)

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

  1. Darknet

    readNetFromDarknet(cfgFile, darknetModel=None)

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

  2. Tensorflow

    readNetFromTensorflow(model, config=None)

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

    参数:

    • model: .pb 文件
    • config: .pbtxt 文件
  3. Torch

    readNetFromTorch(model, isBinary=None)

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

    参数:

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

    readNetFromONNX(onnxFile)

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

总结

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

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

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

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

  2. 常用API

    • dnn.blobfromImage

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

    • dnn.NMSBoxes

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

    • dnn.readNet

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



"""
DNN模块有很多可直接调用的Python API接口,现将其介绍如下: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 - RGBcrop: 图像尺寸 resize 后是否裁剪. 如果crop=True,则,输入图片的尺寸调整resize后,一个边对应与 size 的一个维度,而另一个边的值大于等于 size 的另一个维度;然后从 resize 后的图片中心进行 crop. 如果crop=False,则无需 crop,只需保持图片的长宽比ddepth: 输出 blob 的 Depth. 可选: CV_32F 或 CV_8U另外一个API与上述API类似,是进行批量图片处理的,其原型如下所示:blobFromImages(images, scalefactor=None, size=None, mean=None, swapRB=None, crop=None, ddepth=None):作用:批量处理图片,创建4维的blob,其它参数类似于 dnn.blobFromImage。
"""
import cv2
from cv2 import dnn
import numpy as np
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams["font.sans-serif"] = ["SimHei"] #支持中文显示
mpl.rcParams["axes.unicode_minus"] = Falseimg_cv2 = cv2.imread("MM.png")
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)
#(1, 2, 0)中 1指高,2指宽,0指通道
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)
#(1, 2, 0)中 1指高,2指宽,0指通道
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()"""
dnn.NMSBoxes作用:根据给定的检测boxes和对应的scores进行NMS(非极大值抑制)处理原型:NMSBoxes(bboxes, scores, score_threshold, nms_threshold, eta=None, top_k=None)参数:boxes: 待处理的边界框 bounding boxesscores: 对于于待处理边界框的 scoresscore_threshold: 用于过滤 boxes 的 score 阈值nms_threshold: NMS 用到的阈值indices: NMS 处理后所保留的边界框的索引值eta: 自适应阈值公式中的相关系数:nms_threshold i+1 = eta * nms_threshold itop_k: 如果 top_k>0,则保留最多 top_k 个边界框索引值.
"""
"""
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:CaffereadNetFromCaffe(prototxt, caffeModel=None)作用:加载采用Caffe的配置网络和训练的权重参数DarknetreadNetFromDarknet(cfgFile, darknetModel=None)作用:加载采用Darknet的配置网络和训练的权重参数TensorflowreadNetFromTensorflow(model, config=None)作用:加载采用Tensorflow 的配置网络和训练的权重参数参数:model: .pb 文件config: .pbtxt 文件TorchreadNetFromTorch(model, isBinary=None)作用:加载采用 Torch 的配置网络和训练的权重参数参数:model: 采用 torch.save()函数保存的文件ONNXreadNetFromONNX(onnxFile)作用:加载 .onnx 模型网络配置参数和权重参数
"""


In [1]:

import cv2 as cv

from cv2 import dnn

import numpy as np

import matplotlib.pyplot as plt

In [2]:

img = cv.imread("test.jpeg?s=#34;)

print("原始图像大小:",img.shape)

原始图像大小: (960, 640, 3)

In [3]:

plt.figure()

plt.imshow(img[:,:,::-1])

Out[3]:

In [6]:

inweight = 256

inHeight = 256

outblob1 = dnn.blobFromImage(img,scalefactor=1.0/255,size=(inweight,inHeight),mean=(0,0,0),swapRB = False,crop=False)

outblob1.shape

Out[6]:

(1, 3, 256, 256)

In [7]:

outimg1 = np.transpose(outblob1[0],(1,2,0))

In [8]:

plt.figure()

plt.imshow(outimg1[:,:,::-1])

Out[8]:

In [9]:

outblob2 = dnn.blobFromImage(img,scalefactor = 1.0/255,size=(inweight,inHeight),mean=(0,0,0),swapRB=False,crop=True)

In [10]:

outblob2.shape

Out[10]:

(1, 3, 256, 256)

In [11]:

outimg2 = np.transpose(outblob2[0],(1,2,0))

In [12]:

plt.figure()

plt.imshow(outimg2[:,:,::-1])

Out[12]:



推荐阅读
  • 世界人工智能大赛OCR赛题方案!
     Datawhale干货 作者:阿水,北京航空航天大学,Datawhale成员本文以世界人工智能创新大赛(AIWIN)手写体OCR识别竞赛为实践背景,给出了OCR实践的常见思路和流 ... [详细]
  • 本文提供了PyTorch框架中常用的预训练模型的下载链接及详细使用指南,涵盖ResNet、Inception、DenseNet、AlexNet、VGGNet等六大分类模型。每种模型的预训练参数均经过精心调优,适用于多种计算机视觉任务。文章不仅介绍了模型的下载方式,还详细说明了如何在实际项目中高效地加载和使用这些模型,为开发者提供全面的技术支持。 ... [详细]
  • 视觉图像的生成机制与英文术语解析
    近期,Google Brain、牛津大学和清华大学等多家研究机构相继发布了关于多层感知机(MLP)在视觉图像分类中的应用成果。这些研究深入探讨了MLP在视觉任务中的工作机制,并解析了相关技术术语,为理解视觉图像生成提供了新的视角和方法。 ... [详细]
  • Kali Linux 渗透测试实战指南:第24章 客户端安全威胁分析与防御策略
    客户端安全威胁分析与防御策略主要探讨了终端设备(如计算机、平板电脑和移动设备)在使用互联网时可能面临的各种安全威胁。本章详细介绍了这些设备如何作为信息和服务的提供者或接收者,以及它们在与服务器等其他系统交互过程中可能遇到的安全风险,并提出了有效的防御措施。 ... [详细]
  • 华为200万年薪招聘AI应届生——有多少本事,给多少钱
    据新浪科技报道,阿里AIlabs年薪百万美元引进两位科学家。除AI顶尖科学家外,华为也是为多位AI应届博士开出了200万的高价年薪。19年9月,各大互联招聘企业陆续发布2019年人 ... [详细]
  • 百度AI的2020
    百度AI的2020-世界的2020,是充满不确定性的变局之年;中国的2020,是团结一心、共克时艰、于变局中开新局的希望之年;百度AI的2020,是坚定信念,拥抱变化,践行“科技为 ... [详细]
  • 深入解析经典卷积神经网络及其实现代码
    深入解析经典卷积神经网络及其实现代码 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • 图像分割技术在人工智能领域中扮演着关键角色,其中语义分割、实例分割和全景分割是三种主要的方法。本文对这三种分割技术进行了详细的对比分析,探讨了它们在不同应用场景中的优缺点和适用范围,为研究人员和从业者提供了有价值的参考。 ... [详细]
  • NVIDIA最新推出的Ampere架构标志着显卡技术的一次重大突破,不仅在性能上实现了显著提升,还在能效比方面进行了深度优化。该架构融合了创新设计与技术改进,为用户带来更加流畅的图形处理体验,同时降低了功耗,提升了计算效率。 ... [详细]
  • 在Windows命令行中,通过Conda工具可以高效地管理和操作虚拟环境。具体步骤包括:1. 列出现有虚拟环境:`conda env list`;2. 创建新虚拟环境:`conda create --name 环境名`;3. 删除虚拟环境:`conda env remove --name 环境名`。这些命令不仅简化了环境管理流程,还提高了开发效率。此外,Conda还支持环境文件导出和导入,方便在不同机器间迁移配置。 ... [详细]
  • 如何提升Python处理约1GB数据集时的运行效率?
    如何提升Python处理约1GB数据集时的运行效率?本文探讨了在后端开发中使用Python处理大规模数据集的优化方法。通过分析常见的性能瓶颈,介绍了多种提高数据处理速度的技术,包括使用高效的数据结构、并行计算、内存管理和代码优化策略。此外,文章还提供了在Ubuntu环境下配置和测试这些优化方案的具体步骤,适用于从事推荐系统等领域的开发者。 ... [详细]
  • NVIDIA CUDA Toolkit 不同版本的安装方法详解
    在安装NVIDIA CUDA Toolkit以配置GPU加速环境时,通常可以通过查阅网络文章或访问官方文档来获取安装指南。然而,这些资料往往侧重于介绍最新版本的安装方法,而忽视了不同版本之间的差异。本文将详细解析各个版本的安装步骤,帮助用户根据自身需求选择合适的CUDA Toolkit版本进行安装,确保兼容性和性能最优化。 ... [详细]
  • 亚马逊老板杰夫·贝佐斯
    本文主要介绍关于的知识点,对【亚马逊创始人或成地球首位万亿富豪,起底贝佐斯创业之路】和【亚马逊老板杰夫·贝佐斯】有兴趣的朋友可以看下由【CSDN资讯】投稿的技术文章,希望该技术和经验能帮到你解决你所遇 ... [详细]
  • 本文详细介绍了在Windows操作系统上使用Python 3.8.5编译支持CUDA 11和cuDNN 8.0.2的TensorFlow 2.3的步骤。文章不仅提供了详细的编译指南,还分享了编译后的文件下载链接,方便用户快速获取所需资源。此外,文中还涵盖了常见的编译问题及其解决方案,确保用户能够顺利进行编译和安装。 ... [详细]
author-avatar
Adam_phper
与时俱进
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有