# 🏠 Floor Plan Parser Parse floor plan images into structured data — walls with thickness, doors, windows, and automatically detected rooms. ## Architecture ``` Floor Plan Image (raster or vector) │ ▼ ┌──────────────────────────────┐ │ 1. INITIAL PARSE │ VLM extracts walls/doors/windows │ (VLM or vector parser) │ into structured JSON schema └──────────────────────────────┘ │ ▼ ┌──────────────────────────────┐ │ 2. COMPUTE TOPOLOGY │ Derive rooms from wall faces │ (computational geometry) │ via planar subdivision (Shapely) └──────────────────────────────┘ │ ▼ ┌──────────────────────────────┐ │ 3. RENDER OVERLAY │ Schema → SVG/PNG → alpha-composite │ (PIL / SVG) │ on original image for verification └──────────────────────────────┘ │ ▼ ┌──────────────────────────────┐ │ 4. VERIFY & CORRECT │ VLM sees overlay vs original, │ (VLM or human) │ outputs field-level corrections └──────────────────────────────┘ │ ▼ converged? ──no──→ back to step 1 yes ▼ Final structured schema (JSON) ``` ## The Schema Walls are first-class. Everything else references them. ```json { "walls": [ { "id": "w1", "centerline": [{"x": 0, "y": 0}, {"x": 6, "y": 0}], "thickness": 0.24, "openings": [ { "id": "win1", "type": "window", "start": 1.5, "length": 1.5 } ] } ], "rooms": [ { "id": "r1", "label": "bedroom", "boundary": [ {"wall_id": "w1", "side": "right"}, {"wall_id": "w2", "side": "left"} ], "area": 16.0 } ] } ``` **Key design decisions:** - **Walls have thickness** — exterior (0.20-0.30m) vs interior (0.10-0.15m) - **Openings live on walls** — `start` + `length` along the centerline - **Rooms are topological** — defined by ordered wall-face references (left/right side), not duplicate coordinates - **Curved walls** = polyline centerlines with many sample points - **Non-rectangular rooms** fully supported (any angles) ## Modules | File | Purpose | |------|---------| | `floorplan/schema.py` | Pydantic data models — `Wall`, `Opening`, `Room`, `FloorPlan`, `Correction` | | `floorplan/geometry.py` | Computational geometry — wall polygons, room detection, centerline ops | | `floorplan/renderer.py` | SVG + PIL rendering for visual verification and overlay | | `floorplan/parser.py` | VLM-based parsing with iterative correction loop | ## Quick Start ### Demo (no API key needed) ```bash pip install pydantic shapely numpy pillow python example.py --demo ``` Renders a 2-bedroom apartment with angled walls → `output/demo_floorplan.png` + `.svg` + `.json` ### Parse a real floor plan ```bash pip install pydantic shapely numpy pillow openai python example.py --image myfloorplan.png --api-key sk-... ``` Or with a local model (vLLM, Ollama, etc.): ```bash python example.py --image myfloorplan.png --base-url http://localhost:8000/v1 --model qwen2.5-vl-72b ``` ### Python API ```python from floorplan import FloorPlan, Wall, Opening, OpeningType, Point2D from floorplan import build_rooms, render_to_image, render_floorplan_svg # Build a floor plan programmatically walls = [ Wall(id="w1", centerline=[Point2D(x=0, y=0), Point2D(x=5, y=0)], thickness=0.24, openings=[Opening(id="d1", type=OpeningType.DOOR, start=1.0, length=0.9)]), Wall(id="w2", centerline=[Point2D(x=5, y=0), Point2D(x=5, y=4)], thickness=0.24), Wall(id="w3", centerline=[Point2D(x=5, y=4), Point2D(x=0, y=4)], thickness=0.24), Wall(id="w4", centerline=[Point2D(x=0, y=4), Point2D(x=0, y=0)], thickness=0.24), ] rooms, room_polygons = build_rooms(walls) fp = FloorPlan(walls=walls, rooms=rooms) # Render img = render_to_image(fp, room_polygons=room_polygons) img.save("output.png") # Export SVG svg = render_floorplan_svg(fp, room_polygons=room_polygons) # Serialize to JSON print(fp.model_dump_json(indent=2)) ``` ### VLM parsing with correction loop ```python from floorplan import parse_floorplan fp, room_polygons, overlays = parse_floorplan( image="floorplan.png", api_key="sk-...", model="gpt-4o", max_iterations=4, ) # overlays contains the render-on-original images for each iteration for i, overlay in enumerate(overlays): overlay.save(f"overlay_{i}.png") ``` ## Features - ✅ **Wall thickness** — not just centerlines - ✅ **Non-rectangular rooms** — any angles - ✅ **Curved walls** — polyline approximation - ✅ **Automatic room detection** — from wall topology via Shapely - ✅ **Doors & windows** — parametric on walls - ✅ **SVG + PNG rendering** — dual output - ✅ **Overlay verification** — rendered schema composited on original - ✅ **Iterative VLM correction** — parse → render → compare → correct → repeat - ✅ **JSON serialization** — full Pydantic roundtrip - ✅ **Field-level corrections** — modify, add, delete walls/openings ## Dependencies **Core** (always needed): - `pydantic` — schema validation - `shapely` — computational geometry - `numpy` — array ops - `pillow` — image rendering **VLM parsing** (optional): - `openai` — for VLM API calls (works with any OpenAI-compatible endpoint) ## License MIT