图像素描风格生成

前言

论文链接:Combining Sketch and Tone for Pencil Drawing Production

Matlab版本的代码,目前找到有两个:

1、https://github.com/fumin/pencil

2、https://github.com/candycat1992/PencilDrawing

效果看起来第二个要好,而且写的代码非常简洁。

我实现了Scala的版本(有一小部分用到了python),基于第一个Matlab版本的代码:

https://github.com/Ldpe2G/Pencil-Drawing-Scala

其实是差不多实现完了才发现了第二个版本的matlab代码,后面会看看能否作些改进。

正文

首先看看从论文中截取的素描风格生成框架图:

主要是两大步组成,模拟画家画素描画的两个步骤:

1,Line Drawing,先画线,描轮廓;

2,Tone Drawing 再加上色调,比如阴影。

下面详细介绍两个步骤。

1. Line Drawing

首先来看看一幅图:

左边是画家画的一幅素描画,右边是放大细节部分。通过观察我们可以发现,画家在画

边的时候,都是用一段一段的线段组合起一幅画的。基于这个事实,文章提出了一种模

拟素描画边的方法。主要也是分两步走。

1.1 Classification

首先将输入图片转为灰度图,然后通过前向差分,分别计算x,y方向的梯度,再根据以下

公式计算大小:

公式中的 I 表示输入图片的灰度图,实现上我是用Prewitt’s operator来计算梯度的,

也试过Sobel 算子,效果差不多。

在模拟素描画线的难点在于估计每个像素点的画线方向,比较简单的方法是根据梯度方向,

但是会很容易受噪声的影响,而在文章中则提出了一个更加鲁棒的策略。

首先生成8个方向的线段(卷积核),

然后分别和G作卷积:

然后通过得到的相应图Gi来分类像素点,i (1~8):

p代表原图像素点的索引。根据公式3,我们可以知道

文章中声称以上的方法能对抗各种的噪声。

1.2 Line Shaping

获得Ci之后,首先和对应的线段卷积核作卷积,然后再加起来:

通过卷积操作可以聚集附近同一个方向的像素点,这样就可以把边原图上边上的像素点连起

来。最后的结果就是把S‘的像素值反转,然后再映射到 [0, 1] 区间。就得到结果了。

用scala代码跑的结果作演示:

2. Tone Drawing

这一步这要就是模拟画家用铅笔上色的过程,这需要利用道原始灰度图的信息。

我们首先来看一张图:

左边是自然场景图片和对应的像素值直方图,右边是素描画和对应的直方图。

可以看到直方图的分布是很不一样的。因此原图像的色调是不能直接用在色调生成上的。

然后文章中提出了一种参数化模型来解决这个问题。

2.1 Model-based Tone Transfer

文中提出了一个模型来表示色调分布:

v 表示色调值,然后 p(v)表示这个像素是用色调值v来表示的概率。Z是正则化因子。

三个 pi(v) 分别代表在素描画中的三个不同的色调层,ω 代表权值,形象的理解可以看

作是对应的色调的像素值的个数。再来看一幅图:

(a)是一幅素描画,然后 (b),是把像素值分成三类的结果,绿,橙,蓝分别代表

深,中,浅三种色调。(c)对应的三种色调的直方图。分析结果就是,自然图像和素描

画的最大的区别就是素描画空白的区域更大,亮度更高。

然后三中色调对应三个公式来表示:

然后就是如何求解公式中的参数了。

2.2 Parameter Learning

权值 ω 由每个色调层的像素个数决定。然后对每层的参数采用最大似然估计的方式来

求解。每层的像素值的均值和标准差表示为m和s。参数可以近似的表示为:

xi代表像素值,N表示每层像素值的个数。

然后学习到的参数如下:

但是其实在matlab代码的实现上,对于权值 ω的设定和三个公式的实现,并不是完全按照

论文中的定义来实现的,我做了不少实验来调节参数然后看结果,发现还是得按照matlab

代码的设定才能最大程度复现论文的结果,所以应该还有有哪里一些细节没处理好。

然后学习到参数之后,对于每一张新的输入图像,通过直方图匹配的方法来修正灰度图的

像素值,也就是用输入图像的灰度图的直方图去匹配素描画的直方图。

2.3 Pencil Texture Rendering

做完直方图匹配之后,原图的像素值分配就比较接近素描画的了,但是还不能直接就用这个

修正的灰度图和上一步生成的描边直接组合,还需要模拟一下素描画的纹理。如何生成

这个纹理是一个很难解决的问题。

文章中生成他们收集了20张左右的素描纹理图来做实验,matlab的代码中提供了3张:

每个输入图片只需要一张即可。在画家作画的时候,色调的生成就是在某处重复的画。

模拟的方法直观的理解就是,通过将纹理图作乘法。

。这个 beta 就是我们要求解的。 beta 越大则得到的得到色调越深。通过求解以

下公式可以得到 beta :

其实怎么在代码上去实现求解我是想不到的,但是好在matlab的代码实现了求解,

最后其实是在求解一个非常大的线性方程组,不过矩阵都是非常稀疏的。至于怎么能

那么实现,到目前为止我还是没看懂,不过直接把matlab的代码移植到scala还是没问

题的。个人感觉复现过程中最难的部分也就是这里了,我尝试了很多java/scala的矩阵库

(la4j, mtj, colt等等),速度上都不满意,最终发现 breeze是速度上最接近matlab的,

但是在求解稀疏矩阵相关的线性方程组的时候,breeze还不支持,最后实在没办法了,

只能把这部分求解的实现放到python中去做,用scipy这个库来解决,由此可以看到,

scala在做科学计算上还是,比不上python。最后用了一种比较low的方法,在代码中调

用python的脚本,然后再把脚本的结果读取上来。

ok,回到正题,得到 beta 之后,模拟素描画色调纹理的图就可以得到了:

最终的结果就是把色调和轮廓结合起来,用一个矩阵的点乘操作即可:

3 Color Pencil Drawing

文章还做了一些拓展,比如如何给素描画上色,就是比如把RGB转换到YUV空间,

然后把Y通道拿出来,经过之前的步骤来生成素描画,再把它放回到Y通道上,最后再

重新转换成RGB即可。文章剩下的部分就是一些结果展示和对比试验结果,想深入了解

的话可以去看看paper。

4 复现结果展示

最后展示一下用scala代码生成的一些素描图,只能说勉强复现了论文的方法。

展示格式,原图,素描轮廓图,素描图或彩色素描图。

5 参考资料

[1] http://stackoverflow.com/questions/12636896/how-to-solve-a-linear-system-of-matrices-in-scala-breeze

[2] http://statr.me/2015/09/an-overview-of-linear-algebra-libraries-in-scala-java/

[3] http://stackoverflow.com/questions/7086820/convert-rgb-to-ycbcr-c-codehttps://en.wikipedia.org/wiki/Edge_detection

[4] https://en.wikipedia.org/wiki/Edge_detection

[5] http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.301.927&rep=rep1&type=pdf

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

1 条评论
登录 后参与评论

相关文章

来自专栏Ldpe2G的个人博客

图像素描风格生成

1122
来自专栏计算机视觉

perceptual loss(感知loss)介绍,解释做到详细

Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Net...

4308
来自专栏大数据挖掘DT机器学习

确定权重方法之一:主成分分析

作者:数据小宇军 http://blog.sina.com.cn/s/blog_a032adb90101k47u.html 什么是权重呢?所谓权重,是指某指标...

2616
来自专栏AI科技评论

干货 | 史上最好记的神经网络结构速记表(下)

翻译 / 唐青 校对 / 李宇琛 整理 / 雷锋字幕组 本文提供了神经网络结构速查表,全面盘点神经网络的大量框架,并绘制直观示意图进行说明,是人手必备的神经网...

36012
来自专栏Petrichor的专栏

深度学习: 参数初始化

好的开始是成功的一半。 为了让你的模型跑赢在起跑线 ε=ε=ε=(~ ̄▽ ̄)~ ,请慎重对待参数初始化。

1232
来自专栏用户2442861的专栏

相似图片搜索的原理(二)

每张图片都可以生成颜色分布的直方图(color histogram)。如果两张图片的直方图很接近,就可以认为它们很相似。

671
来自专栏计算机视觉life

OpenCV学习入门(三):kmeans原理及代码

Kmeans是一种非监督的聚类方法,是最常用的聚类技术之一。kmeans尝试找到数据的自然类别,通过用户设定的类别个数K,它可以快速的找到“好的”类别中心,“好...

1775
来自专栏磐创AI技术团队的专栏

基于word2vec训练词向量(二)

作者 | 荔枝boy 编辑 | 磐石 出品 | 磐创AI技术团队 ---- 【磐创AI导读】:前几篇文章中我们介绍了一些机器学习、深度学习入门资源项目合集,本篇...

3709
来自专栏大数据挖掘DT机器学习

KMeans聚类算法思想与可视化

1.聚类分析 1.0 概念 聚类分析简称聚类(clustering),是一个把数据集划分成子集的过程,每一个子集是一个簇(cluster),使得簇中的样本彼此...

6406
来自专栏Petrichor的专栏

深度学习: 数据扩充 (Data Augmentation)

包括:水平翻转、垂直翻转、水平垂直翻转。OpenCV中的 cv2.flip 接口可用于快速实现翻转操作:opencv: cv2.flip 图像翻转 进行 数据增...

1753

扫码关注云+社区