BlueprintParse-R50
π°π· Korean card: MODEL_CARD.ko.md
Read this first
- Five sanitary fixture classes only: gas range, toilet, washbasin, kitchen sink, bathtub. Walls, rooms, dimensions, text and every other object are neither detected nor claimed.
- Automatic quantity takeoff: COUNT_NO_GO. On 53 novel drawings, per-drawing exact count match was 0.566 (95% CI 0.434β0.698), far below our 0.90 gate.
- Use the counts only as a draft that a person checks item by item.
Faster R-CNN (ResNet-50 FPN v2) detector for Korean architectural floor-plan images, exported to a single FP32 ONNX graph that runs on CPU or GPU with onnxruntime. It returns boxes, class and score for the five fixture classes, with boxes mapped back to original image pixels.
0. How to use
pip install onnxruntime pillow numpy huggingface_hub # onnxruntime-gpu for CUDA
hf download ThakiCloud/BlueprintParse-R50 --local-dir BlueprintParse-R50 # huggingface_hub >= 0.34 (older: huggingface-cli download)
cd BlueprintParse-R50
python blueprintparse.py --selftest # synthetic drawing, checks the graph loads and runs
python blueprintparse.py floor_plan.png --threads 16
python blueprintparse.py floor_plan.png --providers CUDAExecutionProvider,CPUExecutionProvider
from blueprintparse import BlueprintParse
bp = BlueprintParse(threads=16) # verifies the ONNX sha256
out = bp(open("floor_plan.png", "rb").read())
print(out["counts_draft"]) # {"gas_range": 1, "toilet": 2, ...} draft only
for d in out["detections"]:
print(d["class"], d["score"], d["box_xyxy"])
Pre-processing (same as training): grayscale, shrink so the long side is at most 2048 px (read from model metadata), scale to 0..1, replicate to 3 channels. Detections with score β₯ 0.5 are returned; scores in [0.3, 0.5) go to uncertain_candidates. review_required is always true.
ONNX interface: input image [3,H,W] float32 (H, W dynamic); outputs boxes [N,4] (input-tensor xyxy), labels [N] int64 (1..5), scores [N]. Opset 17. Metadata holds class_ids, max_side, precision, opset and the source checkpoint sha256.
1. Files
| File | What it is |
|---|---|
bp_fp32.onnx |
FP32 ONNX detector, sha256 5ed19b8bccc6d5abfdeb5dd26f153c28379115b100a9a4ce479479e10bffb773 |
blueprintparse.py |
inference (pre-processing, box mapping, counts draft) + synthetic self-test |
export_onnx.py |
reproduce the ONNX from your own torchvision checkpoint, and check ONNX vs PyTorch |
No drawings, crops, labels, overlays or sample predictions from the training data are in this repository.
2. Results
All numbers come from our own runs, recorded in an internal experiment ledger. The official test split was scored once with the published ONNX file.
Detection
| Split | Images | mAP50-95 | AP50 |
|---|---|---|---|
| Official test split | 1,014 | 0.926 | 0.9805 |
| Novel drawings (near-duplicates of training removed) | 53 | 0.7875 | 0.922 |
AR@100 on the test split: 0.9447. ONNX FP32 vs the PyTorch training checkpoint: β0.0009 / 0.0 (test), β0.0026 / β0.0005 (novel).
Per-class AP50:
| Class | Test (1,014) | Novel (53) |
|---|---|---|
| gas_range | 0.9883 | 0.9637 |
| toilet | 0.9793 | 0.9508 |
| washbasin | 0.9886 | 0.9489 |
| kitchen_sink | 0.9677 | 0.7896 |
| bathtub | 0.9784 | 0.9572 |
The drop from test to novel (0.926 β 0.7875 mAP50-95) is the number to plan with for drawings that do not look like the training set. Kitchen sinks drop the most.
Counting (why takeoff is COUNT_NO_GO)
Novel 53 drawings, 400 ground-truth objects, score threshold 0.8 (chosen on the dev split):
| Metric | Value | Gate |
|---|---|---|
| Per-drawing exact count match (all 5 classes right) | 0.566 (0.434β0.698) | β₯ 0.90 |
| Mean absolute error per class cell | 0.1925 | β€ 0.05 |
| Error-flag recall | 0.478 | β₯ 0.80 |
| Exact match on drawings the model did not flag | 0.684 | β₯ 0.95 |
Both the fully automatic gate and the "auto only for unflagged drawings" gate failed, and the upper confidence bounds are still below the thresholds. Counts are therefore a draft for human review.
Latency (p50 per image, ms)
Synthetic 1448Γ2048 input. Columns: ONNX FP32 on CUDA / ONNX FP16 on CUDA / ONNX FP32 on CPU / INT8 static on CPU / INT8 dynamic on CPU.
| Hardware | FP32 CUDA | FP16 CUDA | FP32 CPU | INT8 static CPU | INT8 dyn CPU |
|---|---|---|---|---|---|
| B200 (CPU 32 cores) | 26.1 | 24.69 | 786.1 | 1925.01 | 2831.59 |
| H200 (CPU 16 cores) | 27.33 | 22.23 | 1204.46 | 2590.13 | 3607.11 |
| H100 (CPU 10 cores, proxy weights) | 30.12 | 25.2 | 1953.59 | 2496.96 | 4100.12 |
Only the FP32 graph is published. Under our pre-registered selection rule, INT8 dynamic lost 0.0735 dev mAP50-95, INT8 static kept accuracy but was slower than FP32 on CPU, and FP16 kept accuracy but was only 5% faster on B200 (the rule required β₯10%). H100 timings used stand-in weights of the same architecture. On real drawings (B200, ONNX FP32 CUDA) end-to-end time including pre-processing was 135 ms p50 with 22.8 ms inference, and 889 ms on 32 CPU threads; latency did not depend on the number of detections up to 28 per drawing.
3. Limitations
- Five classes only (see top). Zero detections is not proof of absence.
- COUNT_NO_GO for automatic quantity takeoff; draft + human check only.
- Evaluated on one public dataset. No customer drawings have been evaluated.
- The densest evaluated drawings had 28 objects; drawings with hundreds of fixtures were not measured.
- Ground truth is the dataset's label boxes; label quality was not audited.
- The novel split is small (53 drawings), so its confidence intervals are wide.
4. Training data
Trained on AI νλΈ(AI-Hub) β κ±΄μΆ λλ©΄ λ°μ΄ν°(OBJ)(71465) (Korean architectural drawing dataset, object annotations, AI-Hub dataset 71465). Split: 7,900 train / 199 dev / 1,014 test, with a 53-drawing novel subset.
λ°μ΄ν° μ¬λ°°ν¬ λΆκ°, μ μ²μ λ³ΈμΈ λ΄λΆ μ΄μ©. The dataset is not redistributable: it was used only by the applicant, inside the applicant's own environment. This repository contains trained weights and code only; no drawings, crops, label files or derived subsets. To retrain, apply for the dataset on AI-Hub with your own account.
Initialization: torchvision fasterrcnn_resnet50_fpn_v2 COCO-pretrained weights.
5. License
Apache-2.0 for the weights and code. See NOTICE for the required dataset attribution. Runtime dependencies are permissively licensed (MIT / BSD / Apache-2.0).