OpenCV中的DNN模块
OpenCV中的DNN(Deep Neural Network)模块是一个功能强大的工具,它允许开发者在计算机视觉应用中使用深度学习模型。以下是对OpenCV DNN模块的详细介绍:
一、功能概述
DNN模块的主要功能是载入其他深度学习框架(如TensorFlow、Caffe、Torch等)中已经训练好的模型,并使用这些模型完成预测等工作。它支持多种深度学习框架和模型格式,并提供了高效的推理能力。此外,DNN模块还与OpenCV的其他模块无缝集成,便于在计算机视觉项目中使用。
二、支持的模型格式
OpenCV的DNN模块支持多种深度学习模型格式,包括但不限于:
- Caffe:.caffemodel(模型权重文件)和.prototxt(模型配置文件)。
- TensorFlow:.pb(冻结的图文件)、.pbtxt(文本图文件)。
- Torch:.t7(Torch7模型)。
- ONNX:.onnx(ONNX模型)。
- Darknet:.cfg(配置文件)和.weights(权重文件)。
- PyTorch:通过ONNX格式导出。
三、基本使用方法
使用OpenCV的DNN模块进行推理的基本步骤如下:
-
加载预训练的模型和相应的配置文件:
- 使用
cv2.dnn.readNetFromCaffe()
加载Caffe模型。 - 使用
cv2.dnn.readNetFromTensorflow()
加载TensorFlow模型。 - 使用
cv2.dnn.readNetFromTorch()
加载Torch模型。 - 使用
cv2.dnn.readNetFromONNX()
加载ONNX模型等。
- 使用
-
对输入图像进行预处理:
- 使用
cv2.dnn.blobFromImage()
函数将图像转换为DNN模型所需的输入blob,并进行必要的缩放和归一化。 - 函数cv2.dnn.blobFromImage:实现图像预处理,从原始图像构建一个符合人工神经网络输入格式的四维块。
blob = cv2.dnn.blobFromImage(image, scalefactor=None, size=None, mean=None, swapRB=None, crop=None)
- 参数:
- image:表示输入图像。
- scalefactor:表示对图像内的数据进行缩放的比例因子。具体运算是每个像素值*scalefactor,该值默认为 1。
- size:用于控制blob的宽度、高度。
- mean:表示从每个通道减去的均值。 (0,0,0):表示不进行均值减法。即不对图像的B、G、R通道进行任何减法操作。若输入图像本身是B、G、R通道顺序的,并且下一个参数swapRB值为True,则mean值对应的通道顺序为R、G、B。
- swapRB:表示在必要时交换通道的R通道和B通道。一般情况下使用的是RGB通道。而openCV通常采用的是BGR通道,因此可以根据需要交换第1个和第3个通道。该值默认为False。
- crop:布尔值,如果为True,则在调整大小后进行居中裁剪。
- 返回值:
- blob: 表示在经过缩放、裁剪、减均值后得到的符合人工神经网络输入的数据。该数据是一个四维数据,布局通常使用N(表示batch size)、C(图像通道数,如RGB图像具有三个通道)、H(图像高度)、W(图像宽度)表示
- 使用
-
进行推理:
- 使用
net.setInput(blob)
设置输入。 - 使用
output = net.forward()
进行推理,forward
函数返回模型的输出。
- 使用
-
解析和处理输出结果:
- 输出的处理方式取决于具体的应用。例如,对于图像分类任务,输出通常是一个概率分布,表示每个类别的概率;对于目标检测任务,输出通常包括检测到的对象的边界框和类别。
四、DNN 模块的特点
- 轻量: OpenCV 的深度学习模块只实现了模型推理功能,不涉及模型训练,这使得相关程序非常精简,加速了安装和编译过程。
- 外部依赖性低:重新实现一遍深度学习框架使得 DNN 模块对外部依赖性极低,极大地方便了深度学习应用的部署。
- 方便:在原有 OpenCV 开发程序的基础上,通过 DNN 模块可以非常方便地加入对神经网络推理的支持。
- 集成:若网络模型来自多个框架,如一个来自 TensorFlow,另外一个来自 Caffe,则 DNN 模块可以方便地对网络进行整合。
- 通用性:DNN 模块提供了统一的接口来操作网络模型,内部做的优化和加速适用于所有网络模型格式,支持多种设备和操作系统。
五、常见应用示例
- 图像分类:使用DNN模块进行图像分类的典型步骤包括加载预训练的分类模型、预处理输入图像、进行推理以及解析和显示分类结果。
- 目标检测:目标检测任务通常包括加载预训练的检测模型、预处理输入图像、进行推理以及解析检测结果并绘制检测到的对象边界框。
- 图像分割:图像分割任务的步骤与分类和检测类似,但输出通常是一个掩码图像,表示每个像素的类别。
- 风格迁移:基于深度学习技术的图像处理方法,它允许将一张图片(风格图)中的风格、纹理迁移到另一张图片(内容图)上,同时保留内容图原有的主体结构。
示例:图片风格迁移
-
图片的风格迁移就是运用OpenCV中的DNN模块中的方法,引用别人已经训练好的不同风格模型,将自己的图片以另一种风格展现出来
-
例如将下图中左边的图片以右边的风格展示出来
-
以下链接中提供了几个由Torch训练出来的模型
-
代码实现:
import cv2 image_yuantu = cv2.imread("wechat.jpg") # 读取图片 # 将图片的大小缩小,可选,根据自己的图片大小决定 image = cv2.resize(image_yuantu, dsize=None, fx=0.5, fy=0.5) cv2.imshow('yuan tu', image) # 显示图片 cv2.waitKey(0) """ -----------图片预处理------------------ """ (h, w) = image.shape[:2] # 获取图像尺寸 blob = cv2.dnn.blobFromImage(image, 1, (w, h), (0, 0, 0), swapRB=True, crop=False) """ ---------------------加载模型------------------------- """ net = cv2.dnn.readNet(r'model\starry_night.t7') # 统一的调用方法 # net = cv2.dnn.readNetFromTorch(r'.\model\la_muse.t7') # net = cv2.dnn.readNetFromTorch(r'.\model\candy.t7') # net = cv2.dnn.readNetFromTorch(r'.\model\composition_vii.t7') # net = cv2.dnn.readNetFromTorch(r'.\model\feathers.t7') # net = cv2.dnn.readNetFromTorch(r'.\model\udnie.t7') # net = cv2.dnn.readNetFromTorch(r'.\model\the_scream.t7') # 设置神经网络的输入 net.setInput(blob) # 对输入图像进行前向传播,得到输出结果 out = net.forward() # 将输出结果转换为合适的格式 # out是四维的:B*C*H*W # B:batch图像数量(通常为1),C:channels通道数,H:height高度、W:width宽度 # ======输出处理====== # 重塑形状(忽略第1维),4维变3维 # 调整输出out的形状,模型推理输出out是四维BCHW形式的,调整为三维CHW形式 out_new = out.reshape(out.shape[1], out.shape[2], out.shape[3]) # 对输入的数组(或图像)进行归一化处理,使其数值范围在指定的范围内 cv2.normalize(out_new, out_new, norm_type=cv2.NORM_MINMAX) # 转置输出结果的维度 result = out_new.transpose(1, 2, 0) # 显示转换后的图像 cv2.imshow('Stylized Image', result) cv2.waitKey(0) cv2.destroyAllWindows()
- 原图如下:
- 效果图如下:
- 原图如下: