读书笔记——Painterly Rendering with Curved Brush Strokes of Multiple Sizes

最近对非现实图像处理感兴趣。

在网上翻翻,发现了这篇挺有意思的论文——《Painterly Rendering with Curved Brush Strokes of Multiple Sizes》,作者Aaron Hertzmann。

这篇论文主要描述了一种用计算机模仿人类画油画的算法。该算法用不同尺寸的笔刷以不同的精细程度,从粗到细,层层叠加,最终完成绘画。

算法过程就是用从大到小的笔刷半径循环调用paint()函数

for Ri in R[1:n]; paint(sourceImage,Ri); end;

函数paint

paint函数:以某种半径的笔刷在画布上放置笔划。

算法的伪代码

paint

输入:sourceImage表示原图,Ri表示,从大到小,不同的笔刷半径 1..n。

输出:canvas表示画布。

1. 先使用一个初始颜色铺满画布,为了让笔刷能够覆盖整个画布。因此这个颜色值需要设成一个和图像中所有颜色都足够差异的特殊值MAXINT。

2. 先以笔刷半径乘以一个常参数fσ 为标准差fσ Ri,产生高斯滤波器核,然后用原图卷积高斯滤波器,生成参考图像referenceImage。也就是说,对原图高斯模糊操作后生成参考图像referenceImage。

3. paintLayer() 在参考图像referenceImage与画布canvas有差异的地方,以笔刷半径Ri画上笔划stroke。

函数paintLayer

paintLayer:循环遍历画布,在参考图像referenceImage与画布canvas有颜色差异的网格点【11】,以笔刷半径R画上笔划stroke。

算法的伪代码

paintLayer


输入:参考图像referenceImage,笔刷半径R

输出:画布canvas

1. 初始化一个空笔划集合S,用存储生成的笔划。

2.由difference函数,计算画布canvas与参考图像referenceImage的每个点的“颜色距离”。

|(r1,g1,b1)-(r2,g2,b2)|=((r1-r2)^2+(g1-g2)^2+(b1-b2)^2)^1/2

产生差异矩阵D。

D=abs(referenceImage-canvas)

为了让笔刷能够覆盖整个画布,画布在初始状态时需要设一个和图像中所有颜色都足够差异的特殊值MAXINT。

3.设置网格的长度 grid=fg x R ,网格是正方形

4.以网格长度为步长遍历差异矩阵D,计算网格点(x,y)领域M(x,y)的平均颜色距离误差areaError(x,y)。

areaError(x, y) =∑ i, j∈M(x, y) Di, j/ grid^2

M(x, y)= D(x-grid/2:x+grid/2, y-grid/2:y+grid/2)

5.如果平均颜色距离误差areaError(x,y)大于阈值T,则在领域M(x,y)的范围内颜色距离最大的点(x1,y1)上,以笔刷半径R生成笔划 makeStroke(R, x1, y1, referenceImage)。

6.当画布的所有笔划生成完毕后,以随机顺序渲染到画布canvas上。

上述第5步中的生成笔划方法可以有不同的实现方式,可以简单地在(x,y)以笔刷半径R画圆点,也可以沿图像颜色距离梯度的法线方向画线条。

我们通过 “在具有更多细节(高频信息)的图像区域上使用更小半径的笔刷,在具有少量细节的区域只使用大半径笔刷” 的方法实现聚焦细节的目标。通过这种方法可以选择不同的笔刷半径适配源图像中不同的细节等级。这种选择背后的原因是因为在通常情况下细节区域包含更重要的视觉信息。当然也可以有别的选择,比如强调前景物体或者人物,但这样一来就需要对图像进行语义分析。图像语义分析是机器视觉领域一个非常困难的问题。我们还可以把选择操作交给用户完成【16】。

产生弧形笔划

我们以反锯齿三次B样条曲线为笔划建模,每个B样条包括颜色和厚度(透明度),然后通过圆形笔刷掩膜沿着曲线轨迹渲染笔划。

在我们的系统中,我们约定每一笔笔刷笔划使用不变的颜色,并且使用图像梯度的方向放置笔划。其他作者也使用这个概念【11,8,18】放置笔划。通过不变的颜色可以描出图像的大致轮廓。我们的方法是沿着图像梯度法线方向放置B样条曲线的控制点。当笔划颜色偏离曲线控制点下的颜色超过具体的阈值时笔划在那个控制点结束。可以认为这是使样条曲线和参考图像的等值线大致匹配。

下面更具体地解释一下这个样条放置算法。

我们使用一个控制点列表、一个颜色和一个笔刷半径共同表示一个笔划。

1. 这个算法始于图像中(x0,y0),笔刷半径R。将控制点(x0,y0)加入列表,并且参考图像在(x0,y0)点的颜色设置为这个笔划的颜色。

2. 接下来我们需要计算出曲线上的下一个控制点。

首先计算参考图像的亮度。亮度计算公式:

L(r,g,b) = 0.30r + 0.59g + 0.11b

对参考图像的亮度值进行索贝尔滤波(Sobel-filtered luminance)

然后计算控制点(x0,y0)的梯度方向角

θ0=arctan(Gx0/Gy0)

因为笔划是沿着梯度的法线方向(颜色在梯度的法线方向变化最小),所以需要加上π/2。

θ0+π/2

从(x0,y0)点沿方向角(θ0+π/2)距离笔刷半径R,放置下一个控制点(x1,y1)。

使用笔刷半径R作为两个控制点间的距离是因为R代表着我们能用笔刷捕捉的细节等级。先用大笔刷创建图像的概貌,后续再用小笔刷精雕细刻。

3.重复步骤2计算剩余的控制点。整个过程沿着图像梯度法线方向放置控制点,直到碰到如下两种情况后结束。

a)达到最大的预定义笔划长度。

最大笔划长度是为了防止出现无限循环。

b)参考图像中最后一个控制点位置的颜色与笔划的颜色之差,大于参考图像中最后一个控制点位置的颜色与画布上现有颜色的色差。

笔划的颜色即(x0,y0)点的参考图像颜色。控制点的颜色即控制点所在位置的参考图像颜色,画布上现有颜色即画布上控制点位置的颜色。

另外需要注意,实际上存在两个法线方向,所以下个控制点有两个方向可以选择,θi+π/2和θi-π/2。为了笔划曲率的最小化,我们选择小于π/2的方向角Di。

我们还可以在笔刷方向上使用一个无限冲击响应滤波器,这样可以夸大或者减少笔刷的曲率。使用一个预定义的常量系数fc来控制这个滤波器。

设上一个笔划控制点方向  

D’i-1=(dx’i-1, dy’i-1)

当前笔划控制点方向  

Di= (dxi,dyi)

则 滤波后的笔划控制点方向  

D’i= fc Di+ ( 1- fc )D’i-1= ( fc dxi+ (1- fc )dx’i-1, fc dyi+ (1- fc ) dy’i-1)

算法的伪代码

makeSplineStroke

输入: 笔划的起始点位置 (x0,y0),笔刷半径R,参考图像

输出:笔划样条曲线控制点列表

其中最小笔刷长度是为了防止出现非常短的笔划引起斑点现象。

渲染曲线笔划

先用细分方法(subdivision)计算样条曲线,然后用一个反锯齿圆形掩膜沿着曲线路径绘制。

渲染风格

为了量化表征绘画风格,建议使用风格参数控制渲染过程。

在上述算法中用到的一些参数:

近似阈值 T —— 值越大产生的图像越粗糙。

笔刷尺寸 —— 除了定义笔刷列表 (R1:Rn)之外,还可以定义 最小笔刷R1、笔刷尺寸变化律Ri+1/Ri,笔刷数n。

曲率滤波器系数 fc ——用于控制笔划曲率

模糊因子 fσ —— 控制模糊核的尺寸

最小和最大笔划长度 minLength、maxLength ——以控制点个数为单位

不透明度α——设置绘画的不透明度,范围0-1 之间

网格尺寸 fg——控制笔划之间的空隙

颜色抖动 系数 —— jh,js,jv或者jr,jg,jb表示在 H,S,V 或者 R,G,B 分量中加入随机抖动

0表示没有抖动。

不同的系统设置形成不同的风格

印象派——正常的画风。无曲率滤波,无随机色

T= 100,R=(8,4,2),fc=1,fs=.5, a=1,fg=1, minLength=4, maxLength=16

表现派——细长的笔划,加上颜色抖动。

T= 50,R=(8,4,2),fc=.25,fs=.5, a=.7,fg=1, minLength=10, maxLength=16,jv=.5

水彩——松散、半透明的笔划,随机抖动

T= 200,R=(8,4,2),fc=1,fs=.5, a=.5,fg=1, minLength=4, maxLength=16,jr=jg=jb=.3

点点——以随机色调和饱和度密集画圆点

T= 100,R=(4,2),fc=1,fs=.5, a=1,fg=.5, minLength=0, maxLength=0,jv=1,jh=.3.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容