4 语义分割成部件
✅ 已验证 · 代码 code/segment.py · 入口 trace_prepare.py 顶部
目标
把 origin 切成十几个有名字的部件:头发、脸、躯干、裙子、丝带……每个部件之后会成为 .kra 里的一个组。这是全流程的第一刀,切错了后面全错。
边界屏障法,不是颜色分类
三种「按颜色分」的路子都试过,都错:
| 方法 | 错在哪 |
|---|---|
| 逐像素 HSV 规则 | 发梢的粉色判成皮肤 |
| 区域均值色 | 整头头发判成皮肤 |
| 加金色先验 | 小腿高光吞进头发 |
原因很简单:一个部件内部的颜色变化(头发从金到粉的渐变)常常比部件之间的差别还大。
segment.regions(img, thr=25, win=7, min_px=300) 走的是另一条路:先找边界(局部对比超过阈值的地方形成屏障),再把屏障围出来的连通区域各自编号。头发内部金→粉是平滑渐变,不构成屏障,天然不会被切开。产出是一张区域标签图和每个区域的 bbox / 中心 / 面积。
区域 → 部件:一张手工核对的表
regions() 切出来的是几十个无名区域。把它们归到部件靠 trace_prepare.py 顶部的 ASSIGN 表:
ASSIGN = [
("Hair_Back", [5, 26, 30, 32, 25]),
("Skin_Leg_L", [58]),
...
("Hair_Front", [2, 3, 6, 1]),
]
顺序 = 底→顶 = 遮挡顺序。 后面的部件盖住前面的,所以 Hair_Front 在最后。
这张表是对着 atlas.png(区域伪彩图 + 编号)目视核对写出来的,换一张图必须重做。没有被分配到的区域会并入空间最近的已分配部件。
本书用的 origin 分成 15 个部件:
Hair_Back Skin_Leg_L Skin_Leg_R Skin_Foot Shoe Skin_Torso Skin_Arm Skin_Face
Dress_Bodice Dress_Skirt Dress_Frill Ribbon_Waist Ribbon_Hem Ribbon_Hair Hair_Front
部件之后的两个集合
同在 trace_prepare.py 顶部:
STRANDY = {"Hair_Back", "Hair_Front"} # 哪些部件长发丝
HATCHY = {"Skin_Face", "Skin_Torso", "Skin_Arm", "Skin_Leg_L", "Skin_Leg_R"} # 哪些排线
它们决定第 18 章里 strand 和 hatch 两种笔落在哪。也是换图要改的。