图像风格迁移是计算机视觉领域极具趣味性的技术之一 —— 它能将普通照片(内容图像)与艺术画作(风格图像)的特征融合,生成兼具 “内容轮廓” 与 “艺术风格” 的新图像。OpenCV 的 DNN(深度神经网络)模块为风格迁移提供了轻量、便捷的实现方案,无需搭建复杂的深度学习框架,仅通过加载预训练模型即可快速完成风格迁移。本文将从基础概念入手,详解 DNN 模块特性,最终通过完整案例实现 “照片转梵高星空风”“照片转糖果风” 等效果。

一、核心概念:风格迁移与 OpenCV DNN 模块

在动手写代码前,我们需要先理清两个关键概念:风格迁移的原理OpenCV DNN 模块的定位,这是理解后续实战的基础。

1. 什么是图像风格迁移?

图像风格迁移的核心目标是 “内容与风格的分离与重组”:

  • 内容图像:提供图像的 “结构信息”,比如照片中的建筑、人物、风景轮廓(例:黄鹤楼照片)。
  • 风格图像:提供图像的 “艺术风格信息”,比如梵高《星空》的漩涡笔触、莫奈《睡莲》的色彩晕染(例:梵高《星空》)。
  • 生成图像:保留内容图像的结构,同时赋予风格图像的艺术特征(例:“梵高星空风” 的黄鹤楼)。

在 OpenCV 中,风格迁移的实现依赖预训练的神经网络模型—— 这些模型已通过大量 “内容 - 风格” 图像对训练完成,能自动学习 “如何提取内容特征”“如何迁移风格特征”,我们只需加载模型并传入内容图像即可生成结果。

2. OpenCV DNN 模块:轻量的深度学习推理工具

DNN(Deep Neural Networks)是 OpenCV 中专门用于深度学习模型推理的模块,它不负责模型训练,仅专注于 “加载已训练模型并完成预测”,这使其具备以下核心优势:

DNN 模块实现风格迁移的核心流程可概括为:
加载预训练风格模型 → 内容图像预处理 → 模型推理(风格迁移) → 输出结果后处理 → 显示/保存生成图像

二、关键技术:图像预处理与模型加载


风格迁移的效果好坏,除了依赖预训练模型,还与 “图像预处理” 和 “模型加载方式” 密切相关。下面详解这两个关键步骤的技术细节。


1. 图像预处理:让图像符合模型输入要求


深度学习模型对输入图像的格式有严格要求(如尺寸、通道顺序、数据范围),而 OpenCV 读取的原始图像(BGR 格式、像素值 0-255)通常无法直接传入模型,需要通过 **cv2.dnn.blobFromImage()** 函数进行预处理,将其转换为模型可识别的 “四维 Blob 数据”(格式:N×C×H×W,其中 N = 批量大小、C = 通道数、H = 高度、W = 宽度)。
cv2.dnn.blobFromImage()参数详解
该函数是 DNN 模块的 “预处理核心”,支持缩放、裁剪、通道转换、均值减法等操作,参数如下:

辅助工具:自动缩放图像函数
若原始图像尺寸过大(如 4K 照片),会导致模型推理速度慢且占用内存高。可自定义一个 “自动缩放函数”,按指定宽度 / 高度缩放图像,同时保持纵横比不变:

import cv2def auto_resize(image, width=None, height=None, inter=cv2.INTER_AREA):"""自动缩放图像(保持纵横比):param image: 输入原始图像:param width: 目标宽度(若为None,则按height缩放):param height: 目标高度(若为None,则按width缩放):param inter: 插值方式(cv2.INTER_AREA适合缩小,cv2.INTER_CUBIC适合放大):return: 缩放后的图像"""# 获取原始图像尺寸(h, w) = image.shape[:2]# 若未指定宽度和高度,返回原图if width is None and height is None:return image# 若仅指定高度,按高度比例计算宽度if width is None:ratio = height / float(h)dim = (int(w * ratio), height)# 若仅指定宽度,按宽度比例计算高度else:ratio = width / float(w)dim = (width, int(h * ratio))# 执行缩放并返回结果resized = cv2.resize(image, dim, interpolation=inter)return resized

2. 模型加载:两种常用函数对比

OpenCV DNN 模块提供两种加载风格模型的函数,需根据模型格式选择:cv2.dnn.readNet()(通用)和 **cv2.dnn.readNetFromTorch()**(专门用于 Torch 格式模型)。

(1)cv2.dnn.readNetFromTorch():Torch 模型专用

风格迁移的预训练模型多为 Torch7 格式(文件后缀.t7),该格式模型将 “架构” 和 “权重” 存储在同一个文件中,加载时只需传入文件路径:

# 加载梵高星空风格模型(.t7格式)
net = cv2.dnn.readNetFromTorch("models/starry_night.t7")
(2)cv2.dnn.readNet():多格式通用

若模型为 Caffe(需.prototxt架构文件 + .caffemodel权重文件)、TensorFlow(.pb文件)等格式,需用该函数,根据格式传入不同参数:

# 加载Caffe格式模型(需架构文件+权重文件)
net = cv2.dnn.readNet(model="models/style.caffemodel", config="models/style.prototxt")# 加载Torch格式模型(与readNetFromTorch效果一致)
net = cv2.dnn.readNet(model="models/starry_night.t7")  # 仅需传入模型文件

三、完整实战:实现多风格迁移

下面通过完整代码,实现 “加载不同风格模型 → 预处理图像 → 推理生成 → 显示结果” 的全流程。我们以 “黄鹤楼照片” 为内容图像,分别迁移 “梵高星空风” 和 “糖果风”。

1. 前期准备

  • 环境搭建:安装 OpenCV(pip install opencv-python)。
  • 模型下载:下载上述推荐的.t7格式风格模型,放在models文件夹中(与代码同级目录)。
  • 内容图像:准备一张内容图像(如huanghelou.jpg),放在代码同级目录。

2. 完整代码(支持切换风格模型)

import cv2def auto_resize(image, width=None, height=None, inter=cv2.INTER_AREA):"""自动缩放图像(保持纵横比)"""(h, w) = image.shape[:2]if width is None and height is None:return imageif width is None:ratio = height / float(h)dim = (int(w * ratio), height)else:ratio = width / float(w)dim = (width, int(h * ratio))resized = cv2.resize(image, dim, interpolation=inter)return resizeddef style_transfer(content_img_path, model_path, target_width=600):"""图像风格迁移核心函数:param content_img_path: 内容图像路径:param model_path: 风格模型路径(.t7格式):param target_width: 内容图像目标宽度(默认600px,平衡速度与效果):return: 风格迁移后的图像"""# 1. 读取并预处理内容图像content_img = cv2.imread(content_img_path)if content_img is None:raise ValueError(f"无法读取内容图像,请检查路径:{content_img_path}")# 自动缩放图像(避免尺寸过大导致推理缓慢)content_img_resized = auto_resize(content_img, width=target_width)(h, w) = content_img_resized.shape[:2]  # 获取缩放后图像尺寸# 2. 图像预处理:转换为DNN模型可识别的Blob格式# 参数说明:缩放因子1.0,尺寸(w,h),均值(0,0,0),交换BGR→RGB,不裁剪blob = cv2.dnn.blobFromImage(image=content_img_resized,scalefactor=1.0,size=(w, h),mean=(0, 0, 0),swapRB=True,crop=False)# 3. 加载风格模型并执行推理print(f"正在加载风格模型:{model_path}")net = cv2.dnn.readNetFromTorch(model_path)net.setInput(blob)  # 将预处理后的Blob传入模型output = net.forward()  # 执行前向传播,得到风格迁移结果(四维Blob:1×3×h×w)# 4. 输出结果后处理(将四维Blob转换为OpenCV可显示的图像格式)# 步骤1:重塑维度(去掉批量维度,变为3×h×w)output_reshaped = output.reshape((3, h, w))# 步骤2:归一化(将像素值映射到0-1范围,避免数值溢出)cv2.normalize(output_reshaped, output_reshaped, norm_type=cv2.NORM_MINMAX)# 步骤3:转置维度(从C×H×W转为H×W×C,符合OpenCV图像格式)output_img = output_reshaped.transpose((1, 2, 0))# 步骤4:将像素值从0-1映射到0-255(OpenCV显示需8位整数)output_img = (output_img * 255).astype("uint8")# 5. 显示结果cv2.imshow("原始内容图像", content_img_resized)cv2.imshow("风格迁移结果", output_img)print("按下ESC键关闭窗口")# 等待ESC键(27为ESC的ASCII码),关闭窗口后释放资源while cv2.waitKey(1) != 27:continuecv2.destroyAllWindows()return output_img# ------------------- 主程序:切换不同风格模型 -------------------
if __name__ == "__main__":# 内容图像路径(请根据实际情况修改)content_image_path = "huanghelou.jpg"# 风格模型路径(可切换不同模型实现不同风格)style_models = {"梵高星空风": "models/starry_night.t7","糖果风": "models/candy.t7","文艺复兴风": "models/la_muse.t7","呐喊风": "models/the_scream.t7"}# 选择一种风格执行迁移(例如:梵高星空风)selected_style = "梵高星空风"style_model_path = style_models[selected_style]# 执行风格迁移print(f"开始执行{selected_style}迁移...")result_img = style_transfer(content_image_path, style_model_path)# (可选)保存结果图像save_path = f"huanghelou_{selected_style}.jpg"cv2.imwrite(save_path, result_img)print(f"结果图像已保存至:{save_path}")

3. 代码说明与效果验证

(1)核心流程拆解
  1. 图像缩放:通过auto_resize()将内容图像缩放到宽度 600px,平衡推理速度与视觉效果。
  2. Blob 转换cv2.dnn.blobFromImage()将 BGR 图像转为 RGB 格式的四维 Blob,符合模型输入要求。
  3. 模型推理:加载.t7模型后,通过net.setInput(blob)net.forward()完成风格迁移。
  4. 结果后处理:通过重塑维度、归一化、转置,将模型输出的四维 Blob 转为 OpenCV 可显示的 8 位图像。
(2)效果验证
  • 运行代码后,会弹出两个窗口:“原始内容图像” 和 “风格迁移结果”。
  • 按下 ESC 键关闭窗口后,结果图像会自动保存为huanghelou_梵高星空风.jpg(或对应风格名称)。
  • 切换风格时,只需修改selected_style变量(如改为 “糖果风”),即可生成不同艺术风格的图像。

4. 常见问题与解决方案

四、总结与扩展

本文通过 “概念→技术→实战” 的流程,详解了 OpenCV DNN 模块实现风格迁移的完整方案:

  • 核心优势:无需依赖重型深度学习框架,仅用 OpenCV 即可快速实现风格迁移,适合轻量级部署。
  • 关键技术cv2.dnn.blobFromImage()预处理、cv2.dnn.readNetFromTorch()加载模型、结果维度转换与归一化。
  • 实战价值:支持切换多种风格模型,可应用于图像美化、文创设计、短视频特效等场景。

扩展方向

  1. 批量风格迁移:遍历文件夹中的所有图像,批量生成指定风格的结果(需添加文件遍历逻辑)。
  2. 实时摄像头风格迁移:调用电脑摄像头,实时捕捉画面并应用风格迁移(类似案例 2 的摄像头检测逻辑,将每一帧传入模型)。
  3. 模型优化:对于嵌入式设备()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/100471.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/100471.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/100471.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 日志:undo log、redo log、binlog以及MVCC的介绍

一、MySQL 日志:undo log、redo log、binlogundo log(回滚日志):是 Innodb 存储引擎层生成的日志,实现了事务中的原子性,主要用于事务回滚和 MVCC(隔离性)。 redo log(重…

【面板数据】省及地级市农业新质生产力数据集(2002-2025年)

农业新质生产力是以科技创新为核心驱动力,以科技化、数字化、网络化和智能化为主线,通过技术革命性突破、生产要素创新性配置、产业深度转型升级,实现农业全要素生产率显著跃升的先进生产力形态 本数据基于2002-2025年各省政府工作报告中关于…

20250917在荣品RD-RK3588-MID开发板的Android13系统下使用tinyplay播放wav格式的音频

input keyevent 24 1|console:/sdcard # cat /proc/asound/cards console:/sdcard # ls -l /dev/snd/【需要打开Android13内置的音乐应用才会有声音出来,原因未知!】 1|console:/sdcard # tinyplay /sdcard/Music/kiss8.wav -D 1 -d 020250917在荣品RD-R…

总共分为几种IP

IP(Internet Protocol)地址根据不同的分类标准可分为多种类型,以下是常见的分类方式:按版本分类IPv4:32位地址,格式为四组十进制数字(如192.168.1.1),约43亿个地址&#…

【Linux】常用命令(六)

【Linux】常用命令(六)1. yum命令1.1 基本语法1.2 常用命令2. 从服务器把数据cp到本地3. uname命令3.1 常用命令1. yum命令 全称:Yellowdog Updater, Modified作用:是 RPM 包管理器的前端工具,用于基于 RPM 的 Linux …

go grpc开发使用

1、安装proto 下载 Windows 版本 打开官方发布页面 访问 Protocol Buffers 的 GitHub Releases 页面: 👉 https://github.com/protocolbuffers/protobuf/releases 解压 ZIP 文件 将下载的 ZIP 文件解压到一个你容易找到的目录,例如&#xff1…

MyBatis分页:PageHelper

MyBatis分页:PageHelper 📖 前言:为什么需要分页? 在处理大量数据时,一次性从数据库查询并返回所有结果是不可行的,这会带来巨大的性能和内存开销。分页是解决这一问题的标准方案。而PageHelper是一个极其流…

Gin框架:构建高性能Go Web应用

Gin框架:构建高性能Go Web应用 Gin是Go语言中最受欢迎的Web框架之一,以其高性能、简洁API和丰富的中间件支持而闻名。本文将带你从零开始,逐步掌握Gin框架的核心概念和高级特性,并通过实际代码示例演示如何构建高效的Web应用程序。…

IO进程——线程、IO模型

一、线程Thread1、引入1.1 概念相当于是一个轻量级的进程,为了提高系统的性能引入线程,在同一进程中可以创建多个线程,共享进程资源1.2 进程和线程比较相同点:都为操作系统提供了并发执行的能力不同点:调度和资源&…

人工智能概念:NLP任务的评估指标(BLEU、ROUGE、PPL、BERTScore、RAGAS)

文章目录一、评估指标基础1. 准确率(Accuracy)2. 精确率(Precision)3. 召回率(Recall)4. F1-Score5. 示例二、文本生成专用指标1. BLEU:机器翻译与标准化文案的“质量标尺”1.1 计算流程&#x…

团队对 DevOps 理解不统一会带来哪些问题

团队对DevOps理念与实践的理解不统一、片面甚至扭曲,是导致众多企业DevOps转型失败的根本原因,它将直接引发一系列深层次的、相互关联的严重问题。核心体现在:转型极易沦为“为了工具而工具”的盲目自动化,导致最核心的文化变革被…

企业级实战:构建基于Qt、C++与YOLOv8的模块化工业视觉检测系统(基于QWidget)

目录一、概述二、项目目标与技术架构2.1 核心目标2.2 技术选型2.3 软件架构三、AI推理DLL的开发 (Visual Studio 2019)3.1 定义DLL接口 (DetectorAPI.h)3.2 实现核心功能 (DetectorAPI.cpp)四、Qt Widget GUI应用程序的开发4.1 项目配置 (.pro 文件)4.2 UI设计 (mainwindow.ui)…

SVN自动化部署工具 脚本

SVN自动化部署工具 功能概述 这是一个自动化部署SVN仓库的bash脚本,主要功能包括: 自动安装SVN服务(如未安装) 创建SVN项目仓库 配置多用户权限 设置自动同步到网站目录 提供初始检出功能 下载地址 https://url07.ctfile…

Facebook主页变现功能被封?跨境玩家该如何申诉和预防

不少跨境玩家在运营Facebook公共主页时,最期待的就是通过变现工具获得稳定收入。但现实中,经常会遇到一个扎心的问题:主页好不容易做起来,却突然收到提示——“你的变现功能已被停用”。这意味着收入中断,甚至可能导致…

安装es、kibana、logstash

下载 elk 下载地址 elasticsearch地址: https://www.elastic.co/cn/downloads/elasticsearch kibana地址: https://www.elastic.co/cn/downloads/kibana logstash地址: https://www.elastic.co/cn/downloads/logstash 解压elk 创建es全家桶文件夹 cd /usr/local mkdir elk …

Django admin 后台开发案例【字段/图片】

这是一个简单的django admin 管理后台,这个应用案例主要是给运营人员进行填写数据 主要功能包括: 上传图片功能【选择上传时可以预览】【替换已有数据中的图片时可以预览新旧图片】 每条数据都将会记录操作历史。记录操作人是谁?修改内容是什么?并且定位责任到某一员。 …

【C++】const和static的用法

目录🚀前言💻const:“只读”的守护者💯修饰普通变量💯修饰指针💯修饰函数💯修饰类成员💯修饰对象🌟static:“静态存储”与“作用域控制”💯修饰全…

F019 vue+flask海外购商品推荐可视化分析系统一带一路【三种推荐算法】

文章结尾部分有CSDN官方提供的学长 联系方式名片 B站up: 麦麦大数据 关注B站,有好处! 编号: F019 关键词:海外购 推荐系统 一带一路 python 视频 VueFlask 海外购电商大数据推荐系统源码 (三种推荐算法 全新界面布局…

【大数据专栏】流式处理框架-Apache Fink

Apache Fink 1 前言 1.1 功能 1.2 用户 国际 国内 1.3 特点 ◆ 结合Java、Scala两种语言 ◆ 从基础到实战 ◆ 系统学习Flink的核心知识 ◆ 快速完成从入门到上手企业开发的能力提升 1.4 安排 ◆ 初识Flink ◆ 编程模型及核心概念 ◆ DataSet API编程 ◆ Data…

向内核社区提交补丁

一、背景 内核的版本一直以来一直在持续迭代,离不开众多开发者的贡献。有时候我们会根据项目要求基于现有的内核版本开发一些新的功能或者修复掉一些特定场下的问题,我们是可以将其提交给社区的。 一般提交社区有两个基本原则,一是提交的补…