Two isolated experiments: (A) hard-structure instance reject — a tree instance whose hard-blob share exceeds 0.6 is rejected instead of kept (r3pr vs r2); (B) per-segment TCS ground — SMRF ground classified once on the union of all records of a segment instead of per record (r3 vs r3pr), the behaviour you asked for.
A = keep. Exactly 4 tree instances are rejected on 4 segments, all four are pure structure (mrf 0.005–0.048), M3 hard contamination goes 23 cells / 41 187 pts → 10 / 29 769, and canopy recall, the 12 truth spots and the 085 GT numbers are bit-identical to r2.
B = not shippable yet. It loses a real 018 sign on a 27 mm z_ground shift, M3 gets worse than r2 (17 cells / 68 142 pts), the 060 billboard is re-painted green, and a tile-shaped hole is bitten out of a truth crown.
B does win where it matters most for you: 085 human-GT tree recall 0.755 → 0.887 (27 349 new GT-tree points) and a genuine new scrub belt on 060 — so the idea is right and the implementation is not.
Root cause found: the segment-wide min-Z seeding keeps only 0.37–0.75 of the ground points (low-noise density scales with the number of overlapping passes), so the DEM (Digital Elevation Model, the per-cell ground surface) tail is biased down to −8 m and turns road into candidates. Default set back to off; fix planned = noise-robust (supported) min-Z seeding.
0. How to read the renders
Every render is one spot in the raw no-scan-angle-filter cloud, 6 columns left to right:
true RGB | number_of_returns (grey = 1, orange = 2, red = ≥ 3) | BASE paint | r2 paint | r3pr paint (per-record TCS, = experiment A) | r3 paint (per-segment TCS, = experiment B).
Top row oblique, bottom row the same points top-down; each column is labelled in the image itself.
unmaskedtreemedium_vegetationsign-ish (sign / pole / delineator)guardrailother
Click any image for full resolution; ← / → (or swipe) step through the images of that card only; Esc closes.
4 rejects out of 352 tree rows, all pure structure, M3 −13 cells / −11 418 pts, every canopy and GT metric bit-identical to r2.
per-segment TCS ground
tcs_ground.per_segment = true
retune, ship off
Loses a real sign, doubles M3, holes a truth crown and re-paints the billboard — because the segment ground union drops 25–63 % of the ground points.
hard-blob unpaint
model defaults
keep (coupled)
Byte-identical r2 → r3pr, but its share denominator changed outside the new knob, so it must now ship together with the reject.
returns stripper
tau 0.30, r 0.75
unchanged, still off
Byte-identical r2 → r3pr on all four segments; the one residual 060 pole_other FP at (293.58, −112.32) is still there in r2, r3pr and r3.
canopy extension
0.20 / 0.02
regression-clean
Summary lines byte-identical r2 vs r3pr on every segment; it only moves under r3, and that is the DEM, not this pass.
sparse-sign guard
sign_post.min_points_per_m = 100
regression-clean
Still exactly the two 018 ghosts and nothing else; it is not what loses the 018 sign under B (that reject reason is short_bare_post, ~890 pts/m).
2. Improved — experiment A, the instance reject
Four instances rejected, all four are structure keep
Churn r2 → r3pr in tree_clusters.csv is 4 rows out of 352, all vegetation_rf/accepted → reject/hard_structure_returns; clusters.csv (the whole sign path) churn is 0 rows on every segment, and the painted-point delta is exactly the rejected instances with +0 added anywhere.
BEFORE = 3rd/4th panel · 018 cid16, a flat sign board on a T-post over guardrail and road streaks, n 72 883, hard share 0.893, mrf 0.050 · base/r2 paint long green streaks along road and rail, r3pr/r3 paint nothing — no foliage exists in the circleBEFORE = 3rd/4th panel · 018 cid20, the curved row of hoops/arches + bar standing on the carriageway (known false tree #1), n 8 455, share 0.923 · green in base and r2, clean in r3pr/r3BEFORE = 3rd/4th panel · 060 cid33, a bare linear streak on empty asphalt (known false tree #2), n 9 214, share 0.939 · gone in r3pr/r3, and the real tree belt top-right is pixel-for-pixel identical in all four rootsBEFORE = 3rd/4th panel · 085 cid11, a mid-carriageway streak plus the pre-existing guardrail-crest line, n 9 379, share 0.919 · r2 removed part, r3pr removes the rest; the cid0 crest over-paint survives unchanged, not worsened
M3 hard contamination 23 cells / 41 187 pts → 10 cells / 29 769 pts (−28 %, and −85 % vs base) · detection diff vs r2 = REMOVED 4 / ADDED 0 / MOVED 0 · 066 does not change by a single point · both known false trees gone · the two extra rejects have instance mrf 0.048 and 0.005 against a tree population of 0.42–0.55.
The reject is canopy-neutral verified on both truth crowns
Compare the r2 and r3pr columns only (the 4th and 5th): they are the same paint. All point-level canopy metrics are unchanged to 5 decimals.
BEFORE = 3rd/4th panel · 018 truth spot lowrej_018_c0_s2, canopy top 7.2 m · the r2 and r3pr columns are identical — the reject touches no crown (the hole in the last column is experiment B, see below)BEFORE = 3rd/4th panel · 060 truth spot lowrej_060_c12_s0, canopy top 17.2 m · r2 == r3pr again; both truth crowns confirm the reject is canopy-neutral
M1 canopy recall > 10 m 0.83264 (identical), M1b 4–10 m 0.898 (identical), M2 foliage-cell recall 0.90608 (identical), 12/12 truth spots recalled with 0 FP, 085 GT recall unchanged to the point · no sign, delineator or rail-half-post record is touched.
3. Did not work — experiment B, per-segment TCS ground
A real sign disappears on a 27 mm ground shift blocker
The clearest single regression: the cluster is present and accepted in base, r2 and r3pr as sign_post_with_plate (n 2 496, ml 0.665), and in r3 the same 2 492 points are rejected because z_ground moved from −5.916 to −5.943 m.
BEFORE = 3rd/4th panel · 018 (−3212.87, −2195.74), a real post with plate at the road edge in front of dense foliage · magenta in base, r2 and r3pr, absent in r3 — cid 593 n 2 492 rejected short_bare_post after a 27 mm z_ground shift
Nothing else about the cluster changed · 018 signs 5 → 4 · and the same DEM shift flips a rail_half_post to rescue_stage (7 → 6).
Canopy paint is lost, in tile-shaped pieces regression
The added paint is low and single-return-heavy (a third of it below 0.5 m, 5th percentile below the independent ground) while the removed paint is higher and more foliage-like — wrong direction on both counts.
BEFORE = 3rd/4th panel · 018 truth crown 7.2 m · look at the last (r3) column: a clean rectangular, tile-aligned hole is bitten out of the crown paintBEFORE = 3rd/4th panel · 018 roadside hedge/scrub belt, instance n 140 264 · base/r2/r3pr paint the whole belt, r3 paints only the right-hand third — two thirds of a real hedge lose their paintBEFORE = 3rd/4th panel · 018 dense wood belt, churn −147 031 / +221 181 pts · r3 paints a narrow near-edge band and drops most of the interior canopy
M1b mid 018 −0.049, M1 hi 018 −0.010 · 018 removes 457 247 painted points, 066 removes 354 626 of which half sit above 4 m · the crown hole is rectangular and tile-aligned, i.e. a tiling artefact of the segment-wide ground, not a threshold.
Structure comes back, and the stated motivation is falsified regression
B was meant to remove road-surface tree paint via a better DEM; measured in the 066 streak window it adds road paint instead, and it re-contaminates the 060 billboard the hard-blob pass had cleaned.
BEFORE = 3rd/4th panel · 060 billboard panel + frame beside a real conifer, cid93 · r2/r3pr leave the panel grey, r3 speckles panel and legs green again (share 0.58 → 0.50, unpaint 109 697 → 96 537 pts, new hard cell 296,−67 with 10 950 pts)BEFORE = 3rd/4th panel · 066, 68 m of carriageway with lane markings and a belt each side · base’s wide streaks are gone from r2/r3pr, but the two thin lane-marking lines stay green in r3 and are brighter/more continuous (+13 326 pts) — the stated motivation for B, falsified
M3 hard contamination 10 cells / 29 769 pts → 17 / 68 142 (+129 %, and +65 % worse than r2) · 066 streak window 126 761 → 140 087 pts (+10.5 %), wider low window 236 958 → 281 407 (+18.8 %) · z_ground tail biased down: 066 mean −0.337 m, 88 clusters shift > 1 m, p5 −3.04 m, min −8.09 m.
Gains to preserve through the retune real recall
Two places where per-segment ground is unambiguously right: low vegetation that per-record ground swallowed, and the tall 085 forest the human GT can actually score.
BEFORE = 3rd/4th panel · 060 low scrub/bush band below the road, orange (multi-return) in the number_of_returns panel · base/r2/r3pr leave it unpainted, r3 paints it — a genuine recall gain on real vegetation (+34 624 / +30 205 pts)BEFORE = 3rd/4th panel · 085 tall 30 m forest, +7 970 / +2 854 pts in r3 · the 085 human-GT recall rises to 0.887 here, although r3’s upper canopy paint looks slightly thinner than r3pr’s (GT only covers the old angle-filtered cloud)
085 human-GT tree recall 0.7547 → 0.8865 (fn 50 760 → 23 489; of the extra paint the GT sees, 27 349 pts are GT tree and 21 638 GT medium_veg) · M2 +0.005, M1 hi 060 +0.011, 4 genuinely new scrub-tree records on 060 · cost: precision 0.4924 → 0.4697, hard fp 52 538 → 74 229.
4. Results per segment
segment
canopy recall > 10 m base / r2 / r3pr / r3
M3 hard cells / points base → r2 → r3pr → r3
detections sign / delineator / tree base → r2 → r3pr → r3
M3 is defined on 018+060 only (the segments with truth spots); pooled it is 44/195 676 → 23/41 187 → 10/29 769 → 17/68 142.
Base and r2 runtimes come from the previous round and were measured under different concurrency; r3pr and r3 both ran 4-up, so r3 vs r3pr (+31–71 %) is the only fair runtime comparison — worst case 7.5 min, well inside the 20 min/segment budget.
"TCS ground kept fraction" is the share of per-record ground points that survive the segment-wide union; record071 on 066 alone keeps 0.0889.
Supported min-Z seeding for the ground union — seed the segment DEM from min-Z points that are supported by neighbours instead of the raw minimum, so a few low-noise points from one pass cannot drag the union down; canaries after the retune: the 018 sign at (−3212.87, −2195.74) must come back, M3 on 018+060 must be ≤ 29 769 pts, and the crown_truth_018 tile hole must be gone.
Ship the two hard-blob knobs as a pair — the share denominator changed from all instance points to points above hard_blob_min_elev_m and that change is not gated by the new knob, so with the reject off the current code would leave 29 991 hard points that r2 removed; either ship together or gate the denominator.
Add a survivor test to the 0.6 cap — 060 cid93 (real conifer + billboard) sits at share 0.5815; crossing the cap would delete a real tree, so require the surviving elevated points to be non-foliage (survivor mrf, or a survivor-count floor).
Stripper pole_other residual — reject stripped promotions to pole_other (or require a minimum relative drop, sf ≥ 0.10, before features are recomputed); the 060 FP at (293.58, −112.32, h 9.715, n 1191) is unchanged in r2, r3pr and r3 and keeps the sign-path stripper disabled.
Minors to review — cache staleness when a record leaves a segment, a provenance check in the canopy pass, and outcome/reason preservation on reject.