Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

18 六种笔

✅ 已验证line 🧪) · 代码 code/strokes.py

每种笔对应参考画里肉眼可见的一类痕迹。表里的 preset 和笔数是 paint 风格(第 20 章)的实测值。

干什么preset收尖笔数(paint)
wash平涂铺满,不看误差b) Airbrush Soft~12k(只有背景)
soft把色阶之间的台阶揉开b) Airbrush Soft~27k
hatch短平行排线c) Pencil 1 Sketch (mypaint)~190
strand沿形体流向的收尖长笔c) Pencil 1 Sketch (mypaint)~2.7k
detail多尺度贪心补差c) Pencil-3 Large 4B~39k
line色トレス线稿(从轮廓曲线生成)c) Pencil 1 Sketch (mypaint)0(anime 风格约 1.2k)

wash 平涂

按固定间距把整块区域来回扫满,三个角度各一遍。用在纯渐变上——误差驱动的笔(soft / detail)在平滑渐变上会留空隙:误差一降到阈值以下就不再起笔,笔与笔之间没铺到的地方露出底色。背景辉光就是这么变成一片黑斑的。

一条扫线要拆成短段逐段取色seglen=2.2·R)。整条一个颜色的话,一笔从画面中心的亮处扫到角落的暗处只带一个色——背景变成一片交叉错色扫痕,最暗的角落被抬亮((0,0,0) → (6,0,1))。

soft 柔和过渡

大号 airbrush,低透明度(0.22 / 0.18),两个尺度。种子按 R 大小的格子取(每格一个,误差 > T 才起笔),沿等色线生长(亮度梯度的法线),Hertzmann 的收笔判据:画布已经比这支笔更接近参考就停。

笔径跟着色阶格的大小走:R = min(13, max(0.30·等效半径, 2))。固定半径会让小色块被一笔糊掉——一支直径 200px 的笔盖在 300px 宽的阴影上,那块阴影就没了。

hatch 排线

短平行线。方向由整块区域的主梯度定,不是逐点定——逐点定会变成一团乱麻;参考画腮红上那片斜线是一致方向的。主方向用双角平均(atan2(mean sin 2θ, mean cos 2θ)/2)避免 +d / −d 互相抵消。只在 HATCHY 部件的非 Flat 色阶上。

strand 发丝

沿形体流向的收尖长笔,只在 STRANDY 部件。颜色顺着局部明暗推开 contrast=14(发丝要比它盖住的地方更亮或更暗,否则看不见)。

这是「8K 比参考画多出来的 3.3 倍细节」的主要去处:1x 的 origin 里没有这么细的丝,但流向是它给的。点列要狠简化到 ≤ 9 个点——收尖只能逐段 paintLine,34 段和 8 段撑出的是同一条曲线,调用次数差 4 倍。

detail 细节

Hertzmann 1998 的多尺度贪心:从粗到细(R = 6 → 3 → 1.5),每级把参考图按笔刷尺度模糊,在误差 > T 的格子里起笔,沿等色线生长。

opacity 0.6 而不是 1.0:结构已经由矢量色阶层给定了,这一层只该补质感。不透明的粗笔会把色阶结构整片盖掉(第一版就是这样,五官被抹平)。最细停在 R=1.5——继续加细只把 PSNR 从 27.8 抬到 28.0,却要多花两倍的笔。

line 线稿 🧪

已有的轮廓曲线生成色トレス线稿:沿贝塞尔走,取内侧的颜色压暗(darken=0.72),分段落笔。取内侧而不是线上:线正压在两侧颜色的过渡带上,取到的是混合色,压暗后发灰。

不去源图上找暗脊——那条路(lines(),局部 max_filter − lum > 18)在色トレス图上是失败的:抓到的 18% 主体像素其实是明暗过渡,v3 实测强行描线掉 10 dB。

不逐段收尖:一条连续的轮廓线被切成很多段,每段两头都收尖会画成一串虚线。段与段共用端点,不收尖也接得上;手绘感靠半径的轻微抖动给。

只在 anime 风格开启。跑过两轮,线出来了但还不好看(太粗、太重的一版把荷叶边画成一串香肠)。

落盘前简化点列

点数 = API 调用次数。 生长出来的点列按 step=R 密排,R=1 时逐像素。_mk() 落盘前用 RDP(eps = max(0.35·R, 0.4))简化。理由在第 19 章