先来看下效果:

上图是小编在甘南合作的米拉日巴佛阁外面拍下的一张照片,采用风格迁移技术后的效果为:

一些其它效果图:

下面进入正题。

近年来,由深度学习所引领的人工智能(AI)技术浪潮,开始越来越广泛地应用到生活各个领域。这其中,人工智能与艺术的交叉碰撞,在相关技术领域和艺术领域引起了高度关注。就在上个月,由电脑生成的艺术品在佳士得(Christie’s)的拍卖价竟高达43.25万美元,证明人工智能不仅可以具有创造性,还可以创作出世界级的艺术品。

早些时候,有些人坚信艺术的创造力是人工智能无法替代的,艺术将是人类最后一片自留地!这不,没过多久,这片唯一的自留地也逐渐被人工智能所取代。

在这各种神奇的背后,最核心的就是基于深度学习的风格迁移(style transfer)技术。我将在这篇博客带领大家学习如何使用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个预训练模型可用,所有模型和相应风格图片都已上传至百度网盘。

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

来测试一下:

>>> models = glob.glob('./*/*/*.t7')
>>> models      ## 列出所有可用的预训练模型
['.\\models\\eccv16\\composition_vii.t7', '.\\models\\eccv16\\la_muse.t7',  '.\\models\\eccv16\\starry_night.t7', '.\\models\\eccv16\\the_wave.t7', '.\\models\\instance_norm\\candy.t7', '.\\models\\instance_norm\\feathers.t7',  '.\\models\\instance_norm\\la_muse.t7',   '.\\models\\instance_norm\\mosaic.t7',    '.\\models\\instance_norm\\starry_night.t7',  '.\\models\\instance_norm\\the_scream.t7',    '.\\models\\instance_norm\\udnie.t7'] >>> pathIn = './img/img01.jpg'
>>> pathOut = './result/result_img01.jpg'
>>> model = './models/instance_norm/the_scream.t7'
>>> style_transfer(pathIn, pathOut, model, width=500)
加载预训练模型......
风格迁移花费:1.18秒 >>> pathIn = './img/img02.jpg'
>>> pathOut = './result/result_img02.jpg'
>>> model = './models/instance_norm/starry_night.t7'
>>> style_transfer(pathIn, pathOut, model, width=500)
加载预训练模型......
风格迁移花费:3.17秒 >>> pathIn = './img/img03.jpg'
>>> pathOut = './result/result_img03.jpg'
>>> model = './models/instance_norm/the_scream.t7'
>>> style_transfer(pathIn, pathOut, model, width=500)
加载预训练模型......
风格迁移花费:0.90秒 >>> pathIn = './img/img04.jpg'
>>> pathOut = './result/result_img04.jpg'
>>> model = './models/eccv16/the_wave.t7'
>>> style_transfer(pathIn, pathOut, model, width=500)
加载预训练模型......
风格迁移花费:2.68秒 >>> pathIn = './img/img05.jpg'
>>> model = './models/instance_norm/mosaic.t7'
>>> style_transfer(pathIn, pathOut, model, width=500)
加载预训练模型......
风格迁移花费: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. 角色互换

为了方便在电脑上阅读,文章也同步更新到相应专栏:

  • 知乎:

    https://www.zhihu.com/people/zoro-3-92/posts

  • 简书:

    https://www.jianshu.com/u/981ba7d6b4a6

往期热门:

菜鸟学Python数据分析|文章汇总上篇

值得收藏|菜鸟学Python【入门文章大全】

菜鸟写Python程序,如何从新手变老手

学习群:

小密圈人气很高的两个实战项目

小密圈的趣味实战-微信主题

3个月还没入门Python,看这100名小密圈的同学3周学Python的杰作

用Python深度学习来快速实现图片的风格迁移相关推荐

  1. 深度学习笔记(47) 神经风格迁移

    深度学习笔记(47) 神经风格迁移 1. 神经风格迁移 2. 代价函数 1. 神经风格迁移 近,卷积神经网络最有趣的应用是神经风格迁移 来看几个例子,比如这张照片,照片是在斯坦福大学拍摄的 如果想利用 ...

  2. Keras深度学习实战(21)——神经风格迁移详解

    Keras深度学习实战(21)--神经风格迁移详解 0. 前言 1. 神经风格迁移原理 2. 模型分析 3. 使用 Keras 实现神经风格迁移 小结 系列链接 0. 前言 在 DeepDream 图 ...

  3. 深度学习项目二: 图像的风格迁移和图像的快速风格迁移 (含数据和所需源码)

    图像风格迁移是指,将一幅内容图的内容,和一幅或多幅风格图的风格融合在一起,从而生成一些有意思的图片 一:传统的图像风格迁移 为了让我们生成的迁移图在风格上与风格图片尽可能相似,在内容上尽可能与内容图相 ...

  4. 深度学习(十)人脸识别与神经风格迁移

    转载自:https://blog.csdn.net/red_stone1/article/details/79055467 <Convolutional Neural Networks>是 ...

  5. 手把手写深度学习(12):CycleGANs伟大的风格迁移理论基础篇

    前言:前几篇博客讲了pix2pix GANs,能做点对点的转换,并且需要成对的数据.本文介绍cycleGANs,不需要成对的数据集,能做域之间的转换,能做很多有趣的应用:风格迁移.物体变形.季节转换. ...

  6. 吴恩达老师深度学习视频课笔记:神经风格迁移(neural style transfer)

            什么是神经风格迁移(neural style transfer):如下图,Content为原始拍摄的图像,Style为一种风格图像.如果用Style来重新创造Content照片,神经风 ...

  7. Python深度学习-快速指南

    Python深度学习-快速指南 (Python Deep Learning - Quick Guide) Python深度学习-简介 (Python Deep Learning - Introduct ...

  8. [GAN学习系列3]采用深度学习和 TensorFlow 实现图片修复(中)

    上一篇文章–[GAN学习系列3]采用深度学习和 TensorFlow 实现图片修复(上)中,我们先介绍了对于图像修复的背景,需要利用什么信息来对缺失的区域进行修复,以及将图像当做概率分布采样的样本来看 ...

  9. 怎么装python的keras库_Keras 教程: Python 深度学习终极入门指南

    在这篇 Keras 教程中, 你将学到如何用 Python 建立一个卷积神经网络! 事实上, 我们将利用著名的 MNIST 数据集, 训练一个准确度超过 99% 的手写数字分类器. 开始之前, 请注意 ...

最新文章

  1. QT的滚动条极简教程
  2. 3种时间序列混合建模方法的效果对比和代码实现
  3. 加入收藏 lsk的BLOG
  4. 在div中设置文字与内部div垂直居中
  5. opengl 区域填充之种子填充线扫描法
  6. HTML-浮动(特点-影响-居中)-定位
  7. Linux Qt工程组织结构与动态库引用
  8. 数据库原理及应用教程第四版课后答案
  9. 【uni-app】第三方ui组件推荐引入的方法
  10. wps自动生成目录总是有正文内容
  11. win7系统电脑蓝屏怎么解决,如何解决win7电脑蓝屏
  12. 当我真正开始爱自己,我才认识到,所有的痛苦和情感折磨,都...
  13. Python中文分词及词频统计
  14. win7关机一直卡在正在关机
  15. centos 安装kermit
  16. 用matlab解方程组例子,Matlab求解超定方程组实例
  17. MySQL-条件查询
  18. JAVA学习56_用UltraEdit代替“笨重”的IDE,实现轻巧编程!
  19. WZOI基础题库1:Hello World
  20. 解决vue路由hash模式下,微信网页授权问题

热门文章

  1. java.lang.ClassCastException: com.mysql.jdbc.Driver cannot be cast to javax.sql.DataSource
  2. 汽车 OTA 是不可或缺的吗?
  3. 用React实现百度搜索框(简易版)
  4. Microsoft JScript 运行时错误: 缺少对象
  5. 代码发芽网(Beta版)发布,欢迎测试、试用
  6. 表面肌电信号sEMG之常用特征
  7. 同一局域网计算机发消息,win7系统中为局域网电脑发消息的具体操作步骤
  8. AS自带安卓模拟器无法启动,一直黑屏解决方法
  9. 2021年中国白酒行业现状及趋势分析:产品需求向中高端类走[图]
  10. 区块链三加一:致李笑来老师的一封感谢信!