Qistinasofea commited on
Commit
7f550d4
Β·
verified Β·
1 Parent(s): a529afb

upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +115 -5
  2. app.py +289 -0
  3. requirements.txt +9 -0
README.md CHANGED
@@ -1,13 +1,123 @@
1
  ---
2
- title: Controlnet Floorplan Demo
3
- emoji: πŸŒ–
4
- colorFrom: indigo
5
  colorTo: green
6
  sdk: gradio
7
- sdk_version: 6.2.0
8
  app_file: app.py
9
  pinned: false
10
  license: mit
 
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Draw Your Floorplan - ControlNet
3
+ emoji: 🏠
4
+ colorFrom: blue
5
  colorTo: green
6
  sdk: gradio
7
+ sdk_version: 4.44.0
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
+ models:
12
+ - Qistinasofea/controlnet-floorplan
13
+ - stable-diffusion-v1-5/stable-diffusion-v1-5
14
  ---
15
 
16
+ # 🏠 Draw Your Floorplan - ControlNet
17
+
18
+ **AI54 Final Project - Spatially Conditioned Floorplan Generation**
19
+
20
+ ## 🎨 Interactive Demo
21
+
22
+ This Space allows you to **draw colored segmentation masks** and generate architectural floorplans using a fine-tuned ControlNet model.
23
+
24
+ ### How to Use:
25
+
26
+ 1. **Draw** colored regions on the canvas - each color represents a different room type
27
+ 2. **Describe** your floorplan in the text box
28
+ 3. **Adjust** settings if needed (inference steps, control strength, seed)
29
+ 4. Click **Generate Floorplan** to see your AI-generated layout!
30
+
31
+ ### Suggested Colors:
32
+ - πŸ”΄ Red - Living room / Main spaces
33
+ - 🟒 Green - Bedrooms
34
+ - πŸ”΅ Blue - Bathrooms
35
+ - 🟑 Yellow - Kitchen
36
+ - 🟣 Purple - Dining area
37
+ - 🟠 Orange - Office / Study
38
+ - 🩡 Cyan - Utility / Storage
39
+
40
+ ---
41
+
42
+ ## πŸ“Š Model Information
43
+
44
+ ### Training Details:
45
+ - **Method:** Full ControlNet Fine-Tuning
46
+ - **Base Model:** Stable Diffusion 1.5 (frozen)
47
+ - **ControlNet:** Segmentation variant (fully trained)
48
+ - **Dataset:** 11,375 orientation-normalized floorplan samples
49
+ - **Parameters:** 361M trainable parameters (100% of ControlNet)
50
+ - **Training Steps:** 10,000
51
+ - **Final Loss:** 0.0887
52
+ - **Training Time:** 3.7 hours on T4 GPU
53
+
54
+ ### Architecture:
55
+ The model uses a two-stage architecture:
56
+ 1. **Base Model (SD 1.5):** Generates realistic textures and appearance (frozen weights)
57
+ 2. **ControlNet:** Guides spatial structure based on colored segmentation input (fully fine-tuned)
58
+
59
+ This separation allows the model to:
60
+ - βœ… Preserve spatial layouts from user drawings
61
+ - βœ… Generate realistic architectural details
62
+ - βœ… Maintain consistent room boundaries
63
+ - βœ… Produce diverse outputs from the same layout
64
+
65
+ ---
66
+
67
+ ## πŸ”— Links
68
+
69
+ - **Trained Model:** [Qistinasofea/controlnet-floorplan](https://huggingface.co/Qistinasofea/controlnet-floorplan)
70
+ - **Dataset:** [Qistinasofea/floorplan-12k-aligned](https://huggingface.co/datasets/Qistinasofea/floorplan-12k-aligned)
71
+ - **Training Notebook:** Available in model repository
72
+
73
+ ---
74
+
75
+ ## πŸŽ“ Academic Context
76
+
77
+ This is a final project for **AI54: Artificial Intelligence course** focused on:
78
+ - Conditional image generation
79
+ - Spatial control in diffusion models
80
+ - ControlNet architecture and training
81
+ - Parameter-efficient fine-tuning considerations
82
+ - Real-world application development
83
+
84
+ ### Key Contributions:
85
+ 1. **Dataset Preprocessing:** Orientation normalization using PCA-based rotation alignment
86
+ 2. **Training Strategy:** Full fine-tuning justified by dataset size (11,375 samples)
87
+ 3. **User Interface:** Visual layout-driven interaction for non-technical users
88
+
89
+ ---
90
+
91
+ ## πŸ’» Technical Stack
92
+
93
+ - **Framework:** πŸ€— Diffusers
94
+ - **Model:** ControlNet + Stable Diffusion 1.5
95
+ - **Interface:** Gradio
96
+ - **Deployment:** HuggingFace Spaces
97
+ - **Hardware:** GPU-enabled (T4 or better recommended)
98
+
99
+ ---
100
+
101
+ ## πŸ“ Citation
102
+
103
+ If you use this model or approach in your work, please cite:
104
+
105
+ ```
106
+ @misc{controlnet-floorplan-2024,
107
+ author = {Qistinasofea},
108
+ title = {ControlNet for Floorplan Generation},
109
+ year = {2024},
110
+ publisher = {HuggingFace},
111
+ howpublished = {\url{https://huggingface.co/Qistinasofea/controlnet-floorplan}}
112
+ }
113
+ ```
114
+
115
+ ---
116
+
117
+ ## πŸ“„ License
118
+
119
+ This project is released under the MIT License. The base Stable Diffusion 1.5 model follows its original CreativeML Open RAIL-M license.
120
+
121
+ ---
122
+
123
+ **Built with ❀️ for AI54 Final Project**
app.py ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ from diffusers import StableDiffusionControlNetPipeline, ControlNetModel, UniPCMultistepScheduler
4
+ from PIL import Image
5
+ import numpy as np
6
+
7
+ # ============================================================================
8
+ # MODEL LOADING
9
+ # ============================================================================
10
+
11
+ print("πŸ”„ Loading ControlNet Floorplan model...")
12
+
13
+ # Load trained ControlNet
14
+ controlnet = ControlNetModel.from_pretrained(
15
+ "Qistinasofea/controlnet-floorplan",
16
+ torch_dtype=torch.float16
17
+ )
18
+
19
+ # Create pipeline
20
+ pipe = StableDiffusionControlNetPipeline.from_pretrained(
21
+ "stable-diffusion-v1-5/stable-diffusion-v1-5",
22
+ controlnet=controlnet,
23
+ torch_dtype=torch.float16,
24
+ safety_checker=None
25
+ )
26
+
27
+ # Use faster scheduler
28
+ pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)
29
+
30
+ # Move to GPU if available
31
+ device = "cuda" if torch.cuda.is_available() else "cpu"
32
+ pipe = pipe.to(device)
33
+
34
+ print(f"βœ… Model loaded on {device}!")
35
+
36
+ # ============================================================================
37
+ # GENERATION FUNCTION
38
+ # ============================================================================
39
+
40
+ def generate_floorplan(
41
+ segmentation_mask,
42
+ prompt,
43
+ num_steps,
44
+ conditioning_scale,
45
+ seed
46
+ ):
47
+ """
48
+ Generate floorplan from colored segmentation mask
49
+
50
+ Args:
51
+ segmentation_mask: User-drawn colored layout
52
+ prompt: Text description
53
+ num_steps: Number of diffusion steps
54
+ conditioning_scale: ControlNet influence strength
55
+ seed: Random seed for reproducibility
56
+ """
57
+
58
+ if segmentation_mask is None:
59
+ return None, "⚠️ Please draw a layout first!"
60
+
61
+ try:
62
+ # Handle Gradio ImageEditor format
63
+ if isinstance(segmentation_mask, dict):
64
+ # Extract the composite image
65
+ if 'composite' in segmentation_mask:
66
+ segmentation_mask = segmentation_mask['composite']
67
+ elif 'background' in segmentation_mask:
68
+ segmentation_mask = segmentation_mask['background']
69
+
70
+ # Convert to PIL Image
71
+ if isinstance(segmentation_mask, np.ndarray):
72
+ segmentation_mask = Image.fromarray(segmentation_mask)
73
+
74
+ # Ensure RGB and correct size
75
+ segmentation_mask = segmentation_mask.convert('RGB')
76
+ segmentation_mask = segmentation_mask.resize((512, 512), Image.LANCZOS)
77
+
78
+ # Generate floorplan
79
+ generator = torch.Generator(device=device).manual_seed(int(seed))
80
+
81
+ output = pipe(
82
+ prompt=prompt,
83
+ image=segmentation_mask,
84
+ num_inference_steps=int(num_steps),
85
+ controlnet_conditioning_scale=float(conditioning_scale),
86
+ generator=generator
87
+ ).images[0]
88
+
89
+ status = f"βœ… Generated successfully! (seed: {seed})"
90
+ return output, status
91
+
92
+ except Exception as e:
93
+ error_msg = f"❌ Error: {str(e)}"
94
+ print(error_msg)
95
+ return None, error_msg
96
+
97
+ # ============================================================================
98
+ # GRADIO INTERFACE
99
+ # ============================================================================
100
+
101
+ # Custom CSS for better styling
102
+ custom_css = """
103
+ #title {
104
+ text-align: center;
105
+ font-size: 2.5em;
106
+ font-weight: bold;
107
+ margin-bottom: 10px;
108
+ }
109
+ #subtitle {
110
+ text-align: center;
111
+ font-size: 1.2em;
112
+ color: #666;
113
+ margin-bottom: 20px;
114
+ }
115
+ .color-legend {
116
+ display: flex;
117
+ flex-wrap: wrap;
118
+ gap: 10px;
119
+ margin: 10px 0;
120
+ }
121
+ .color-item {
122
+ display: flex;
123
+ align-items: center;
124
+ gap: 5px;
125
+ }
126
+ .color-box {
127
+ width: 20px;
128
+ height: 20px;
129
+ border: 1px solid #ccc;
130
+ }
131
+ """
132
+
133
+ # Create interface
134
+ with gr.Blocks(css=custom_css, title="Draw Your Floorplan") as demo:
135
+
136
+ # Header
137
+ gr.HTML("<h1 id='title'>🏠 Draw Your Floorplan</h1>")
138
+ gr.HTML("<p id='subtitle'>AI54 Final Project - ControlNet for Architectural Layout Generation</p>")
139
+
140
+ gr.Markdown("""
141
+ ### πŸ“ How to Use:
142
+ 1. **Draw** colored regions on the canvas - each color represents a room type
143
+ 2. **Describe** your floorplan in the text box
144
+ 3. **Adjust** settings if needed (optional)
145
+ 4. Click **Generate Floorplan** 🎨
146
+
147
+ ### 🎨 Suggested Colors:
148
+ - πŸ”΄ **Red** - Living room / Main spaces
149
+ - 🟒 **Green** - Bedrooms
150
+ - πŸ”΅ **Blue** - Bathrooms
151
+ - 🟑 **Yellow** - Kitchen
152
+ - 🟣 **Purple** - Dining area
153
+ - 🟠 **Orange** - Office / Study
154
+ - 🩡 **Cyan** - Utility / Storage
155
+ - 🟀 **Brown** - Corridors / Hallways
156
+ """)
157
+
158
+ with gr.Row():
159
+ # LEFT COLUMN - Input
160
+ with gr.Column(scale=1):
161
+ gr.Markdown("### 🎨 Step 1: Draw Your Layout")
162
+
163
+ # Drawing canvas
164
+ input_image = gr.ImageEditor(
165
+ label="Draw colored regions (each color = room type)",
166
+ type="numpy",
167
+ image_mode="RGB",
168
+ brush=gr.Brush(
169
+ colors=["#FF0000", "#00FF00", "#0000FF", "#FFFF00",
170
+ "#FF00FF", "#FFA500", "#00FFFF", "#8B4513"],
171
+ default_size=20
172
+ ),
173
+ height=512,
174
+ width=512
175
+ )
176
+
177
+ gr.Markdown("### πŸ“ Step 2: Describe Your Floorplan")
178
+
179
+ prompt = gr.Textbox(
180
+ label="Text Description",
181
+ placeholder="Example: A modern apartment with 2 bedrooms, kitchen, and living room",
182
+ value="A residential floorplan with multiple rooms",
183
+ lines=3
184
+ )
185
+
186
+ # Advanced settings
187
+ with gr.Accordion("βš™οΈ Advanced Settings", open=False):
188
+ num_steps = gr.Slider(
189
+ minimum=10,
190
+ maximum=50,
191
+ value=20,
192
+ step=1,
193
+ label="Inference Steps (higher = better quality, slower)"
194
+ )
195
+
196
+ conditioning_scale = gr.Slider(
197
+ minimum=0.5,
198
+ maximum=2.0,
199
+ value=1.0,
200
+ step=0.1,
201
+ label="Control Strength (how closely to follow your drawing)"
202
+ )
203
+
204
+ seed = gr.Slider(
205
+ minimum=0,
206
+ maximum=999999,
207
+ value=42,
208
+ step=1,
209
+ label="Random Seed (for reproducibility)"
210
+ )
211
+
212
+ # Generate button
213
+ generate_btn = gr.Button("🎨 Generate Floorplan", variant="primary", size="lg")
214
+
215
+ # RIGHT COLUMN - Output
216
+ with gr.Column(scale=1):
217
+ gr.Markdown("### πŸ–ΌοΈ Generated Floorplan")
218
+
219
+ output_image = gr.Image(
220
+ label="Your AI-Generated Floorplan",
221
+ type="pil",
222
+ height=512
223
+ )
224
+
225
+ status_text = gr.Textbox(
226
+ label="Status",
227
+ value="Draw a layout and click Generate!",
228
+ interactive=False
229
+ )
230
+
231
+ gr.Markdown("""
232
+ ### πŸ’‘ Tips for Best Results:
233
+ - Draw clear, distinct colored regions
234
+ - Use different colors for different room types
235
+ - Make rooms rectangular for better results
236
+ - Add a descriptive text prompt
237
+ - Experiment with different seeds for variety!
238
+
239
+ ### πŸ“Š Model Info:
240
+ - **Training:** Full ControlNet fine-tuning on 11,375 samples
241
+ - **Architecture:** SD 1.5 + ControlNet Segmentation
242
+ - **Parameters:** 361M trainable parameters
243
+ - **Final Loss:** 0.0887
244
+ """)
245
+
246
+ # Examples section
247
+ gr.Markdown("---")
248
+ gr.Markdown("### πŸ“‹ Example Layouts")
249
+ gr.Markdown("Click an example below to try it out!")
250
+
251
+ # Note: You'll need to add actual example images
252
+ # For now, using placeholders
253
+ gr.Examples(
254
+ examples=[
255
+ [None, "A small studio apartment with combined living and sleeping area", 20, 1.0, 42],
256
+ [None, "A two-bedroom apartment with separate kitchen and bathroom", 20, 1.0, 123],
257
+ [None, "An office space with multiple workrooms and meeting area", 20, 1.0, 456],
258
+ ],
259
+ inputs=[input_image, prompt, num_steps, conditioning_scale, seed],
260
+ outputs=[output_image, status_text],
261
+ fn=generate_floorplan,
262
+ cache_examples=False,
263
+ )
264
+
265
+ # Footer
266
+ gr.Markdown("---")
267
+ gr.Markdown("""
268
+ ### πŸŽ“ AI54 Final Project
269
+ **Student:** Qistinasofea
270
+ **Model:** [Qistinasofea/controlnet-floorplan](https://huggingface.co/Qistinasofea/controlnet-floorplan)
271
+ **Dataset:** [Qistinasofea/floorplan-12k-aligned](https://huggingface.co/datasets/Qistinasofea/floorplan-12k-aligned)
272
+
273
+ Built with πŸ€— Diffusers, Gradio, and ControlNet
274
+ """)
275
+
276
+ # Connect button to function
277
+ generate_btn.click(
278
+ fn=generate_floorplan,
279
+ inputs=[input_image, prompt, num_steps, conditioning_scale, seed],
280
+ outputs=[output_image, status_text]
281
+ )
282
+
283
+ # ============================================================================
284
+ # LAUNCH
285
+ # ============================================================================
286
+
287
+ if __name__ == "__main__":
288
+ demo.queue() # Enable queuing for better performance
289
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ diffusers==0.30.0
4
+ transformers
5
+ accelerate
6
+ gradio
7
+ Pillow
8
+ numpy
9
+ safetensors