DNN模块是什么?
OpenCV 的 DNN 模块是在 OpenCV 3.3 版本引入的,它旨在为开发者提供一个统一的接口,以便在 OpenCV 框架内加载、部署和运行各种预训练的深度神经网络模型。该模块支持多种深度学习框架训练的模型,无需额外安装复杂的深度学习库,就能在不同平台上实现高效的推理。
DNN模块的特点
支持的模型格式
- Caffe:由伯克利视觉和学习中心(BVLC)开发的深度学习框架,OpenCV 可以加载 Caffe 训练的模型(.prototxt 用于定义网络结构,.caffemodel 存储训练好的权重)。
- TensorFlow:谷歌开发的开源深度学习框架,OpenCV 支持加载 TensorFlow 的冻结图模型(.pb 文件)。
- PyTorch:Facebook 开发的深度学习框架,OpenCV 可以加载经过 ONNX(开放神经网络交换格式)转换后的 PyTorch 模型(.onnx 文件)。
- Darknet:YOLO(You Only Look Once)目标检测算法所使用的深度学习框架,OpenCV 能加载 Darknet 训练的模型(.cfg 定义网络结构,.weights 存储权重)。
主要功能
- 图像分类:可以使用预训练的分类模型(如 ResNet、VGG 等)对输入图像进行分类,判断图像所属的类别。
- 目标检测:支持多种目标检测模型(如 YOLO、SSD 等),能够在图像或视频中检测出特定目标的位置和类别。
- 语义分割:利用语义分割模型(如 U-Net、DeepLab 等)将图像中的每个像素划分到不同的类别,实现对图像的精细化分析。
- 特征提取:从输入数据中提取高级特征,这些特征可用于后续的机器学习任务,如目标识别、图像检索等。
实例风格迁移
通过torch训练好的模型进行对图片的处理。
模型如下:通过网盘分享的文件:model.zip
链接: https://pan.baidu.com/s/1EjVsi3WIGcOm8Gk28xiMWA 提取码: x2m3
文件模型可以自由挑选
本文使用图片:
代码:
import cv2
# 读取指定路径下的图片文件 'nezha.jpg',将其存储为一个多维数组(表示图像)
# 该数组包含了图像的像素信息,后续可以对这些像素进行各种操作
image = cv2.imread('nezha.jpg')
# 使用 cv2.imshow 函数显示原始图像
# 第一个参数 'yuan tu' 是显示窗口的标题,第二个参数 image 是要显示的图像
cv2.imshow('yuan tu', image)
# cv2.waitKey(0) 用于等待用户按下任意按键
# 参数 0 表示无限等待,直到用户按下按键才会继续执行后续代码
cv2.waitKey(0)
'''图片预处理'''
# 获取图像的高度和宽度
# image.shape 返回一个元组,包含图像的高度、宽度和通道数
# [:2] 表示取元组的前两个元素,即高度和宽度
(h, w) = image.shape[:2]
# 使用 cv2.dnn.blobFromImage 函数对图像进行预处理,将其转换为适合神经网络输入的格式
# 第一个参数 image 是要处理的图像
# 第二个参数 1 是缩放因子,这里不进行缩放
# 第三个参数 (w, h) 是输出图像的尺寸,这里保持原图像的尺寸
# 第四个参数 (0, 0, 0) 是每个通道的均值,这里将每个通道的均值设为 0
# swapRB=False 表示不交换颜色通道(在 OpenCV 中,图像默认是 BGR 格式)
# crop=False 表示不进行裁剪操作
blob = cv2.dnn.blobFromImage(image, 1, (w, h), (0, 0, 0), swapRB=False, crop=False)
'''加载模型'''
# 使用 cv2.dnn.readNet 函数加载预训练的神经网络模型
# r'model\starry_night.t7' 是模型文件的路径,r 表示原始字符串,避免反斜杠被转义
net = cv2.dnn.readNet(r'model\starry_night.t7')
# 将预处理后的图像数据 blob 输入到神经网络中
net.setInput(blob)
# 调用 net.forward() 函数进行前向传播计算
# 即让图像数据通过神经网络,得到输出结果
out = net.forward()
# 调整输出结果的形状
# out.shape 返回输出结果的维度信息,通过 reshape 函数将其重新调整为 (out.shape[1], out.shape[2], out.shape[3]) 的形状
out_new = out.reshape(out.shape[1], out.shape[2], out.shape[3])
# 对调整形状后的输出结果进行归一化处理
# cv2.normalize 函数用于将数组中的元素值归一化到指定的范围
# 第一个参数 out_new 是要进行归一化处理的数组
# 第二个参数 out_new 是输出数组,这里表示将归一化后的结果存储在原数组中
# norm_type=cv2.NORM_MINMAX 表示使用最小 - 最大归一化方法,将数组中的元素值缩放到 [0, 1] 范围内
cv2.normalize(out_new, out_new, norm_type=cv2.NORM_MINMAX)
# 对归一化后的结果进行维度转换
# transpose(1, 2, 0) 表示将数组的维度按照指定的顺序进行重新排列
# 这样可以将数据转换为适合 OpenCV 显示的格式
result = out_new.transpose(1, 2, 0)
# 使用 cv2.imshow 函数显示经过风格转换后的图像
# 'Stylized Image' 是显示窗口的标题,result 是要显示的图像
cv2.imshow('Stylized Image', result)
# 再次等待用户按下任意按键
cv2.waitKey(0)
# 关闭所有由 OpenCV 创建的窗口,释放相关资源
cv2.destroyAllWindows()
结果:
也可以对视频进行风格迁移,一下是摄像头拍摄的风格迁移
import cv2
cap = cv2.VideoCapture(0)
net = cv2.dnn.readNetFromTorch(r'D:\where-python\python-venv\shi_jue_demo\DNN\model\starry_night.t7')
if not cap.isOpened():
print('摄像头启动失败')
exit()
while True:
ret,frame = cap.read()
if not ret:
print('不能读取摄像头')
break
(h,w) = frame.shape[:2]
blob = cv2.dnn.blobFromImage(frame,1,(w,h),(0,0,0),swapRB=True,crop=False)
net.setInput(blob)
out = net.forward()
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('result',result)
key_pressed = cv2.waitKey(10)
if key_pressed ==27:
break
cap.release()
cv2.destroyAllWindows()