Bridge Crack Detection (crack-seg)
Pixel-level semantic segmentation of cracks in high-resolution UAV bridge imagery with a U-Net encoder-decoder. Inference tiles large images into overlapping 448×448 patches, blends them with a 2D Gaussian weight map, and optionally emits a crack-density heatmap. See the code repo for the full pipeline.
Checkpoints
| File | Architecture | Notes |
|---|---|---|
unet_v3.pth |
U-Net [32,64,128,256] + SE blocks + deep supervision |
Recommended. Trained 2026-08 on multiple data sources (UAV Kaggle + DeepCrack train + merged crack sources), 512px, BCE+Dice, Adam 5e-4 + cosine, EMA. |
unet_narrow_v2.pth |
U-Net [32,64,128,256] |
Tuned via internal hyperparameter optimization tool: Pathfinder |
unet_wide_v1.pth |
U-Net [64,128,256,512] |
Original notebook model (4× params). |
All checkpoints load through the same code path — the loader
(src/models/checkpoint.py) auto-detects channel widths, legacy key naming,
SE/deep-supervision heads, and upsample mode.
Metrics (threshold 0.5, direct full-image inference)
Held-out staged test split (447 pairs)
| Model | Dice | IoU | Recall | Precision |
|---|---|---|---|---|
| v3 | 0.730 | 0.575 | 0.739 | 0.721 |
| narrow-v2 | 0.310 | 0.183 | 0.200 | 0.690 |
| wide-v1 | 0.339 | 0.204 | 0.231 | 0.634 |
The staged test split is the clean in-distribution held-out benchmark (only the val split is used for checkpoint selection). The old models were trained on UAV-only data, which is why they drop sharply here.
DeepCrack test set (237 images)
| Model | Dice | IoU | Recall | Precision |
|---|---|---|---|---|
| v3 | 0.866 | 0.764 | 0.867 | 0.866 |
| narrow-v2 | 0.720 | 0.562 | 0.656 | 0.797 |
| wide-v1 | 0.775 | 0.633 | 0.727 | 0.830 |
⚠️ Note: DeepCrack train was part of v3's training data, so the DeepCrack test number is held-out but in-distribution, not cross-domain. The staged test split above is the harder held-out benchmark.
Training (v3)
- Data: UAV Kaggle (fresh stratified 70/15/15 split), DeepCrack train (300), and a capped subset of a merged 11.2k crack dataset (CRACK500, CFD, GAPS384, Rissbilder, Volker, Sylvie, forest, cracktree200, noncrack), all resized to 512×512 with binary masks and ImageNet normalization.
- Model: narrow U-Net + squeeze-and-excitation, bottleneck dropout 0.1, deep supervision, 512px, BCE+Dice (aux-weighted), Adam lr 5e-4 with 3-epoch warmup + cosine decay, EMA, AMP, 30 epochs, best-by-val-Dice.
- Validation Dice ≈ 0.73 global / 0.66 macro at completion.
Usage
pip install -r requirements.txt
uvicorn src.app:app --port 8000
curl -X POST -F "file=@bridge.jpg" \
"http://127.0.0.1:8000/predict?overlay_type=both" -o result.jpg
Load a checkpoint directly:
from src.models.checkpoint import load_unet_checkpoint
import torch
model, features = load_unet_checkpoint("unet_v3.pth", torch.device("cpu"))
Code repo: Ishaan1402/crack-seg