OpenCV:DNN 模块实现图像风格迁移
目录
一、 DNN 模块理论基础
1.1 DNN 模块是什么
1.2 DNN 模块的特点
1.3 DNN 模块使用的主要函数及流程
二、实操步骤:代码实现
2.1 导入库与读取图像
2.2 图像预处理(关键步骤)
2.3 加载模型与前向传播
2.4 输出结果处理
2.5 显示与保存结果
三、常见问题解决
四、总结与拓展
4.1 总结
4.2 拓展
本文基于 OpenCV 的 DNN 模块,结合理论知识与实际代码,带大家一步步完成图像风格迁移。
一、 DNN 模块理论基础
1.1 DNN 模块是什么
DNN 模块是 OpenCV 中专门用来实现深度神经网络(DNN, Deep Neural Networks)相关功能的模块,其作用是载入 TensorFlow、Caffe、Torch 等其他深度学习框架中已经训练好的模型,然后用该模型完成预测等工作。
1.2 DNN 模块的特点
- 轻量:OpenCV 的深度学习模块只实现了模型推理功能,不涉及模型训练,这使得相关程序非常精简,加速了安装和编译过程。
- 外部依赖性低:重新实现一遍深度学习框架使得 DNN 模块对外部依赖性极低,极大地方便了深度学习应用的部署。
- 方便:在原有 OpenCV 开发程序的基础上,通过 DNN 模块可以非常方便地加入对神经网络推理的支持。
- 集成:若网络模型来自多个框架,如一个来自 TensorFlow,另外一个来自 Caffe,则 DNN 模块可以方便地对网络进行整合。
- 通用性:DNN 模块提供了统一的接口来操作网络模型,内部做的优化和加速适用于所有网络模型格式,支持多种设备和操作系统。
1.3 DNN 模块使用的主要函数及流程
DNN 模块使用主要遵循以下流程:
图像预处理:通过cv2.dnn.blobFromImage
函数,将需要处理的图像转换成可以传入人工神经网络的数据形式,构建符合人工神经网络输入格式的四维块。该函数可通过调整图像尺寸和裁图像、减均值、按比例因子缩放、交换 B 通道和 R 通道等可选操作完成对图像的预处理,得到符合人工神经网络输入的目标值。
模型导入:使用cv.dnn.readNet
函数导入预训练好的模型。
设置网络输入:调用net.setInput
方法,将预处理后的图像数据设置为网络的输入。
网络计算:通过net.forward
方法进行网络计算,得到最终的结果。
二、实操步骤:代码实现
2.1 导入库与读取图像
首先导入 OpenCV 库,读取待处理的内容图像(如Mona Lisa.png
),并显示原始图像以便对比。
import cv2# 读取输入图像(需确保图像路径正确,可使用相对路径或绝对路径)
image = cv2.imread('Mona Lisa.png')
# 显示原始图像,等待用户按键后关闭窗口
cv2.imshow('原始图像', image)
cv2.waitKey(0)
2.2 图像预处理(关键步骤)
根据 DNN 模块对输入的要求,模型输入需为 “四维块(B×C×H×W)”,通过cv2.dnn.blobFromImage()
函数完成转换。
# 获取图像原始宽高(后续保持输出尺寸与输入一致)
(h, w) = image.shape[:2]# 图像预处理:转换为模型可接受的四维格式
# 参数说明:
# image:输入图像;1:像素缩放因子(不缩放);(w, h):输出图像尺寸;
# (0, 0, 0):通道均值(不减去均值);False:不交换B/R通道;False:不裁剪
blob = cv2.dnn.blobFromImage(image, 1, (w, h), (0, 0, 0), False, False)
2.3 加载模型与前向传播
导入预训练模型,再将预处理后的blob
传入模型,执行前向传播得到结果。
# 加载Torch预训练风格模型(以星空风格为例,需确保模型路径正确)
net = cv2.dnn.readNet(r"model\starry_night.t7")# 设置模型输入
net.setInput(blob)# 前向传播:获取模型输出的风格迁移结果
out = net.forward()
2.4 输出结果处理
模型输出out
为四维数据(B×C×H×W),需转换为三维图像格式(H×W×C)才能正常显示。
# 1. 重塑维度:忽略batch维度(B=1),从4维转为3维(C×H×W)
out_new = out.reshape(out.shape[1], out.shape[2], out.shape[3])# 2. 归一化:将像素值映射到0-1范围,避免显示异常
cv2.normalize(out_new, out_new, norm_type=cv2.NORM_MINMAX)# 3. 调整通道顺序:从(C×H×W)转为(H×W×C),符合OpenCV显示格式
result = out_new.transpose(1, 2, 0)
2.5 显示与保存结果
查看风格迁移效果,若需留存结果可保存图像。
# 显示风格迁移后的图像
cv2.imshow('风格迁移结果', result)
cv2.waitKey(0)# (可选)保存结果图像(乘以255是将0-1范围转回0-255像素范围)
cv2.imwrite('风格迁移结果.png', result * 255)# 关闭所有窗口,释放资源
cv2.destroyAllWindows()
三、常见问题解决
问题现象 | 可能原因 | 解决方法 |
---|---|---|
图像读取失败(无原始图像窗口) | 图像路径错误;图像文件损坏 | 1. 使用绝对路径(如C:\Users\XXX\Mona Lisa.png );2. 确认图像格式为 PNG/JPG 且文件完好 |
模型加载报错(提示 “无法读取模型”) | 模型路径错误;模型文件不完整 | 1. 核对模型路径(如model\starry_night.t7 是否存在);2. 从可靠来源(如 GitHub)重新下载模型 |
输出图像全黑 / 全白 | 归一化参数错误;通道顺序调整错误 | 1. 确认cv2.normalize 的norm_type 为cv2.NORM_MINMAX ;2. 检查transpose 顺序是否为(1,2,0) |
四、总结与拓展
4.1 总结
本次实操严格遵循 DNN 模块 “预处理→模型导入→推理→结果处理” 的流程,核心是理解 “模型输入格式要求” 与 “图像维度转换逻辑”,这是保证风格迁移成功的关键。
4.2 拓展
更换风格:替换cv2.dnn.readNet()
中的模型路径,可尝试向日葵、睡莲等其他风格的.t7
模型;
优化图像:预处理前可加入 “图像平滑处理” 的高斯滤波(cv2.GaussianBlur()
),减少原始图像噪声对结果的影响。