Agent handoff 2 / 4 self-contained — no vault access needed
Implement vertical-marking detection (delineator posts & signs) — new repo
Continuation target: new repo implementing geometric pole-like object extraction for highway MLS segments (delineator/guide posts, sign posts + plates), plus a small eigenfeature type classifier. Literature bar: 98% precision/recall with zero training labels on 28 km of rural highway. Reuse
iolabs-* Nexus packages; no deep learning in v1.
Project context (inlined)
- Pipeline: LAS highway scans → trajectory → segments cut along the road axis (numpy
.npz; XYZ + intensity + RGB) → per-segment detectors → XML vectors for CAD. Lane markings already ship this way. - Your input: segment clouds + division planes (
iolabs-point-cloud-segmentation-trajectoryoutput), road-axis spline, and per-segment road-surface points/meshes (iolabs-point-cloud-filtering-surfaceoutput) for ground removal. - Data prerequisite: ask Miro to ship 3–5 sample "Abschnitt 1" segments incl. trajectory + surface outputs — data does not live in the repos.
- Neighbors: a guardrail agent (3D geometric detector) and a vegetation agent work in parallel. The tree-vs-pole boundary is shared with the vegetation agent — agree on an "ambiguous cluster" exchange format (cluster id, features, both candidate labels).
Research findings (inlined — adversarially fact-checked 2026-07-07)
Confirmed (3-0 votes unless noted):
- Gouda et al. 2022 (the recipe to copy): trajectory → 50 m station chunks → z-gradient road filter → surface-density filter → DBSCAN → dimensional validation. Precision/recall/F1 > 98% on 28 km across three Alberta rural highways, zero labels, no GPU.
- El-Halawany & Lichti 2013: kd-tree, 2D density segmentation, vertical region growing, segment merging — 86% average detection, 97% correctness (three MLS datasets).
- Ordóñez et al. 2017: ~10 cm voxels, 2D horizontal isolation + 3D vertical continuity — 91% of poles found, 3% false positives (urban). Then type classification with just 4 eigen-features — Z-range, λ₃/(λ₁λ₂), λ₂/λ₃, λ₁λ₃/λ₂² — into an SVM (RBF kernel): 96% overall accuracy, kappa 0.95, six classes (trees, lampposts, advertising signs, small/large traffic lights, traffic signs). Caveat: single urban study, 123 poles / 49 test objects — medium confidence, revalidate thresholds on highway data.
- Open-source reference: Dong, Chen & Stachniss 2021 range-image pole extractor — runs online on CPU; code at PRBonn/pole-localization (Python: NumPy, Open3D, SciPy, scikit-image). Its F1 (0.5–0.6) is graded in a stricter robot-localization setting; borrow the extraction ideas, not the numbers.
- Sign plates: after finding a post, search its upper part for an attached planar patch — high planarity eigenfeature + high laser-reflectance/RGB contrast → sign; a lone ~1 m post with a reflector-bright top → delineator.
Refuted claims — do NOT use:
- A surface-density threshold (~15 pts/m²) to separate poles from trees — rejected 0-3.
- Eigenvalue isotropy alone to split trees from signs (leafy tree ≈ big sign panel on single ratios) — rejected 1-2.
Open: delineator posts are small (~1 m tall, thin) — check per-object point counts at your scan ranges before fixing voxel/cluster sizes; German delineator spacing (typically 50 m) is a useful QC prior; the 96% type figure must be re-earned on highway data with a locally trained SVM.
Nexus packages to reuse
Private index: https://nexus.iolabs.ch/repository/pypi-private/simple (copy the [tool.uv.sources]/index block from 3dai.lanefinder's pyproject.toml). Update flow: uv lock --upgrade-package <pkg> && uv sync. Flat naming: iolabs-point-cloud-* → import iolabs_point_cloud_*.
| Package (Nexus) | Use for |
|---|---|
iolabs-point-cloud-segmentation-trajectory | Segment clouds + planes (input) |
iolabs-point-cloud-filtering-surface | Ground/road removal, height-above-road |
iolabs-point-cloud-filtering-clusters | DBSCAN clustering of off-ground points |
iolabs-geometry-geometry | Axis distances, bounding boxes, cylinder-axis math |
iolabs-point-cloud-modelling-export · iolabs-geometry-visualization · iolabs-common · io_orchestrator.ray_step | XML out, QC overlays, utils, pipeline step wrapper |
Plus scikit-learn (SVM-RBF) for the type classifier — persist the model + training set versioned in-repo. Suggested repo/package: 3dai.iolabs.pointcloud.verticalsigns / iolabs-point-cloud-detection-verticalsigns — confirm remote/org with Miro.
Algorithm to implement
- Ground removal: subtract road surface (surface package outputs) and compute height-above-ground for the roadside strip; work in ~50 m station chunks.
- Candidate isolation: project off-ground points to a 2D grid / ~10 cm voxels; keep cells with tall occupied vertical extent and small footprint (2D isolation + 3D vertical continuity).
- Cluster & validate: DBSCAN; per cluster compute verticality, linearity, radius (optional RANSAC cylinder fit), height, and surrounding free space; dimensional validation rejects fences/walls.
- Plates vs posts: planar-patch search on the upper part (step in findings above).
- Type classifier: SVM-RBF on the 4 eigen-features; train on ~100–150 hand-labelled objects from the sample segments.
- Export: per-object XML (axis station + lateral offset, height, type, confidence) via
modelling-export, mirroring the lines schema.
Verification
- Hand-label all poles on the sample segments; report P/R/F1 + a type confusion matrix. Bar: ≥95% detection (lit. 98% rural).
- QC overlays per segment via
iolabs-geometry-visualization, incl. a misses/false-positives gallery.
References (inlined)
- Gouda, Shalkamy, Li & El-Basyouny (2022). Fully Automated Light-Pole Detection… Transp. Res. Record 2676(7). DOI 10.1177/03611981221082531
- El-Halawany & Lichti (2013). Detecting road poles from MLS data. GIScience & RS 50(6). DOI 10.1080/15481603.2013.866815
- Ordóñez, Cabo & Sanz-Ablanedo (2017). Detection and Classification of Pole-Like Objects… Sensors 17(7):1465. mdpi.com
- Dong, Chen & Stachniss (2021). Online Range-Image-based Pole Extractor. arXiv:2108.08621 · code
Public research briefs: greenery & posts brief · all 30 sources.
Conventions
- UV project, Python ≥3.11, lint/test setup copied from an existing
3dai.iolabs.*repo. - Release = version bump →
uv build→ publish to Nexuspypi-private→ commit tagged with the Jira issue (project AI3D). - No vault on this machine: report findings/decisions back to Miro in your final summary.