本文同步发表在我的微信公众号“计算摄影学”,欢迎扫码关注
【转载请注明来源和作者】
上次给大家讲了一种逐点进行的纹理合成方法Texture Synthesis by Non-parametric Sampling[链接],它可以得到非常惊人的效果,然而它的缺点是速度很慢,重新贴一遍合成过程如下:
你肯定会想,有没有一种方法可以大大加速纹理合成的过程而又能得到同样的效果呢?幸运的是,2001年时,Texture Synthesis by Non-parametric Sampling的作者Efros又和另外一位学者William T. Freeman写出一篇论文Image Quilting for Texture Synthesis and Transfer,恰好就给这个问题带来了答案。
这个新的算法采用了每一次合成一个块而不是一个像素点的方式,因此速度相当快。我做了一个动图,大家可以看看其合成的过程:
今天这个算法不仅仅可以实现纹理的生成,还可以实现纹理的转移,甚至还能实现图像风格化,下图就是一个典型的纹理转移的过程:
据说这个算法甚至被用来做”假“新闻,你可以看看这张图片里面,小布什总统演讲时身后的很多士兵都是用这个算法造出来的
今天我们先来看看该算法想要解决的问题,以及其解决方案。
一、目标和解决方案
1.1 目标1:高速纹理合成
如何进行高速纹理合成,这是作者首先想要解决的问题。如果是你来做,你会想什么办法呢?可能很多人都会想到,可以把随机的纹理块组合在一起,就像下面这样:
先从原始的Texture源中随机的选取一个Block:
然后把随机的Blocks组合到一起,形成目标图像:
你肯定会想到,这样每个块差异很大,直接组合起来很容易看出截断感觉。于是你会想到约束每个块直接的差异,让尽量相似的块排布在一起。为了限制块与块的相似度,你可以规定只有一个块与其左边和上方的块的重叠部分的差异很小时,才能被选择填充到目标图像中。为了依然保有一部分随机性,实际上是采用了先构造所有满足上述差异性限制的块的列表,再随机从中选取一块的方式。效果见下图,很明显效果有较大提升,但是接缝处还是可以看到明显的断裂。
怎么消除这种截断感呢?你也许能想到很多办法,甚至采用我们之前介绍过的金字塔融合或者泊松融合的方法。 但这里作者采用了寻找具有最小代价的接缝的方式,比较好的融合了接缝两边的图像块。
其接缝处理的方法,和我们讲过的Seam Carving[链接]的方法几乎一致:
你可以再看看动图来理解这个过程:
由此可见,其纹理生成的过程是将一个一个的相似的块缝合到一起的过程,这也是这个算法名称Image Quilting的由来。
这个方法的效果非常不错,可以看看它更多的效果图。
1.2 目标2: 纹理转移
我对Image Quilting算法感兴趣的原因是,它不仅仅解决了高速合成纹理的问题,还试图解决问题转移的问题。
什么叫做纹理转移?一张图可以说明问题:
在转移过程中,作者依然采用了纹理缝合的方式,其大部分流程都和刚刚讲的纹理生成过程一致,但在选择相似块时,有一点点不同:
另外的两个要点是:
- 如何计算纹理块和待填充区域的原有图像的接近程度?
作者创造了一个概念叫做Correspondence Map,实际上是指为了比较这种接近程度,分为两个步骤
- 将源纹理图和目标图做指定的变换,例如都转换为灰度图像,或都做一定模糊(rgb2gray)
- 比较接近程度时,在变换后的图像空间上进行
2. 如何选择Patch的大小?
作者指出,单个大小的纹理块来做纹理转移可能效果不够好,因此他们采用了不同的块的大小来迭代式的多次转移的方法来提升效果。 其中,用大的纹理块先做,可以快速的粗糙的缝合纹理块,接下来用更小的纹理块,可以精细化的提升效果。
纹理转移的动态过程可以展示如下:
作者展示了很多惊人的效果,你可以看看更多的效果图。
事实上在纹理转移还可以用于图像风格化,在github上可以看到有一个对Image Quilting的实现http://jmecom.github.io/projects/computational-photography/texture-synthesis/,作者贴出了一些实现出来的效果(上面纹理转移的动图是我在这个工程基础上制作的)
这个项目的作者指出,当使用Image Quilting来做图像风格化时,使用简单的图像亮度来评估texture和待填充目标图像块之间的差异很容易受到图像亮度的轻微变化的影响,例如下面这个例子中,林肯的背后的墙在风格化后本来应该保持同样的纹理,但因为其亮度的轻微差异,导致了最后的纹理有很大不同(这也是这种相对传统简单的算法比起现在用深度学习来做图像风格化的方法的缺点)
二、算法实现
作为经典算法,你可以在github上找到很多该算法的实现。我也根据https://github.com/afrozalm/Patch-Based-Texture-Synthesis做了扩展和重构,修复了一些Bug,添加了纹理转移的功能,实现到了这个仓库中:
https://github.com/yourwanghao/Patch-Based-Texture-Synthesis
其中我还参考了https://github.com/anopara/patch-based-texture-synthesis里面生成GIF动画的方法,用于生成这篇文章所需的动图。
三、总结
今天我介绍了一个发表于2001年的采用块匹配的方式来进行高速纹理生成和转移的算法,并给出了Python实现,它是作者Efros在纹理合成方向上的进一步探索,也为后面的图像风格化领域带来了灵感。
希望这篇文章能够给你带来启发,别忘了给我点赞哦^_^
四、参考资料
本文的大部分信息来自于作者对论文的官方介绍:
- 论文:Efros and Freeman, “Image Quilting for Texture Synthesis and Transfer,” SIGGRAPH 2001
- 作者的演示Slides: https://people.eecs.berkeley.edu/~efros/research/quilting/efros-siggraph01.ppt
- 我的代码实现的基础是:https://github.com/afrozalm/Patch-Based-Texture-Synthesis,我在此基础上作了扩展和修改。注意现在的transfer代码还有很大问题
- 我使用了http://jmecom.github.io/projects/computational-photography/texture-synthesis/中的示意图片,来说明该算法用于图像风格化的结果. 这个工程原本有一些坐标计算的Bug,我对此进行了修复
本文还有少量信息来自于:
CMU 2017 Fall Computational Photography Course 15-463, Lecture 9