雷锋网(公众号:雷锋网)按:本文作者phunter,文章来源大数据杂谈。文中只要介绍了如何使用MXnet做出具有艺术风格的照片。
Neural art:用机器模仿梵高
Neural art是个让机器模仿已有画作的绘画风格来把一张照片重新绘画的算法,比如给一张猫的照片和一张梵高的自画像,我们就可以得到用梵高风格画出来的猫,比如这个样子(图二为梵高在1889年的自画像,引用自wikipedia):
Neural art算法来自于这篇论文 “A Neural Algorithm of Artistic Style” by Leon A. Gatys, Alexander S. Ecker, and Matthias Bethge,链接在http://arxiv.org/abs/1508.06576 有兴趣的观众朋友们可以阅读。
它的基本想法是,利用一个多层的卷积网络(CNN)抽象出给定绘画作品里一些高级的隐藏特征用来模仿绘画风格,并把这个绘画风格应用到一个新的图片上。这类的图像生成模型是深度学习的一个方向,比如谷歌的Inception把一个羊的图片和一个云的图片生成羊形状的云之类的“迷幻类”图像也是类似模型的一种。Facebook也有类似的生成模型,他们基于这篇http://arxiv.org/abs/1406.2661由DMLC作者@antinucleon等人合作的文章。
Neural art算法模型有多种实现方式,比如这里和这里是两个Lua/Torch版的实现,这片论文的gitxiv下面也包含了五花八门的各种实现,他们都是实现论文中的VGG模型并用caffe描述,下面的示例是用MXnet来实现。
MXnet的Neural art样例
MXnet的neural art范例在mxnet/example/neural-style/目录下。因为这个例子需要大量的计算,推荐安装GPU版的mxnet。安装mxnet GPU版的教程参见前一集 http://phunter.farbox.com/post/mxnet-tutorial1 这里就不再重复。当然了,mxnet的CPU和GPU无缝连接,如果没有GPU可以使用CPU版本,只是需要每张图耐心等待约40-50分钟。
选择安装:mxnet可选使用cuDNN加速。对Neural art的例子,cuDNN v3和v4均可运行,v4在我的GTX 960上比v3稍微快约2-3秒。可以简单的执行这几步:
如果之前没有编译安装cuDNN版的mxnet,请在make/config.mk里把USE_CUDNN = 0修改为1重新编译,并更新安装对应的python包。
如果你没有安装mxnet GPU版本的条件,也可以访问以下这些网站或app玩一下Neural art。这个算法需要大量的GPU计算,以下这些免费或收费的实现都需要排队。
Deepart:网址 https://deepart.io/ 用户可以免费提交,平均等待时间为1周左右,如果想插队到24小时之内,可以捐款给网站。
Pikazo App:网址 http://www.pikazoapp.com/ 它相当于把deepart这个网站做成app,需要收费$2.99,也需要排队。
AI Painter: 网址 https://www.instapainting.com/ai-painter 这是instapainting的一个业务,免费,也是需要排队。
观众朋友们如果正好有一个装了GPU版mxnet的机器的话,那我们就开始用mxnet自己动手丰衣足食,还可以帮朋友们生成有艺术感的微博头像哟。以下例子中我用我妹 @dudulee的浪里格朗 家的美猫“破狗”的照片为例讲解具体生成艺术图的步骤。
简要步骤和参数调整
mxnet使用的是论文中描述的VGG模型,在第一次使用的时候需要执行download.sh下载该模型,mxnet的模型版本占约几十MB的空间。下载模型完毕之后,可以把需要绘画的原始图片和模仿的图片放到input目录里,比如说破狗的照片和梵高的图像,然后执行:
耐心等待1-2分钟,就可以看到结果保存在output目录里,比如是这样的:
如果给另外一张现代艺术油画 'Blue Horse' Modern Equine Art Contemporary Horse Daily Oil Painting by Texas Artist Laurie Pace (链接https://www.pinterest.com/pin/407223991276827181/) 替代梵高的画作让机器学习风格,破狗可以画成这样的:
run.py里有一些可以调整的参数,如果想调试输出效果可以按照如下解释调整:
-
–model 指定模型。例子里暂时只有vgg这一个模型,以后可能添加前面提到的inception等其他模型。暂时先不用改。
-
–content-image 内容图片,比如上面的“破狗”的照片
-
–style-image 输入的绘画原作的路径,比如上面的的“梵高自画像”。
-
–stop-eps 模型里用eps值代表两幅图的风格相似度,在训练的过程里会看到这个值逐渐收敛,值越小相似度越高。stop-eps参数指定的是收敛的终止值,一般越小就代表画的越像,但如果太小了会需要很多的计算时间来收敛,默认0.005已经可以得到不错的效果,可适当减小到0.004等。
-
–content-weight –style-weight 内容图片和绘画原作的相对权值,默认是10:1,如果发现绘画风格过于强烈涂抹一片,可适当修改为20:1或者30:1,反之改小。
-
–max-num-epochs 最大收敛步数,默认是1000步。不过一般画作在200步左右就能找到差不多合适的eps风格相似值,这个最大收敛步数不需要修改。
-
–max-long-edge 长边最大边长。程序会自动把输入图片按照这个值等比例缩放,比如上面的图就是缩放到高度为512像素。程序运行时间及内存消耗约和图片面积成正比,因为卷积网络的计算量每个像素相关,700像素的图片差不多比500像素的图片多一倍内存和运行时间。在接下来的对比测试里面可以看到,512像素的图差不多需要1.4GB显存,适合2G显存的显卡比如nvidia显卡的macbook pro等娱乐一下就足够了,4GB的显卡差不多最高可以处理到850-900像素的图片,要想上1080p就得有Titan X的12GB了。同样的,计算时间也会相应拉长,它也和显卡的CUDA核心数约成反比。现在你基本上明白了为什么上面提到的免费版都需要排队几个小时到几周不等了。
-
–lr logistic regression的梯度下降(SGD)学习率,用来寻找既在内容上满足“像破狗”又在风格上“像梵高”的生成图像。较大的eta收敛较快,节省计算时间但会在最小值附近跳跃。默认值0.1,可以调整到0.2和0.3都可以。
-
–gpu 使用第几个GPU,默认是0号GPU,适合只有一块显卡的用户(比如我家里的机器)。如果没有GPU并能忍耐40分钟左右算一张图,–gpu -1也可以指定为纯CPU计算。
-
–output 输出文件名。
-
–save-epochs 是否保存中间结果,默认每50步保存一下结果。
-
-remove-noise 降噪参数,默认0.2,可以降低一些为0.15,这就是高斯降噪的半径。程序在学习模仿画作的过程里会使用两个白噪声图片逼近风格图和内容图,在最终生成的图片里面可能残留一些不必要的噪声点,程序里面可以降噪处理。
机器怎么模仿绘画风格
这个问题的答案在原论文里也语焉不详,作者也没有想解释清楚。以下的讨论均按我个人根据原文以及reddit和知乎上的相关讨论在这里概述一下,更多讨论详情请参阅:reddit 知乎 这里一并感谢上述链接里的作者和评论者。
量化表示“绘画风格”
“绘画风格”是一个抽象定型的词语,它可能和图像的某种高阶统计量相关,但不同的绘画风格有不同的表示,对于一个没有具体定义风格的一般性问题,它很难用人工设计算法去完成。幸运的是,我们知道卷积网络CNN可以通过多层卷积提取物体的抽象特征完成物体识别(请参考Yann Lecun的深度学习教程),这一点“提取抽象特性”的能力被作者借用来描述“风格”。也就是说,经过多层CNN抽象之后的图片丢弃了像素级的特征,而保留了高级的绘画风格。下图引用自原论文图1。在文章里,作者定义了一个5层的CNN网络,梵高的星空在通过第一二三层的时候保留了一些原图的细节,但是在第四第五层的时候,就变成了“看起来是梵高星空的样子”这样的抽象特征:
这时候作者机智的想到了,如果把一张梵高一张其他照片同时都放到这个CNN网络里,经过合适的调整让第二张照片在第四五层接近梵高,而第一二三层保持和原来差不多,那就可以模仿梵高了!细节上,作者为了沿用了CNN的特征抽象能力使用了CNN作物体识别的VGG模型。
学习风格并生成图像
于是让机器模仿绘画风格并生成图片成了一个优化问题:生成的图像要像原内容图,比如我给一张猫的图片最终还是要像猫;生成的图像要像是由风格图画的,比如我给了个梵高的图,我生成的猫的图片要看起来有梵高的风格。也就是说要找到这样一个中间结果,它的内容表示(第一二三层CNN)接近于破狗,它的风格的表示(第四第五层CNN)接近于梵高。在文章里,作者用一个白噪声图片通过梯度下降生成一个接近内容图的图片,以及另一个白噪声图片生成一个接近绘画图风格的图片,并定义了神奇的描述纹理的gram matrix定义了这两个图的损失函数并加权平均当作优化目标函数,在mxnet的实现里通过梯度下降(SGD)完成收敛找到这样一个内容和风格都搭配中间结果。举例来说,“破狗”和“梵高自画像”的生成过程的200多步的循环里,图像的变化依次如下图所示:
我们可以看到,在刚开始的几十步里,图片更像是原图和绘画的简单纹理的叠加,而随着循环步数增加,程序慢慢学习到了配色和笔触的风格,在150步左右基本成型,最终把破狗的照片绘画成梵高的风格。
模仿风格是不是只有这一个办法?
事实上不是的,很多计算图形学的论文已经针对各种方向做出了一些成果,只是这篇文章利用了深度学习和CNN的方法,其他类似学习风格的论文可以参考相关阅读:
"A Parametric Texture Model Based on Joint Statistics of Complex Wavelet Coefficient" http://www.cns.nyu.edu/pub/lcv/portilla99-reprint.pdf这片文章用小波变换的方式提取了图片纹理“风格”所对应的二阶统计量,和本文提到的论文想法是一致的。
“Style Transfer for Headshot Portraits”
https://people.csail.mit.edu/yichangshih/portrait_web/ 这篇文章针对头像照片的风格做到了很快的风格学习,并且可以实时转换视频,对于这个有严格限制的问题,它的速度比Neural art高到不知道哪里去了。
结语
作为深度学习和CNN的例子,Neural art确实很好玩,观众朋友们可以自己用MXnet给自己和朋友们生成有意思的艺术图片,记得发到微博上加#mxnet#话题分享。值得提醒的是,如果原图是半身人像类,建议也使用一些人像的画作来学习风格,比如“破狗”+“梵高”的组合;相对应的,风景图片最好用风景画作风格学习。因为风景的表现重点和人像不同,强行把风格画到人像的照片上并不适合,它会看起来像是两幅图简单叠加,这个即使是人类画家也不好画在一起。
雷锋网注:本文转自大数据杂谈,如需转载请联系原作者。
雷锋网版权文章,未经授权禁止转载。详情见转载须知。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/ai/60740.html