constructelligence's picture
Add pipeline and results diagrams to model card
90d6cac verified
|
Raw History Blame Contribute Delete
13.9 kB
---
license: apache-2.0
language:
- en
library_name: pytorch
pipeline_tag: image-segmentation
tags:
- image-segmentation
- semantic-segmentation
- robotics
- edge-ai
- construction-ai
- autonomous-painting
- wall-painting-robot
- paint-coverage-estimation
- building-facade
- drywall
- skirting-detection
- window-detection
- lidar
- depth-validation
- segformer
- deeplabv3
- pytorch
metrics:
- mean-iou
- iou
model-index:
- name: painting-vision-robotics-kit
results:
- task:
type: image-segmentation
name: Wall / window / other segmentation (hosted best.pt, real facades)
dataset:
name: painting_vision held-out test split, real facade subset (76 images)
type: painting-vision-real-data
split: test
metrics:
- type: mean_iou
value: 0.7717
name: mIoU (other/wall/window, real facades)
- type: iou
value: 0.838
name: wall_painted IoU (real facades)
- type: iou
value: 0.642
name: window IoU (real facades)
- type: recall
value: 0.861
name: window recall (real facades)
---
# Painting Vision Robotics Kit — robot-ready wall-paint coverage segmentation
**Edge-deployable perception and planning for autonomous painting and surface-finishing robots: from pixels to an executable paint plan.**
The Painting Vision Robotics Kit reads a single camera frame of a wall and returns far more than
a mask. It segments the paintable surface, the fixtures and openings that must
not be painted, and the substrate — then hands a downstream planner a *wall
boundary, corners, a two-tool stroke plan, machine-readable waypoints, and a
live paint-progress grid*, independently cross-checked against depth/LiDAR.
It is built for the hard part of construction robotics: knowing **exactly where
the wall is, where the keep-outs are, and when the coat is complete**.
> **Release:** `best.pt` is a SegFormer-B2 (768 px) **facade checkpoint** — walls, windows and paint coverage
> on real exteriors. The interior paint-state and substrate model (**C2-cal**) is in validation and reported
> below. The geometry planner, depth validator, safety gate and dataset tooling ship together and are covered
> by the included test suite.
## The open tier of a larger model family
Constructelligence develops construction-AI models across a range of sizes. This kit is the **open, onboard
tier**: compact enough to run on a painting robot's CPU or a small accelerator, offline, with the full
perception-to-plan pipeline. Our larger models — bigger backbones, higher-resolution and multimodal RGB +
depth/LiDAR input — are a separate class and are not published here.
---
## Why this model exists
General segmentation models tell you a wall is *present*. Painting robots need
to know:
- which pixels are **paintable wall** versus **trim, skirting, openings and fixtures**;
- the **exact boundary and corners** of the wall, so a roller or spray head does not cross an edge;
- a **stroke path** that respects a physical clearance margin and lifts over obstacles;
- the **substrate** (e.g. drywall) so paint behaviour is not confused with surface type;
- **remaining coverage** across repeated observations, so the robot knows when to stop.
The kit is designed end-to-end around those questions.
## Capabilities
![How it works](figures/painting-pipeline.png)
### 1. Ten-class semantic segmentation + substrate head
The model family is **SegFormer-B2** (the hosted `best.pt` is the facade checkpoint; interior classes are
C2's); `models.py --arch` also builds MobileNetV3-Large and ResNet-50/101
DeepLabV3 variants for smaller or larger compute budgets. A **ten-class semantic head** is paired with a
**separate drywall-material head**, so paint state and substrate are predicted independently:
`other · wall_unpainted · wall_painted · wall_uncertain · skirting · switch/outlet · AC unit · door · window · wall_obstacle`
Painted coverage is reported as `wall_painted / (wall_painted + wall_unpainted)`
with lower/upper bounds that include uncertain wall area — a confidence-aware
estimate, not a single false-precise number.
### 2. Window detection you can trust around
Windows are the most safety-critical keep-out in exterior painting. The
`window_postprocess` stage merges mullion-split fragments, fits an **oriented
minimum-area rectangle** with rotating calipers (so a window stays a window at
any viewing angle), and filters specks and non-window shapes by fill ratio and
aspect ratio — producing complete, regularised keep-out geometry.
### 3. Robot paint planner
`robot_planner.py` converts the masks into an executable plan:
- ordered **boundary polygon and corners** (Moore-neighbour contour tracing + Douglas-Peucker — it follows real rooflines and voids, not a convex hull);
- optional **wall-plane rectification** with edge lengths in millimetres;
- a **two-tool plan**: roller passes for open areas plus **trim/brush passes** for edges and around fixtures the roller cannot reach;
- **machine-ready waypoints** with paint on/off flags and travel distance;
- **paint-progress tracking** (`--state`) that targets only what remains and tells the robot when the wall is done.
A documented real-facade run lifted planned coverage from **68% (roller only) to
97.5% (roller + trim)** on the same wall — the residual is the physically
unreachable remainder, reported explicitly.
### 4. Depth / LiDAR validation on top of vision
`depth_validation.py` independently checks the vision output in metric 3D:
RANSAC wall-plane fitting, protrusion/recess detection (missed pipes or windows),
recess-versus-window agreement, and a **metric millimetres-per-pixel scale**
derived from depth instead of guessed — so the planner works in real units.
### 5. Balanced-data tooling
`data_balance.py` and `audit_dataset.py` score coverage and balance across
indoor/exterior, substrate, lighting, weather, paint stage and classes, flag
wall/session leakage and thin classes, and recommend exactly how many more
samples each gap needs. `train.py` supports class-, wall- and hybrid-balanced
sampling so the balanced collection survives into the optimizer.
### 6. Paint colour: named, matched, per face
`paint_color.py` places the painted pixels in CIELAB, trims the darkest and
brightest 10% (shadow, glare, lap marks) and names the coat ("magnolia
#F1EBD6"), reports a k-means palette and a colour per measured wall face — so a
face painted in the wrong colour or a missed second coat is visible in the
report. A specified colour (`--reference-color`) is compared with **CIEDE2000**
and banded (≤1 exact, ≤2 a touch-up match, ≤5 the same at a glance), and
`safety_gate.py` stops the coat when the measured colour is not the specified
one. The colour printed on a paint can's label is read and checked against the
same reference, so the product on site is verified and not assumed.
### 7. The equipment around the wall
`site_objects.py` finds paint cans, trays, brushes, rollers, ladders and dust
sheets around the wall with a classical-vision detector that needs no training data: gradient outlines are cut above the frame's own noise, scene structure
(skirting, ceiling, the wall/floor junction) is removed so a tin standing on the
floor is not welded onto it, outlines are closed and filled back into bodies,
and each body is scored per class from its own cues — aspect, fill, outline
straightness, nap texture, the stripe a tin's rim or a brush's ferrule makes,
the repeats tray ridges or ladder rungs make, frame position, colour. It answers
what a site asks: is the gear the plan needs here, is anything standing where
the paint is going (folded into the keep-out mask), and is the tin the right
colour. Every detection carries the cues that fired and the scores of the
classes it was *not* given; `safety_gate.py` warns by default on clutter and on
missing tools, and stops on a colour mismatch.
## Quickstart
```sh
python3 -m pip install -r requirements.txt
# 1. Segment a frame
python3 predict.py frame.jpg --checkpoint hf://constructelligence/painting-vision-robotics-kit \
--paintable-mask paintable_wall_mask.png \
--keepout-mask fixture_keepout_mask.png \
--json result.json --tta
# 2. Plan the paint path (optional wall-plane rectification + mm scale)
python3 robot_planner.py --paintable paintable_wall_mask.png \
--keepout fixture_keepout_mask.png \
--corners "80,60 1180,55 1190,700 70,710" \
--stroke-width 230 --trim-width 60 --overlap 0.2 --margin 40 --mm-per-unit 3.0 \
--state wall_014.npz --plan plan.json --overlay plan.png
# 3. Validate against depth / LiDAR if available
python3 depth_validation.py --depth depth.npy --intrinsics "fx,fy,cx,cy" \
--mask painting_mask.png --report validation.json
```
## Repository layout
| File | Role |
| --- | --- |
| `models.py` | architecture factory: DeepLabV3 (MobileNet/ResNet) + SegFormer, semantic + drywall heads |
| `train.py` | training, balanced sampling, window loss boost, boundary/coverage metrics |
| `predict.py` | inference: masks, coverage, geometry, regularised windows, paint colour, equipment on site |
| `paint_color.py` | the coat's colour named, paletted, per face, and matched with CIEDE2000 |
| `site_objects.py` | model-free detection of paint cans, trays, brushes, rollers, ladders, dust sheets; the colour on a tin's label |
| `robot_planner.py` | boundary/corners, two-tool stroke plan, waypoints, progress state |
| `window_postprocess.py` | fragment merge + oriented rectangle fitting for windows |
| `depth_validation.py` | LiDAR/depth plane fit, protrusion/recess checks, metric scale |
| `data_balance.py` | coverage/balance analytics |
| `audit_dataset.py` | dataset audit: schema, leakage, class and domain balance |
| `fetch_real_data.py` | downloads and converts a real labeled dataset for testing |
| `smoke_test.py` | end-to-end audit → train → predict → plan |
| `benchmark.py` | head-to-head vs a generic baseline on the shared wall/window/other subset |
| `provenance.py` | content-addressed dataset identity, integrity + licence ledger |
| `safety_gate.py` | fail-closed approve/reject deployment gate |
| `flywheel.py` | ingest corrected captures with content + perceptual dedupe |
| `active_learning.py` | rank which frames to label next (novelty + domain gaps + uncertainty) |
| `run_registry.py` | append-only, hash-linked ledger of training/eval runs |
| `test_*.py` | geometry, window, depth and architecture regression tests |
## Evaluation
Frozen protocol (`benchmark/SPEC.md`, v1.0); every number is tied to one checkpoint.
| Checkpoint | In this repo | What it is |
| --- | --- | --- |
| `best.pt` (sha256 `3ef02176…`) | **yes** | SegFormer-B2, 768 px; semantic + material (drywall) heads; trained for exterior facades |
| `C2-cal` | release candidate | SegFormer-B2 lineage with wallpaper and condition heads, painted-wall hard negatives and reviewed real interiors; calibrated operating points |
![Measured results](figures/painting-results.png)
### This release: `best.pt` on real facades
Held-out real facade frames (76) from the 136-frame test split:
| Metric | Value |
| --- | --- |
| mIoU, other / wall / window | **0.772** |
| wall_painted IoU | **0.838** |
| window IoU · precision / recall | 0.642 · 0.717 / **0.861** |
| painted-coverage MAE | **0.114** |
**Scope.** `best.pt` is an exterior model. The other 60 frames of the split are synthetic interiors, where it
does not predict the interior classes (unpainted wall, skirting, doors, switches) and must not be used to sign
off paint: on the full 136-frame split its 10-class mIoU is 0.186 and it calls 81% of unfinished interior walls
complete. Interior work is what C2 is for.
### Release candidate: C2-cal (not in this repo)
Same test split: 10-class mIoU **0.848**, painted-coverage MAE **0.088**. On real photographs it was never
trained on — two independently reviewed sets, with operating points fitted on set 1 and judged on held-out
set 2:
| Question (set 1 / held-out set 2) | C2-cal |
| --- | --- |
| Finding the wall | 117 / 117 |
| Bare drywall signed off as finished | **0% / 0%** |
| Bare drywall found (recall) | 0.89 / 0.88 |
| Painted wall called bare board | 35% / 31% |
| Wallpaper, held-out precision / recall | 0.64 / 0.70 |
| Damage (peeling / rust) AUROC | 0.61 / 0.72 — surfaced as a proposal for a person to confirm |
`train.py` reports every metric family above on any dataset you supply.
## Intended use and limitations
**Intended:** with `best.pt`, assistive perception and path planning for exterior painting/finishing robots;
dataset curation and annotation QA for construction vision.
**Not intended:** unattended safety-critical control without calibrated geometry, clearance validation and a
human-approved deployment; interior paint sign-off with `best.pt`; judging *finish quality* (streaking, thin
coat, runs).
RGB alone cannot always reveal what is under a smooth surface; the model scores
drywall only where visible evidence supports it and uses `unknown` otherwise.
Always validate on held-out physical walls with the production camera.
## Citation
```bibtex
@misc{constructelligence_painting_vision,
title = {Painting Vision Robotics Kit: robot-ready wall-paint coverage segmentation},
author = {Constructelligence},
year = {2026},
note = {SegFormer-B2 release}
}
```
## Keywords
wall painting robot · autonomous painting · paint coverage estimation ·
construction AI · building facade segmentation · drywall detection · skirting
detection · window detection · semantic segmentation · LiDAR validation ·
depth sensing · robot path planning · paint progress tracking · construction
robotics · BIM · surface finishing automation