Two complementary algorithms for filling the inter-floor voids on the facades of two adjacent towers in a TLS / HLS point cloud. The towers are referred to internally as V (output class 9, magenta) and W (output class 10, cyan).
scripts/
├── common.py Shared LAS I/O + helpers
├── voidfill_geometric.py Geometric column-wise void fill
└── voidfill_lama.py Deep-learning baseline (per-Z slice + LaMa)
These two scripts assume the upstream preprocessing (denoising + voxel-down-sample) and CSF ground extraction have already been done, and that the resulting LAS files live at:
output/02_preprocessed/preprocessed.las # ~400 K points, RGB + intensity
output/03_ground/ground.las # ~27 K ground points (CSF)
voidfill_lama.py additionally reads the per-tower bounding boxes
from output/04_facade_voidfill_VW_only/per_tower/{fill_V,fill_W}.las,
which are produced by voidfill_geometric.py.
# 1. Python environment
python3 -m venv .venv
source .venv/bin/activate
pip install simple-lama-inpainting laspy scipy matplotlib open3d
# 2. Geometric void fill
python3 scripts/voidfill_geometric.py
# -> output/04_facade_voidfill/cloud_with_fill.las (~362 K fill points)
# 3. LaMa void fill (optional DL baseline)
python3 scripts/voidfill_lama.py
# -> output/04b_facade_lama/cloud_with_fill_lama.las (~472 K fill points)The first run of voidfill_lama.py will download the LaMa weights
(big-lama.pt, ~196 MB) into ~/.cache/torch/hub/checkpoints/.
This is a cross-modal prior transfer approach — leveraging 2D image inpainting priors for 3D point cloud completion.
The deep-learning baseline (voidfill_lama.py) reduces the 3D
void-filling problem to a sequence of 2D image inpainting problems on
horizontal slices of the building, then lifts the solutions back to 3D.
This makes a model trained on millions of urban photographs (LaMa)
directly usable on a TLS / HLS point cloud, without retraining and without
any 3D ground truth.
flowchart LR
A["Preprocessed cloud<br/>+ ground layer"]
--> B["1. HAG extraction<br/>kNN on ground"]
B --> C["2. Z-slice<br/>1 m horizontal slabs"]
C --> D["3. Convex-hull mask<br/>hull − slice occupancy"]
D --> E["4. LaMa<br/>2D image inpainting"]
E --> F["5. Back-projection<br/>filled pixels → 3D points"]
F --> G["Filled cloud<br/>class 9 = V, class 10 = W"]
- HAG extraction — Height-Above-Ground for every wall point via inverse-distance kNN (k = 6) on the CSF ground layer; everything below the connecting footbridge top (HAG < 20 m) is dropped.
- Z-slice — the remaining points of each tower are split into 1 m thick horizontal slabs; every slab is processed independently.
- Convex-hull mask — the building's outline at this Z is
approximated by the convex hull of points in a ±5 m Z window, and the
inpainting mask is
hull − slice_occupancy. - LaMa — the slice's binary occupancy and mask are fed to LaMa (Suvorov et al., WACV 2022) as a 2D image; LaMa returns a fully inpainted slice at 0.5 m / px.
- Back-projection — pixels that LaMa turned ON inside the original mask are converted back to 3D points at the slice centre Z, with class 9 (V, magenta) or 10 (W, cyan).
| Method | Idea | Output points | Output folder |
|---|---|---|---|
Geometric (voidfill_geometric.py) |
Inside each tower's XY footprint, bin facade points into 0.5 m XY columns, detect Z gaps in [0.6, 8.0] m, synthesise points at 0.5 m spacing along Z, then run 10 iterations of footprint-clipped neighbourhood propagation. | ~362 K | output/04_facade_voidfill/ |
LaMa per-Z slice (voidfill_lama.py) |
The 5-step pipeline above. | ~472 K | output/04b_facade_lama/ |
| class | meaning | RGB |
|---|---|---|
| 0 | original (unchanged) | original |
| 9 | V tower fill | 255 / 40 / 200 (magenta) |
| 10 | W tower fill | 40 / 200 / 255 (cyan) |
- Synthetic points are not measurements. All output fill points are interpolated or inpainted; they should be used for visualisation, modelling and labelling-data augmentation only — never for accuracy assessment, deformation monitoring, or geometric quality control.
- No quantitative evaluation. The current results are validated by point counts, Z-range checks and 3D visual inspection. A proper benchmark (Chamfer Distance, F-Score @ τ, leave-one-out reconstruction RMSE) is left as future work.
- Convex-hull over-estimation. The LaMa pipeline approximates each Z-slice's outline by a convex hull, which over-fills non-convex buildings (L-shapes, courtyards, atria). An α-shape / concave-hull variant would be more faithful but is not implemented.
- Domain gap for LaMa. LaMa is pretrained on natural urban photographs, not on binary occupancy projections of point clouds. It treats inter-floor space as solid wall and therefore removes the natural window / glass-facade openings; the geometric method preserves them.
- Local coordinate system only. The input cloud has no real-world georeferencing, so neither the filled cloud nor any downstream raster can be overlaid on official base maps without an external transformation.
- Hard-coded scene assumptions. The HAG cutoff (20 m) is tuned to the connecting footbridge of this scene, and the pipeline expects exactly two towers (V and W). Other scenes will require parameter tuning and possibly a re-design of the per-tower extraction.
- Loss of true wall depth. Per-Z back-projection places every fill point at the slice centre Z and on the convex-hull plane, so the output cannot recover the building's actual wall offset / depth variation along Z.
- LaMa model: Suvorov et al., Resolution-robust Large Mask Inpainting with Fourier Convolutions, WACV 2022 — repo advimman/lama.
- LaMa Python wrapper: enesmsahin/simple-lama-inpainting.
