floorplan-parser / README.md
rikhoffbauer2's picture
Upload README.md
39bf1f4 verified
|
raw
history blame
5.96 kB

🏠 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.

{
  "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)

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

pip install pydantic shapely numpy pillow openai
python example.py --image myfloorplan.png --api-key sk-...

Or with a local model (vLLM, Ollama, etc.):

python example.py --image myfloorplan.png --base-url http://localhost:8000/v1 --model qwen2.5-vl-72b

Python API

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

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