铅笔画算法

PencilDrawing

论文《Combining Sketch and Tone for Pencil Drawing Production》(Cewu Lu, LiXu, JiayaJia)
算法的实现。

代码说明

oschina: git.oschina.net/corfox/Kikyo
github: github.com/corfox/Kikyo
该算法的实现在项目目录PencilDrawing中。

依赖

OpenCV2.4.10
Eigen3

class PencilDrawing

构造函数

PencilDrawing()

成员函数

void operator()(const Mat& image, const Mat& pencilStyle, OUT_PARA Mat& pencilDrawing)

生成图像image的铅笔画。

image:原始图像,image的类型需为BGR三通道彩色图或Gray单通道灰度图。
pencilStyle:铅笔画的风格模板(线条的粗细或轻重)
pencilDrawing:算法生成的铅笔画

算法步骤

注:此算法步骤摘自《Combining Sketch and Tone for Pencil Drawing Production》

算法的整体框架如下图:
铅笔画算法_第1张图片

1.生成梯度图:

G=(αxI)2+(αyI)2

2.生成线条形状图:

Gi=φiG,i=1,...,8

其中 φi 是线段滤波器,方向为 45i
Ci(p)={G(p),0,if argmini{Gi(p)}=iotherwise

S=i=18(φiCi)

再次利用 φi Ci 进行滤波,并取和。

3.将 S 映射到区间 [0,1] 得到 S′′ ,最终生成的线条图 S=1S′′

4.生成色调图,将原始图像亮度值划分为三个区域:明亮区,暗区和温和区。每个区域使用一种分布去描述该区域的亮度变化。

明亮区:

p1(v)=1δbe1vδb,0,if v1otherwise

温和区:

p2(v)={1ubua,0,if uavubotherwise

暗区:

pe(v)=12πδde(vud)22δ2d

每个像素值对应的概率值为 p(v)=1Z3i=1wipi(v) ,其中 Z 是归一化因子,使得 10p(v)dv=1

其中,每种分布的参数值是通过已有的铅笔画训练得到的,计算公式如下: δb=1NNi=1|xi1| , ua=mm3sm , ub=mm+3sm , ud=md , δd=sd xi 表示铅笔画明亮区域的像素值, m s 表示铅笔画相应区域的像素均值与标准差。

最后,使用直方图匹配得到色调图 J

5.纹理渲染,记 H 为铅笔画风格图,使用 H 拟合 J H(x)β(x)J(x) 。可以通过共轭梯度法求得 β

β=argminβ||βlnHlnJ||22+λ||β||22

最后得到铅笔纹理图:

T=Hβ

6.最终得到的铅笔画可以表示为:

R=ST

效果图

目前自己实现出来的结果没有论文作者的效果好,原因未知,还请有了解的读者指点一二。

原始图:
铅笔画算法_第2张图片
铅笔画:
铅笔画算法_第3张图片
铅笔画算法_第4张图片

原始图:
铅笔画算法_第5张图片
铅笔画:
铅笔画算法_第6张图片
铅笔画算法_第7张图片

原始图:
铅笔画算法_第8张图片
铅笔画:
铅笔画算法_第9张图片
铅笔画算法_第10张图片

参考资料

  1. 《Combining Sketch and Tone for Pencil Drawing Production》(Cewu Lu, LiXu, JiayaJia)

  2. MatLab版本实现-github.com/candycat1992/PencilDrawing

  3. Python版实现-github.com/moonfighting/PencilDrawing–python-version

你可能感兴趣的:(算法)