计算机视觉(opencv)实战二十九——图像风格迁移


OpenCV DNN 模块实现图像风格迁移:原理与代码详解

在计算机视觉中,图像风格迁移(Neural Style Transfer)是一项非常有趣的应用。它可以将一幅图像的风格迁移到另一幅图像上,比如把一张人脸图像转换成梵高的《星空》风格。本篇文章将通过 OpenCV 的 dnn 模块,结合预训练的 PyTorch 模型,实现一个简易的风格迁移程序。


1. 环境准备与图像读取

原图和结果:

首先,我们需要安装 OpenCV,并加载一张输入图像作为测试对象。

复制代码
import cv2

# 获取输入图像
image = cv2.imread('face1.jpg')  # 读取本地图像
# 如果需要使用摄像头实时输入,可以改为:cap = cv2.VideoCapture(0)

# 显示原始图像
cv2.imshow('yuan tu', image)
cv2.waitKey(0)

要点:

  • cv2.imread() 用于读取本地图像,返回一个 NumPy 数组。

  • cv2.imshow() 可以显示图像,cv2.waitKey(0) 表示无限等待用户按键,否则窗口立即关闭。


2. 图像预处理:blobFromImage

在将图像输入到神经网络之前,我们需要将其转化为网络所需的输入格式。OpenCV 提供了 cv2.dnn.blobFromImage 函数,帮助我们完成这一过程。

复制代码
(h, w) = image.shape[:2]
blob = cv2.dnn.blobFromImage(image, 1, (w, h), (0, 0, 0), swapRB=False, crop=False)

参数详解

  • image:输入图像,必须是 NumPy 数组。

  • scalefactor:缩放因子,对像素值进行乘法缩放,默认 1 表示不缩放。

  • size:调整图像尺寸,必须与模型训练时的输入大小一致。

  • mean :通道均值,用于减去图像的平均值以进行归一化。设置为 (0,0,0) 表示不做均值减法。

  • swapRB:是否交换 R 和 B 通道。因为 OpenCV 默认是 BGR 通道,而许多深度学习模型训练时采用的是 RGB。

  • crop:是否在缩放后裁剪图像,通常设为 False。

最终返回的 blob 是一个 四维张量 ,格式为 NCHW

  • N:批量大小(batch size)

  • C:通道数(通常 3)

  • H:高度

  • W:宽度

参数名 类型 说明 默认值
image numpy.ndarray 输入图像,支持单张图像或多张图像列表。 必填
scalefactor float 缩放因子,将图像像素值缩放到神经网络所需范围,最终结果是 像素值 * scalefactor 1.0
size (width, height) 输出图像的大小(宽,高)。必须与模型训练时的输入尺寸匹配,否则可能导致推理失败或效果不佳。 不缩放
mean (meanR, meanG, meanB) 从每个通道减去的均值,用于归一化。可帮助消除光照影响。 (0, 0, 0)
swapRB bool 是否交换 R 和 B 通道。OpenCV 默认图像通道为 BGR,如果模型训练时使用 RGB,则需设为 True False
crop bool 是否在调整大小后居中裁剪图像。如果设为 False,直接按比例缩放到目标尺寸。 False
ddepth int 输出数据的深度,常用 cv2.CV_32F(32 位浮点)。 CV_32F

3. 加载预训练神经网络

接下来,我们需要加载一个预训练的神经网络模型。OpenCV 提供了 cv2.dnn.readNet,支持多种主流深度学习框架。

复制代码
# 加载模型
net = cv2.dnn.readNet(r"model\starry_night.t7")

参数说明

  • model:模型文件,包含神经网络的权重和计算图。

  • config:可选配置文件,定义网络架构。

  • framework:可选参数,指定模型的框架(如 caffe、tensorflow、onnx 等),不指定时 OpenCV 会自动推断。

模型类型 model 文件 config 文件 读取函数
Caffe *.caffemodel *.prototxt readNetFromCaffe
TensorFlow *.pb *.pbtxt readNetFromTensorFlow
Torch *.t7 / *.net readNetFromTorch
Darknet *.weights *.cfg readNetFromDarknet
OpenVINO *.bin *.xml readNetFromModelOptimizer
ONNX *.onnx readNetFromONNX

这里使用的是一个基于 Torch 训练的风格迁移模型 starry_night.t7,它能将输入图像转换为梵高星空的风格。


4. 前向传播与结果计算

有了模型和输入数据,我们就可以进行前向推理:

复制代码
# 设置输入
net.setInput(blob)
# 前向传播
out = net.forward()

此时 out 是一个四维张量,形状为 (B, C, H, W)

为了便于显示,我们需要对其进行 reshape、归一化和转置:

复制代码
# 调整形状,去掉 batch 维度
out_new = out.reshape(out.shape[1], out.shape[2], out.shape[3])

# 归一化到 0~1 或 0~255 范围
cv2.normalize(out_new, out_new, norm_type=cv2.NORM_MINMAX)

# 转置回 HWC 格式(OpenCV 图像格式)
result = out_new.transpose(1, 2, 0)

5. 显示风格迁移后的图像

最后,将处理好的图像显示出来:

复制代码
cv2.imshow('Stylized Image', result)
cv2.waitKey(0)

运行后,你将看到一幅带有梵高星空风格的图像。


6. 注意事项与优化建议

  1. 图像尺寸 :预处理时的 (w, h) 应与模型输入尺寸一致,否则可能失真。

  2. 归一化处理 :有些模型要求像素值范围在 [-1,1],需要调整 scalefactormean

  3. 性能优化 :若处理视频流,可以把 cv2.imshow() 放在循环中,实时显示风格化结果。

  4. GPU 加速 :可以用 net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) 开启 GPU 推理,速度会提升显著。


总结

本文通过 OpenCV 的 dnn 模块实现了一个简易的风格迁移程序,完整流程包括:

  1. 读取输入图像

  2. 使用 blobFromImage 进行预处理

  3. 加载预训练模型

  4. 前向推理得到风格化结果

  5. 归一化与维度变换

  6. 显示结果图像

这种方法可以快速实现艺术风格迁移,同时可以推广到目标检测、人脸识别等其他深度学习任务。

相关推荐
蒋星熠5 小时前
支持向量机深度解析:从数学原理到工程实践的完整指南
人工智能·python·深度学习·神经网络·算法·机器学习·支持向量机
Vahala0623-孔勇5 小时前
将深度学习与Spring Boot集成:使用DL4J构建企业级AI应用的完整指南
人工智能·spring boot·深度学习
jerryinwuhan5 小时前
公共安全事件分析-3
人工智能·语言模型·自然语言处理·nlp·知识图谱
love530love5 小时前
2025 PyCharm IDE 社区版与专业版合并后,新手该如何安装?(附 Toolbox 图形化安装教程)
ide·人工智能·windows·python·架构·pycharm·github
蜉蝣之翼❉6 小时前
编译OpenCV 无法解析的外部符号 cv::xfeatures2d::VGG::getDef
opencv
Monkey的自我迭代6 小时前
图像拼接(反向拼接巨难,求指教!)
图像处理·人工智能·python·opencv·算法·计算机视觉
minhuan6 小时前
构建AI智能体:四十二、使用 Qwen-Agent Assistant 调用高德 API 实现天气查询
人工智能·agent·function call·天气查询助手·qwen agent
OliverYeung6 小时前
【AskAI系列课程】:P3.Agno从阿里云百炼知识库中检索知识库片段并回答用户问题
人工智能·ai·llm·rag·agentic·deepseek·agno
陈橘又青6 小时前
通过无代码工作流在 Dify 中进行人工智能驱动的网络抓取
大数据·人工智能·ai