File size: 4,633 Bytes
b9afccb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515a447
 
 
 
6aca7ac
 
 
515a447
6aca7ac
 
 
 
 
b9afccb
 
 
 
 
 
 
 
 
6aca7ac
 
 
 
 
 
 
 
 
 
 
 
 
878a590
515a447
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
---
license: cc-by-4.0
tags:
  - mesh-segmentation
  - part-segmentation
  - point-cloud
  - vegetation
  - onnx
  - 3d
  - qtmesheditor
library_name: onnx
pipeline_tag: other
---

# QtMeshEditor β€” Vegetation Part Segmentation

A point-cloud part-segmentation network (PointNet++-style) that labels each
point of a **tree / plant** mesh as `trunk`, `branch`, `foliage`, `root`, or
`flower` (fruit), exported to **ONNX** for local inference via ONNX Runtime.

One of the category-specialised segmentation models built for
**[QtMeshEditor](https://github.com/fernandotonon/QtMeshEditor)** (epic #818,
Track B2) β€” a free, open-source 3D mesh & animation editor. The app
auto-detects the mesh category with a companion
[point-cloud classifier](https://huggingface.co/fernandotonon/QtMeshEditor-mesh-segmentation-category)
and dispatches to this model for vegetation; the
[body model](https://huggingface.co/fernandotonon/QtMeshEditor-mesh-segmentation)
covers characters, with
[vehicle](https://huggingface.co/fernandotonon/QtMeshEditor-mesh-segmentation-vehicle)
and
[building](https://huggingface.co/fernandotonon/QtMeshEditor-mesh-segmentation-building)
siblings. The aggregate download source used by the app is
[QtMeshEditor-models](https://huggingface.co/fernandotonon/QtMeshEditor-models)
(`segment/meshseg_vegetation.onnx`).

## Model

- **Input:** a sampled point cloud `float32 [1, N, 3]` (normalised to a centred
  unit box; +Y up).
- **Output:** per-point class logits over 6 channels
  (`unknown, trunk, branch, foliage, root, flower`); argmax β†’ label, scattered
  back to mesh vertices/faces by nearest sampled point.
- **Architecture:** shared per-point MLP + two kNN local-aggregation blocks
  (in-graph `cdist`+`topk`, ONNX-exportable) + a global max-pooled feature;
  ~0.78 MB. Trained at the app's inference sample size (4096 points).

## Training data & license

Trained **from scratch, 100% on procedurally generated synthetic trees we
own** (no third-party data at all): parametric broadleaf / pine / palm /
dead-tree / bush regimes with surface-sampled capsule trunks and branches,
canopy-vs-per-tip foliage blobs, surface roots, and flower/fruit clusters β€”
labels are exact by construction. Weights released under **CC-BY-4.0**;
please credit *QtMeshEditor*.

## Evaluation

- Held-out synthetic validation accuracy: **93.3%** (v1.1 β€” a harder
  big-canopy / drooping-oak distribution; v1.0 scored 93.8% on the narrower
  set), per-point, unknown masked. Real-world CC0 vegetation packs are the
  planned next data slice (mined via material/submesh-name labels).
- Per-class recall on held-out synthetic trees (v1.2 β†’ v1.3):
  branch 0.58 β†’ **0.92**, root 0.57 β†’ **0.80**, trunk 0.71 β†’ 0.79,
  foliage 0.94, flower 0.78; overall 0.85 β†’ **0.92**.
- Real-world check (stylized oak FBX, huge low canopy + stubby trunk):
  v1.0 mislabelled ~63k canopy verts as trunk β†’ v1.3 gives trunk 4.5k,
  branch 16.6k (full skeleton through the canopy), **root 0** (this oak
  models no root β€” correct), foliage intact. Root/trunk on real meshes
  stays the hardest class β€” the durable fix is the planned CC0
  real-vegetation data slice.

## Reproducing

`scripts/export-meshseg-onnx.py --category vegetation` in the QtMeshEditor
repo (one-time, offline; the app never runs Python). Strategy + roadmap:
`docs/MESH_SEGMENTATION_STRATEGY.md`.

## Versions

- **v1.2.0** (current) β€” root/trunk/branch balance:
  - roots appear in only ~20% of trees (most real tree meshes model no roots β€”
    they're underground) and, when present, are thick / buttress-like /
    strictly ground-hugging (not twig-thin);
  - a new trunk base FLARE is labelled trunk so a widening base isn't read as
    root;
  - branches are strengthened β€” more primary branches, sub-branches that thread
    up into the canopy, and 3Γ— branch sample weight β€” so the trunk/root
    tightening doesn't eat branch recall.
  Net on the real oak: root over-prediction gone (1980β†’0 for a rootless tree),
  branch skeleton recovered (3k→16.6k verts), trunk tightened to the real trunk
  (10k→4.5k). Held-out branch recall 0.58→0.92, root 0.57→0.80, overall
  0.85β†’0.92.
- **v1.1.0** β€” big-canopy robustness: added an `oak` regime
  (stubby trunk, canopy 1.1–2.2Γ— larger, foliage drooping down around/below
  the trunk top with a low skirt) and solid-VOLUME canopy fill (real leaf-card
  canopies are dense volumes, not the hollow shells v1.0 trained on). Fixes
  the verified real-world failure where a stylized oak's low canopy was
  labelled trunk.
- **v1.0.0** β€” initial synthetic-only release (#818 Track B2).