千家信息网

利用Python实现图片风格迁移

发表于:2025-01-28 作者:千家信息网编辑
千家信息网最后更新 2025年01月28日,本篇内容主要讲解"利用Python实现图片风格迁移",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"利用Python实现图片风格迁移"吧!1. 什么是图片的风
千家信息网最后更新 2025年01月28日利用Python实现图片风格迁移

本篇内容主要讲解"利用Python实现图片风格迁移",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"利用Python实现图片风格迁移"吧!

1. 什么是图片的风格迁移?

所谓图片风格迁移,是指利用程序算法学习著名画作的风格,然后再把这种风格应用到另外一张图片上的技术。

举个例子,见上图。左边是我们的原始图片(也称内容图像):小编在苏州甪直古镇的一座小桥上拍下的一张照片。

中间是我们的风格图片:挪威表现派画家爱德华·蒙克的代表作《呐喊》(The Scream)。

右边是将爱德华·蒙克的《呐喊》的风格应用于原始图片后生成的风格化结果图。仔细观察,图片是如何保留了流水、房屋、房屋在水中的倒影,甚至远处树木的内容,但却运用了《呐喊》的风格,就好像爱德华·蒙克在我们的景色中运用了他高超的绘画技巧一样!

问题是,我们应该定义一个什么样的神经网络来执行图片的风格迁移?

这可能吗?

答案是:可以的。我将在下一节简单讨论如何基于神经网络来实现图片风格的迁移。

2. 基本原理

Gatys等人在2015年发表了第一篇基于深度学习的风格迁移算法文章,原文链接为 https://arxiv.org/abs/1508.06576,随后文章收录于2016年的CVPR顶会。

有趣的是,他们提出了一种完全不需要新网络架构的风格迁移算法,其使用的网络构架是在前人的VGG19基础上稍加改造而成的,而且网络参数也使用预训练(通常在ImageNet上)网络的参数。我们来看下它的原理:

我们知道,卷积神经网络(CNN)具有很强的图像特征(feature/representation)提取能力,如上图所示。

对于内容图片,深层网络(d和e)提取的是高维特征,同时也丢弃了细节信息;浅层网络(a, b和c)提取的是低维特征,图片的细节大多都保留下来了。

对于风格图片,通过包含多层的特征相关性(Gram矩阵),可获得多尺度图像风格的重构,捕获其纹理信息。这样构建的网络可以忽略图像的具体细节,保留风格。

为了将内容图片和风格图片融合在一起(见下图),我们应该使风格化结果图(初始为一张白噪声图片)的特征同时与内容图片和风格图片的特征之间的距离最小化,最终获取我们所需的风格化结果图。

因此生成目标图片的损失函数可定义为:

其中α和β分别是内容图片和风格图片的特征所占的权重,通过最小化这个损失函数就可以获得我们想要的结果。来看个动态示意图:

值得注意的是,这里优化的参数不再是网络的权重ω和偏差b,而是初始输入的一张白噪声图片。

虽然上述方法可产生非常漂亮的风格迁移效果,但是速度很慢。

2016年,Johnson等人基于Gatys等人的工作,提出了一种速度可提高三个数量级的风格迁移算法。虽然算法的速度很快,但最大的缺点是不能像Gatys等人那样随意选择你的风格图片。针对每张风格图片,你都需要训练一个网络来重现这个风格。一旦网络模型训练好之后,你就可将它应用于你想要的任何内容图片了。

这篇博客我们将使用Johnson等人的方法,其算法实现和预训练模型可参考 https://github.com/jcjohnson/fast-neural-style。

3. 基于OpenCV的快速实现

下面利用OpenCV来快速实现图片的风格迁移,我将其封装成一个叫 style_transfer()的函数,其使用说明可参考函数内部的注释。目前只有11个预训练模型可用。

1.  `## 载入所需库`2.  `import cv2`3.  `import time` 4.  `def style_transfer(pathIn='',`5.  `pathOut='',`6.  `model='',`7.  `width=None,`8.  `jpg_quality=80):`9.  `'''`10.  `pathIn: 原始图片的路径`11.  `pathOut: 风格化图片的保存路径`12.  `model: 预训练模型的路径`13.  `width: 设置风格化图片的宽度,默认为None, 即原始图片尺寸`14.  `jpg_quality: 0-100,设置输出图片的质量,默认80,越大图片质量越好`15.  `'''`16.  `## 读入原始图片,调整图片至所需尺寸,然后获取图片的宽度和高度`17.  `img = cv2.imread(pathIn)`18.  `(h, w) = img.shape[:2]`19.  `if width is  not  None:`20.  `img = cv2.resize(img, (width, round(width*h/w)), interpolation=cv2.INTER_CUBIC)`21.  `(h, w) = img.shape[:2]` 23.  `## 从本地加载预训练模型`24.  `print('加载预训练模型......')`25.  `net = cv2.dnn.readNetFromTorch(model)` 26.  `## 将图片构建成一个blob:设置图片尺寸,将各通道像素值减去平均值(比如ImageNet所有训练样本各通道统计平均值)`27.  `## 然后执行一次前馈网络计算,并输出计算所需的时间`28.  `blob = cv2.dnn.blobFromImage(img, 1.0, (w, h), (103.939, 116.779, 123.680), swapRB=False, crop=False)`29.  `net.setInput(blob)`30.  `start = time.time()`31.  `output = net.forward()`32.  `end = time.time()`33.  `print("风格迁移花费:{:.2f}秒".format(end - start))` 35.  `## reshape输出结果, 将减去的平均值加回来,并交换各颜色通道`36.  `output = output.reshape((3, output.shape[2], output.shape[3]))`37.  `output[0] += 103.939`38.  `output[1] += 116.779`39.  `output[2] += 123.680`40.  `output = output.transpose(1, 2, 0)` 42.  `## 输出风格化后的图片`43.  `cv2.imwrite(pathOut, output, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality])`

来测试一下:

1.  `>>> models = glob.glob('./*/*/*.t7')`2.  `>>> models      ## 列出所有可用的预训练模型`3.  `['.\\models\\eccv16\\composition_vii.t7',`4.  `'.\\models\\eccv16\\la_muse.t7',`5.  `'.\\models\\eccv16\\starry_night.t7',`6.  `'.\\models\\eccv16\\the_wave.t7',`7.  `'.\\models\\instance_norm\\candy.t7',`8.  `'.\\models\\instance_norm\\feathers.t7',`9.  `'.\\models\\instance_norm\\la_muse.t7',`10.  `'.\\models\\instance_norm\\mosaic.t7',`11.  `'.\\models\\instance_norm\\starry_night.t7',`12.  `'.\\models\\instance_norm\\the_scream.t7',`13.  `'.\\models\\instance_norm\\udnie.t7']` 15.  `>>> pathIn = './img/img01.jpg'`16.  `>>> pathOut = './result/result_img01.jpg'`17.  `>>> model = './models/instance_norm/the_scream.t7'`18.  `>>> style_transfer(pathIn, pathOut, model, width=500)`19.  `加载预训练模型......`20.  `风格迁移花费:1.18秒` 22.  `>>> pathIn = './img/img02.jpg'`23.  `>>> pathOut = './result/result_img02.jpg'`24.  `>>> model = './models/instance_norm/starry_night.t7'`25.  `>>> style_transfer(pathIn, pathOut, model, width=500)`26.  `加载预训练模型......`27.  `风格迁移花费:3.17秒` 29.  `>>> pathIn = './img/img03.jpg'`30.  `>>> pathOut = './result/result_img03.jpg'`31.  `>>> model = './models/instance_norm/the_scream.t7'`32.  `>>> style_transfer(pathIn, pathOut, model, width=500)`33.  `加载预训练模型......`34.  `风格迁移花费:0.90秒` 36.  `>>> pathIn = './img/img04.jpg'`37.  `>>> pathOut = './result/result_img04.jpg'`38.  `>>> model = './models/eccv16/the_wave.t7'`39.  `>>> style_transfer(pathIn, pathOut, model, width=500)`40.  `加载预训练模型......`41.  `风格迁移花费:2.68秒` 43.  `>>> pathIn = './img/img05.jpg'`44.  `>>> model = './models/instance_norm/mosaic.t7'`45.  `>>> style_transfer(pathIn, pathOut, model, width=500)`46.  `加载预训练模型......`47.  `风格迁移花费:1.23秒`

从运行结果可知,在CPU上,一张图片的风格迁移所花的时间大概也就几秒。如果使用GPU,完全可以实时对视频/摄像头进行风格迁移处理。

4. 目前的相关进展

自Gatys等人第一次(2015年)实现基于深度学习的风格迁移以来,风格迁移技术仍一直在发展,如今在速度和质量上都有了很大提高。目前的一些进展可以通过下面的链接来了解:

  • https://github.com/jcjohnson/fast-neural-style

  • https://github.com/DmitryUlyanov/texture_nets

  • https://github.com/luanfujun/deep-painterly-harmonization

  • https://junyanz.github.io/CycleGAN/

他们的一些作品:

1. 风格迁移

2. 外来图片的融合

3. 图片季节的变换

4. 图片背景的虚化

5. 角色互换

到此,相信大家对"利用Python实现图片风格迁移"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

图片 风格 训练 网络 模型 内容 特征 算法 结果 原始 学习 函数 图像 速度 输出 参数 尺寸 平均值 方法 神经 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 电子板报网络安全素材 软件开发是上的什么大学 填报志愿数据库软件 政府吸引 网络技术人才缺乏 软件开发工程师要求掌握什么 互联网科技公司人事岗位武汉 能力果实模组服务器 数据库字典怎么设计 我的世界手机版定位服务器进不去 系统网络技术有限公司 网络安全评价标准的形成 electron连接单机数据库 删除数据库出现错误是什么原因 网站mysql数据库编程 广州游爱网络技术有限公司简历 基于模型的软件开发方法研究 加域服务器共享 开展网络安全大检查的报告 上海黄金交易所软件开发中心 网络技术的专业规划 rdp在线数据库 深圳市网络安全协会会员单位 金铲铲之战登神长阶服务器 天猫无忧购服务器 陕西省公安网络安全备案 数据库基础知识实训报告 奥商网络技术有限公司怎么样 网警普法网络安全 郧西服务软件开发学习 和晶科技互联网金融
0