ColorYourModel logoColorYourModel Docs
GitHub ↗

智能分区(Intelligent Segmentation)设计 · 初版方案(待 REFUTE)

迭代目标(来自用户):实现"真正理解特征"的多算法可配置分区;参考切片引擎与图形学找轮廓; 做 3D 或 3→2→3 的真实特征识别;提供用户微调能力;以 golden samples 为验收标准。 本文件为 PLAN 阶段初版,尚未实现。下一步交给对抗子 agent 证伪。

0. 现有基础(来自代码调研,file:line 见 agent 报告)

  • segment/mod.rs 仅 4 行 pub mod,无统一 trait / 抽象 —— 多算法调度的天然空位。
  • 已有两个 auto 命令:auto_segment(dihedral,segment/dihedral.rs:75)、auto_segment_smart(SDF,sdf.rs:339)。
  • 签名不统一:segment_by_dihedral_angle(mesh, f32, &ProgressFn) vs segment_by_sdf(mesh, u32)(无 progress)。
  • 真实 bug:sdf.rs:30-72 的 consistent_normals 会永久改写 mesh.normals;之后若再跑 dihedral,法线已被翻转 → 多算法串联会污染。
  • SegmentResult(commands/segment.rs:22-28)已是通用返回体;前端 updateSegmentLabels / aSegLabel shader 高亮 / SegmentsPanel 零改动即可复用。
  • 不变量:算法必须写 mesh.segment_labels(长度==faces.len())并 rebuild_segments();自动分割后 mesh.history.clear();auto 标签 < MANUAL_SEGMENT_OFFSET(100_000);label 0 是合法分区。
  • 测试现状:dihedral 0 测试;sdf 5 个;manual 9 个;无 tests/ 目录(全内联 #[cfg(test)])。
  • 依赖:nalgebra 0.33、petgraph 0.6、kiddo 4、stl_io 0.7(仅 STL)。无 OFF/OBJ loader,无 parry3d。

1. 统一接口(最小改动集)

segment/mod.rs 新增:

pub enum SegmentationAlgorithm {
    Dihedral { angle_threshold: f32 },          // 现有,包一层
    ShapeDiameter { k: u32, cone_rays: u32, cone_half_angle: f32 }, // 现有 sdf,补 progress
    CurvatureKMeans { k: u32, smoothing_iters: u32, use_sdf: bool }, // 新增
    MultiView { views: u32, grid_res: u32, normal_tol: f32 },        // 新增 3→2→3
    // ConcaveDecomp { .. }  // 推迟(需 parry3d/V-HACD,重依赖)
}

pub fn run_segmentation(
    mesh: &mut MeshModel,
    algo: &SegmentationAlgorithm,
    on_progress: &ProgressFn,
) -> Vec<Segment>;
  • 两个旧命令保留(参数透传),新增 auto_segment_v2(algorithm_json, params_json) 复用 SegmentResult。
  • ProgressFn = dyn Fn(f32, &str) + Send + Sync(沿用 loader.rs:6),所有算法必须 emit 进度(修 SDF 无进度)。

2. 算法 A:Dihedral(保留现有,仅包接口)

dihedral.rs 不动逻辑,仅让 run_segmentation 调用它。默认 angle_threshold=30.0 收口到一处(消除 useTauriCommand.ts:41 / Toolbar.tsx:89,105 三处硬编码)。

3. 算法 B:ShapeDiameter(改进现有 SDF)

  • 给 segment_by_sdf 加 on_progress,分 4 阶段 emit(锥形射线 / 空洞插补 / kmeans / 凹度合并)。
  • 修副作用:consistent_normals 改为不写回 mesh.normals(返回 oriented 副本供 SDF 内部用),避免污染 dihedral 的后续调用。
  • 凹度合并阈值 0.93 提为命名常量 SDF_CONCAVITY_DOT。
  • 性能:删除 sdf.rs:387 在区域对循环内重复遍历 edge_references() 的 O(clusters²×E) 路径(改为预构建 RAG,与 dihedral 同构)。

4. 算法 C(新增):CurvatureKMeans —— 几何/曲率特征聚类

动机:dihedral 只看二面角(平/曲),无法区分"厚装甲板 vs 细肢体""凸球面 vs 平面"。SDF 是厚度特征。把多特征联合聚类才能"理解特征"。

  • 逐面特征向量(全部归一化到 ~[0,1] 或 z-score): f = [mean_curvature, gaussian_curvature, |SDF|, normal·principalX, normal·principalY, normal·principalZ]
    • 曲率用离散 Laplace-Beltrami(nalgebra 构造 cotangent 权重 Laplacian,mesh.normals + face_adjacency)。
    • 主方向用模型级 PCA(nalgebra SymmetricEigen)固定全局坐标系 → 法线投影稳定。
  • 可选 smoothing_iters:Laplacian 平滑法线/曲率后再聚类(抗 STL 噪声;survey 指出曲率对噪声敏感)。
  • K-means(Lloyd,20 轮,k-means++ 初始化:k 由用户配置,默认 6)。
  • 连通性保证(关键):纯 K-means 会产生空间不连通的"碎片簇"。后处理:用 face_adjacency 做区域邻接图(RAG),对每对相邻、但被分属不同簇的面,按"特征距离 + 边界长度"贪心合并小簇到大邻居(与 dihedral 的 normal_consistency_merge / merge_small_regions_fast 同构,复用其框架)。最终每个 label 是连通分量,匹配人类"部件"语义。
  • 阈值出处:合并 dot 阈值沿用 dihedral 的 MERGE_NORMAL_DOT_THRESHOLD=0.93(≈22°),与现有行为一致;smoothing_iters 默认 1(轻量)。

5. 算法 D(新增):MultiView 3→2→3 —— 多视角投影分割

动机:用户明确说"先 3→2,处理,再 2→3"。切片引擎(Orca/Prusa)靠"可见性 + 投影"做支撑/接缝绘制;SAMesh(2024) 用多视角渲染→SAM→回投→图社区检测得到部件分割。我们做经典版(无 SAM/PyTorch,纯 Rust):

  • 投影(3→2):取 views 个相机(PCA 对齐后沿包围球均匀分布,如 6 或 12 方向;用 nalgebra 构造正交投影矩阵)。逐面质心投影到 (u,v),记录 depth(沿视线)、face_normal、所属面 id。
  • 2D 分割:对每个视角,把面按 (u,v) 落到 grid_res×grid_res 栅格;仅最近深度面占据该栅格单元(解决自遮挡歧义)。在同一单元及 8-邻域内、且法线夹角 < normal_tol 的面聚为同一 2D 区域(连通分量标记)。
  • 回投+融合(2→3):每个面获得一组"各视角 2D 区域 id"。构建面图:若两面在任一视角同属一个 2D 区域则连边;对该图做 union-find / 轻量社区检测(petgraph)得到最终 3D 部件。
  • 为什么有效:平面装甲板在多视角下投影稳定成大片连通 2D 区;球面在每个视角是圆盘;分叉肢体在多数视角被"颈"分开 → 多视角融合自然切出部件。与 SAMesh "render→2D mask→match graph→community detection" 架构一致,只是 2D 前端从 SAM 换成经典连通分量。
  • 理论风险(待 REFUTE):薄特征在少数视角被遮挡 → 该视角无标签;靠多视角覆盖 + 融合缓解。栅格分辨率与 normal_tol 是需调的旋钮。

6. ConcaveDecomp(V-HACD)—— 推迟

  • parry3d 的 V-HACD 是"近似凸分解",概念上最贴近"把模型拆成可制造的部件(球体/护甲片)",但引入 parry3d 是重依赖(simba/crossbeam/大量几何代码),且 vhacd-rs 绑定陈旧(2017)。
  • 决定:本轮不做,列入 backlog;若后续要"工业级部件分解"再单独评估(可能用 vhacd-rs 子仓库或自研体素分解)。

7. 用户微调交互(前端)

  • 新增 IntelligentSegmentPanel(参考 BrushSettings.tsx 的 docked 面板样式 + appStore 的 brushRadius 持久化模式):
    • 算法 <select>(Dihedral / ShapeDiameter / CurvatureKMeans / MultiView)。
    • 动态参数滑块:角度(dihedral)、k/rays( SDF)、k/smoothing(Curvature)、views/grid/tol(MultiView)。
    • 运行按钮 → invoke("auto_segment_v2", {...})。
  • 微调能力:分割后在 SegmentsPanel 支持"合并选中分区""拆分选中分区(按连通分量)""重命名";并可调参后一键重跑(mesh.history.clear() 已处理撤销)。
  • 交互形态:用户说"弹窗或直接切视口都行" → 采用 docked 可折叠面板 + 高级参数 popover(非强制模态),与现有工具栏风格一致;不引入独立视口切换以免破坏 R3F 渲染状态。

8. 验收标准:Golden Samples + PSB 指标(诚实评估,非假满分)

  • 新增最小 OFF loader(mesh/load_off.rs,OFF 是纯文本、约 40 行):用于加载 PSB 黄金样本。
  • Golden samples:尝试从 Princeton Segmentation Benchmark 下载若干(19 类、人工 GT);若沙箱下载受限,则确定性合成几个带已知 GT 的模型(双球融合=2 部件、球+盒、类人形)并明确标注为 synthetic。两者都进 examples/golden/。
  • PSB 指标实现(segment/metrics.rs):
    • Rand Index(聚类一致性)
    • Boundary Precision / Recall / F1(边界匹配,最关键,人类"在哪切")
    • Segmentation Consistency(对多份 GT 取均值,抗单一 GT 偏差)
  • 验收测试(#[cfg(test)] 或 tests/accuracy.rs):每个算法跑 golden samples,打印并断言 Boundary-F1 ≥ 基线(基线由各算法在样本上的实测值回填,绝不预先拍脑袋写死通过阈值)。报告真实数值,不返回"满分"掩盖退化。
  • 离线 E2E 无法跑 Tauri 渲染,但 Rust 分割逻辑 + 指标可 cargo test 全绿;视觉验收仍由用户 cargo tauri dev 完成。

9. 理论缺口清单(提交 REFUTE 的重点)

  • G1 连通性:K-means/Curvature 必产生不连通碎片,靠 RAG 合并;合并阈值拍错会过/欠分割 → 阈值需有出处 + 测试覆盖。
  • G2 曲率噪声敏感:STL 噪声下曲率失效 → 需平滑,但平滑会抹掉真实锐边 → 迭代次数旋钮 + 默认保守。
  • G3 MultiView 遮挡:薄特征单视角丢失 → 多视角 + 仅最近深度占格;views/grid_res/normal_tol 需调参协议。
  • G4 重依赖:V-HACD 推迟,不阻塞。
  • G5 假满分风险:golden GT 必须真实;synthetic 明确标注;指标阈值由实测回填,禁止 !has_gt → 100。
  • G6 SDF 副作用 bug:先修 consistent_normals 不写回,否则多算法串联崩。
  • G7 dihedral 递归 find 爆栈:超大网格风险,改为迭代式(backlog,本轮若顺手可修)。
  • G8 seg_log() 写源码目录:发布版会写文件,清理(backlog)。

10. 实施分阶段(最小改动优先)

  1. 修 SDF 副作用 + 补 progress + 提常量(前置 bugfix,独立提交)。
  2. 统一接口 SegmentationAlgorithm + run_segmentation + auto_segment_v2(行为不变,独立提交)。
  3. CurvatureKMeans(新算法 + 连通性合并 + 测试)。
  4. MultiView 3→2→3(新算法 + 测试)。
  5. OFF loader + golden samples + PSB 指标 + 验收测试。
  6. 前端 IntelligentSegmentPanel + SegmentsPanel 微调(合并/拆分)。
  7. 收口三处 30.0 硬编码;清理 seg_log。

每步带测试,全套 cargo test 报告 "X/X(原 N + K)"。


99. REFUTE 结论与修订(对抗子 agent,2026-08-09)

子 agent 返回 7 个 blocker。逐条处置:

# Blocker 修订 / 处置
1 SDF 性能误诊:真瓶颈在 sdf.rs:172-174 kdtree 查询半径=全 bbox 对角线且放在射线循环内 → O(12·n²);:387 处的 edge_references() 只是 k²·E≈3e8,差 5 个数量级 改:候选查询提出射线循环、且改用 nearest_n(K) 有界候选(SDF_CANDIDATE_K=512),成本降至 O(n·K·rays)。原 :387 全图重扫改为预构建 RAG(与 dihedral 同构)。
2 §4「RAG 贪心合并保证每个 label 连通」逻辑不可达:合并是单调运算,永不产生连通性 改:先对每个 k-means 簇做连通分量拆分(BFS over face_adjacency),再做小分量按特征距离合并。合并判据用特征欧氏距离,不复用 dihedral 的 0.93(语义不同:区域平均法线 dot f64 vs 边界二面角 cos f32,且是 private const)。
3 §5 MultiView 融合算子方向反了:「任一视角同区即并查集连边」+ union-find 单调坍缩 → 视角越多越合并,传递闭包大概率并成 1 块;petgraph 0.6 无任何社区检测 砍掉本轮。正确版需带权 matching graph + 可切割算法(normalized cut / Louvain 自研),非最小改动。列入 backlog,附正确设计(见 §11)。用户说"或者 3→2→3",3D 特征聚类(C+D)已满足"真实特征识别"。
4 §5 栅格占格 → 单例爆炸:多数面在所有视角无标签 → 各自成 label,击穿 MANUAL_SEGMENT_OFFSET=100_000 命名空间 随 §5 砍掉而消解;若未来做,必须 cap label 数 < 100_000。
5 标签命名空间被击穿:rebuild_segments 会把 ≥100_000 的 label 当手动分区改名+随机上色 CurvatureKMeans 最终 label 数 = 最终连通分量数(k 小 + 小分量合并)→ 远 < 100_000;加断言守卫。
6 §4 引入随机性(k-means++ 需 rand,但 Cargo.toml 无 rand;现有 kmeans_1d 明确 Deterministic)破坏确定性 → §8 断言 flaky 改:用确定性最远点播种(max 两两特征距离选种子,survey 提及),无 rand 依赖。
7 §8「基线由实测回填 + 断言 ≥ 基线」= 构造性绿灯(假满分换皮);synthetic 双球/球+盒对 dihedral/SDF 平凡可分 → 四算法全 ~1.0,零区分度 改:阈值来自外部公开 PSB 基线(论文报告值)而非自测回填;synthetic 仅作 smoke(断言"切出正确部件数"这种非平凡拓扑事实,非假满分);GT 缺失时测试 skip/fail,绝不计分。Rand 用列联表公式。

其他 major 处置

  • "凹度合并"名不副实:sdf.rs:395 的 acos(dot) 无符号,分不出凸/凹;§3 把 0.93 命名为 SDF_CONCAVITY_DOT 会把错误固化 → 不命名常量,保留字面量并加注释说明其语义边界。
  • "复用 dihedral 框架"不成立:normal_consistency_merge/merge_small_regions_fast 是 private 且合并判据仍是法线 dot,曲率特征在合并阶段被丢弃 → CurvatureKMeans 不调用 dihedral 私有函数,自写"连通拆分 + 特征距离合并"。
  • PCA 特征非确定:主轴符号 ±、特征值简并(球/立方体)→ normal·principalXYZ 随机翻转,等于按朝向聚类 → 特征向量剔除法线方向,只用 [曲率, |SDF|, 凸性] 内在描述子。
  • SDF 副作用修复会静默改行为:consistent_normals 不写回却不透传副本 → segment_by_sdf_block_with_plate 漂移 → 改:consistent_normals→oriented_normals(mesh)->Vec 不写回;compute_sdf/segment_by_sdf 各自本地持有 oriented(新增 compute_sdf_inner(mesh,&oriented)),compute_sdf 的 pub 签名与返回不变,测试不受影响。
  • "一键重跑"毁数据:history.clear() + 全量覆盖 labels,但 face_colors 保留手动色 → 颜色/标签失配且不可撤销 → 前端层面提示"重跑将清除手动分区",后端重跑前 backup 当前 labels(backlog,本轮先不阻断)。
  • §8 指标命名:PSB 官方为 Cut Discrepancy / Hamming / Rand / Consistency Error;Boundary-F1 是派生代理,标注清楚。
  • OFF loader「40 行」低估:需 .seg GT 解析 + 面序对齐 + 复刻 build_mesh 全套前置 → 本轮不写 OFF loader;golden samples 用确定性合成 STL(双球/球+盒/类人形)写入 examples/golden/,并保留"掉落真实 PSB .off 即自动启用"的挂接点。

11. MultiView 3→2→3 的正确设计(backlog,本轮不做)

若未来做,必须:

  1. 每个视角:面质心正交投影到 (u,v),记录 depth + 2D 区域 id(仅最近深度面占栅格)。
  2. 构建带权 match graph:边权 = 两面在多少个视角同属一个 2D 区域(≥T 视角才连边,T≥2,避免单视角巧合合并)。
  3. 用可切割算法(normalized spectral cut 或自研 Louvain)切分,不是 union-find(union-find 单调不可切)。
  4. 工业级替代:parry3d 的 V-HACD 近似凸分解(重依赖,单独评估)。

12. 实现状态(2026-08-07)

后端(已全部落地,b087c3c)

  • §1 统一接口 SegmentationAlgorithm(serde 内部标签枚举,camelCase,契约由 serde_wire_format_is_stable 锁死)+ run_segmentation + auto_segment_v2 命令。
  • §2 Dihedral、§3 ShapeDiameter(补 progress + 修 consistent_normals 不写回 mesh.normals 的副作用)、§4 CurvatureKMeans(确定性最远点播种 + 连通拆分 + 特征距离合并)。
  • 共享后处理 postprocess.rs:split_connected_components 沿棱角切割(特征∩棱角 交集,根治"uniform 场聚一类"),merge_smooth_boundaries(coplanar 必溶解 + 特征间距护栏),min_region_faces(n)(低面数模型不死坍),finalize_segments。
  • 验收:golden-sample harness 抓出 5 个真实 bug(cube 均匀场、SDF 噪声放大、共面对角、非传递 union、低面数溶解);cargo test --lib 74 passed / 0 failed。拓扑断言:cube→6(curv 双变体)、single_sphere→1(四算法)、two_spheres→2(四算法);golden_eval 曲率(SDF) vs GT:Rand=1.000 / Boundary-F1=1.000 / Hamming=0.000。

前端(本轮落地)

  • §7 IntelligentSegmentPanel 已实现,但形态为模态(沿用 ExportDialog overlay/dialog)而非原草案的 docked 面板——模态更低侵入、与 appStore persist 模式一致;算法集为 dihedral / shapeDiameter / curvatureKMeans(MultiView 按 §11 推迟)。
  • 收口 §2 / §10.7 三处 30.0 硬编码:导入自动分区改走 autoSegmentV2(buildAlgorithm(持久化 or 默认 dihedral 30°, 参数));旧 autoSegment / autoSegmentSmart 钩子退役。
  • appStore 持久化 lastAlgorithmParams(sanitizeAlgorithmParams 值域校验)+ lastSegmentKind;tsc --noEmit 通过。

验收结论

  • 诚实评估:后端 golden 拓扑断言全绿;但视觉/交互仍须需求方 cargo tauri dev 手动复验(headless 无 Tauri runtime,依赖 IPC invoke 的模型加载/分区无法自动化)。
  • 推迟项(backlog):MultiView 3→2→3(§11)、OFF loader + PSB 真实样本、SegmentsPanel 合并/拆分微调、dihedral 递归→迭代、重跑前 labels 备份。
On this page