14 接缝
✅ 已验证
部件各自独立矢量化,边界曲线不会正好贴合。接缝处会漏出底色——底是纯黑,所以是一串黑点或黑线。这一章讲三条解法,以及一条走错的路。
走错的路:partition of unity
很自然会想到给相邻部件按覆盖率分配 alpha:alpha_i = cov_i / Σcov,接缝处两边各 0.5,加起来正好 1。
Krita 是 alpha-over 合成,不是加权和。 两层各 0.5 叠出来会留下 (1−0.5)×(1−0.5) = 25% 的背景。纯黑底上就是一串黑点。
正确做法和画师铺色一样:每个部件自己不透明,并向邻居底下多铺几像素,靠遮挡顺序让上面的盖住下面的。
一、Flat 向外扩 0.6px
contour.trace(..., expand=0.6):取 −0.6 等值线而不是 0,等于把 Flat 的轮廓向外推 0.6 个 1x 像素(8x 上约 5px)。
躯干那一块(部件交界最密)实测:
| expand | 漏底(主体像素) | 溢出(剪影外) |
|---|---|---|
| 0.0 | 0.935% | 0.077% |
| 0.3 | 0.595% | 0.177% |
| 0.6 | 0.410% | 0.260% |
| 1.0 | 0.240% | 0.347% |
漏底压了一半多,代价是剪影外鼓出一圈。
二、部件组 clip 到剪影
鼓出来的那圈由第二条解法切掉:04_Color 组底放一条主体剪影矢量,每个部件组 setInheritAlpha(True)。部件可以随便涂出界,剪影仍然由那一条曲线精确定义。依据是第 13 章第二条。
只有色阶组的 Flat 用 expand,其余色阶不扩——它们的邻居是同部件的另一档,嵌套结构(第 6 章)保证上层盖下层,本来就没缝。
三、背景铺满整幅
背景辉光原来只铺「主体之外且有辉光」的区域,误差驱动的种子在平滑渐变上留空隙,而且剪影周围一圈没铺到——剪影和部件轮廓差一点点就漏黑边。
改成铺满整幅画布、放最底层:主体那一块被上面的部件组盖住,天然不会露。主体挡住的那块辉光从外面外推出来(_blur(bg, 24, mask=~subject) 归一化卷积)。改完低频 likeness 从 21.7 dB 升到 33.6 dB,全图最暗像素回到 (0,0,0)。
这也是画师的顺序:先把背景整个铺完,再在上面画人。
细长条会被平滑吃掉
一个相关的坑,来自旧路线但现在仍适用:高斯平滑 SDF 时,1–2px 宽的细条会整条变成负值 → 覆盖率 0 → 什么都不画 → 黑底透出来。实测 (x=201, y=283):origin (254,247,225),画成 (4,2,1)。
逐部件的面积判据抓不到——丢几根细丝对 9 万像素的部件不到 0.5%,视觉上却是一串黑洞。修法是让平滑只许改形状不许吃内部:sdf = where(sdf ≥ 1, max(smoothed, sdf), smoothed)(code/upsample.py)。contour.trace() 的 smooth=0.8 比旧的 1.2 小,也是为了这个。