Spaces:
Sleeping
Sleeping
File size: 5,920 Bytes
64e387f f1c6a8d 64e387f d22607c 64e387f d22607c 64e387f d22607c 64e387f d22607c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | import gradio as gr
from PIL import Image, ImageDraw
import tempfile
import json
import os
import requests
from gradio_client import utils as gradio_client_utils
_original_json_schema_to_python_type = gradio_client_utils._json_schema_to_python_type
def _safe_json_schema_to_python_type(schema, defs=None):
"""Compatibility patch for Gradio 4.44 / gradio_client 1.3 schema parsing.
Some component schemas contain additionalProperties as a boolean. Older
gradio_client assumes that value is always a dict and crashes while building
API info during Space startup.
"""
if isinstance(schema, bool):
return "Any"
if isinstance(schema, dict) and isinstance(schema.get("additionalProperties"), bool):
schema = dict(schema)
schema["additionalProperties"] = {}
return _original_json_schema_to_python_type(schema, defs)
gradio_client_utils._json_schema_to_python_type = _safe_json_schema_to_python_type
# Roboflow API configuration
ROBOFLOW_API_KEY = os.getenv("ROBOFLOW_API_KEY")
ROOM_MODEL = "room-segmentation-frntt/1"
DOOR_WINDOW_MODEL = "door-detection-model/2"
color_options = ["Red", "Green", "Blue", "Yellow"]
layer_options = ["Room Detection", "Doors and Windows Detection"]
def roboflow_infer(image_path, model_id, api_key):
"""Direct HTTP call to Roboflow inference API"""
if not api_key:
return {"predictions": [], "error": "Missing ROBOFLOW_API_KEY Space secret"}
url = f"https://detect.roboflow.com/{model_id}"
params = {"api_key": api_key}
with open(image_path, "rb") as f:
files = {"file": f}
response = requests.post(url, params=params, files=files)
if response.status_code == 200:
return response.json()
else:
print(f"API Error: {response.status_code} - {response.text}")
return {"predictions": []}
def apply_zoom(image, zoom_factor):
width, height = image.size
new_width = int(width * zoom_factor)
new_height = int(height * zoom_factor)
return image.resize((new_width, new_height))
def detect_and_draw(image_path, model_id, filter_classes=None, color_choice=None):
result = roboflow_infer(image_path, model_id, ROBOFLOW_API_KEY)
original_img = Image.open(image_path)
overlayed_img = original_img.copy()
draw = ImageDraw.Draw(overlayed_img)
counts = {}
for prediction in result.get('predictions', []):
pred_class = prediction.get('class', '').lower()
if filter_classes and pred_class not in filter_classes:
continue
counts[pred_class] = counts.get(pred_class, 0) + 1
x = int(prediction['x'] - prediction['width'] / 2)
y = int(prediction['y'] - prediction['height'] / 2)
width = int(prediction['width'])
height = int(prediction['height'])
draw.rectangle([x, y, x + width, y + height], outline=color_choice, width=2)
label = f"{pred_class}"
draw.text((x, y - 10), label, fill=color_choice)
return overlayed_img, counts
def process_floor_plan(image, zoom_factor, color_choice, selected_layers):
try:
if image is None:
return None, None, json.dumps({"error": "Please upload a floor plan image."}, indent=2)
selected_layers = selected_layers or []
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp_file:
image.save(temp_file.name)
temp_file_path = temp_file.name
zoomed_image = apply_zoom(Image.open(temp_file_path), zoom_factor)
zoomed_image.save(temp_file_path)
room_overlay = None
dw_overlay = None
if "Room Detection" in selected_layers:
room_overlay, room_counts = detect_and_draw(
temp_file_path,
ROOM_MODEL,
filter_classes=["room"],
color_choice=color_choice
)
else:
room_counts = {}
if "Doors and Windows Detection" in selected_layers:
dw_overlay, dw_counts = detect_and_draw(
temp_file_path,
DOOR_WINDOW_MODEL,
filter_classes=["door", "window"],
color_choice=color_choice
)
else:
dw_counts = {}
combined_counts = {}
combined_counts.update(room_counts)
combined_counts.update(dw_counts)
return room_overlay, dw_overlay, json.dumps(combined_counts, indent=2)
except Exception as e:
return None, None, json.dumps({"error": str(e)}, indent=2)
# Gradio 5.x Interface
with gr.Blocks(title="Floor Plan Detection") as demo:
gr.Markdown("# 🏗️ Floor Plan Detection")
gr.Markdown("Upload a floor plan image to detect rooms, doors, and windows.")
with gr.Row():
with gr.Column():
input_image = gr.Image(type="pil", label="Upload Floor Plan")
zoom_factor = gr.Slider(minimum=0.5, maximum=3.0, value=1.0, step=0.1, label="Zoom Factor")
color_choice = gr.Dropdown(choices=color_options, value="Red", label="Annotation Color")
selected_layers = gr.CheckboxGroup(choices=layer_options, value=layer_options, label="Detection Layers")
process_btn = gr.Button("Process", variant="primary")
with gr.Column():
room_output = gr.Image(type="pil", label="Room Detection")
door_window_output = gr.Image(type="pil", label="Doors and Windows Detection")
output_json = gr.Textbox(label="Detection Results (JSON)", lines=10)
process_btn.click(
fn=process_floor_plan,
inputs=[input_image, zoom_factor, color_choice, selected_layers],
outputs=[room_output, door_window_output, output_json]
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860, show_api=False)
|