Annotation / CLAUDE.md
MathewKasbarian
feat(ai): tiled inference, machine API, and label JSON interchange in annotator
c640d68
|
Raw History Blame Contribute Delete
3.01 kB
# Annotator Tool
Gradio annotation tool for facade frame detection. Deployed to HF Spaces as `Infin8-AI/Annotation`.
## Files
- `app.py` β€” Gradio UI (3 tabs: Detect, Review & Edit, Send to Backend) + hidden machine API
- `detection.py` β€” YOLO inference wrapper (tiled for full sheets) with OpenCV fallback
- `requirements.txt` β€” Python deps for local dev and HF Spaces
- `packages.txt` β€” System deps (poppler-utils) for HF Spaces
- `best.pt` β€” YOLO11n weights (not in git β€” download from HF Hub or train locally)
## Detection
Full drawing sheets are detected with **tiled inference** (`detect_tiled`: 640Γ—640 windows,
stride 480, cross-tile NMS IoU 0.5) at **200 DPI** β€” whole-sheet single-pass inference finds
nothing because mullions shrink below detectable size. `detect_rectangles()` tiles
automatically for images larger than one tile. Constants live in `detection.py`
(`TILE_SIZE`, `TILE_STRIDE`, `TILE_MERGE_IOU`, `DETECTION_DPI`) and must match the
training dataset builder.
Model resolution order: `FACADE_MODEL_PATH` (local file) β†’ `FACADE_MODEL_REPO`
(HF Hub, e.g. `Infin8-AI/estimat8-vm-v1`, pin with `FACADE_MODEL_REVISION`, auth with
`HF_TOKEN`) β†’ `best.pt` next to `detection.py`.
## Machine API (for backends)
Hidden endpoints exposed via the Gradio API, called with `gradio_client`:
```python
from gradio_client import Client, handle_file
client = Client("Infin8-AI/Annotation", hf_token=...) # or http://localhost:7860
result = client.predict(handle_file("page.png"), 0.25, api_name="/detect_image")
# -> {"width_px", "height_px", "model_version", "boxes": [{x1,y1,x2,y2,conf}]}
```
- `/detect_image (image_file, conf)` β€” primary: caller renders the PDF page and uploads one PNG.
- `/detect_page (pdf_file, page_number, dpi, conf)` β€” testing/fallback; avoid for big PDFs
(gradio_client re-uploads the file every call).
## Label JSON import/export (Review & Edit tab)
`↓ Labels` exports every annotated page as canonical per-page label JSON (coordinates in
**PDF points**, provenance + rejected boxes preserved), zipped. The Import field loads such
JSONs back (audited β†’ approved, machine bootstrap β†’ pending, rejected β†’ rejected). This is
the audit interchange format consumed by `scripts/annotation/` at the repo root.
## Deploying to HF Spaces
HF Spaces builds from `hf/main`. The Space expects files at the repo root, so use git subtree:
```bash
# Add remote once
git remote add hf https://YOUR_HF_TOKEN@huggingface.co/spaces/Infin8-AI/Annotation
# Push this subdirectory as the Space root
git subtree push --prefix=tools/annotator hf main
```
## Training loop
See `scripts/build_dataset_from_events.py` and `scripts/train_facade_detector.py` at the repo root.
```bash
# From repo root β€” after exporting events.jsonl from the Gradio tool
python scripts/build_dataset_from_events.py --events events.jsonl --pdf source.pdf
python scripts/train_facade_detector.py --version v2
cp models/yolo_facade_v2/best.pt tools/annotator/best.pt
```