SpacelyJohn commited on
Commit
c00b86e
ยท
verified ยท
1 Parent(s): 495b6e6

Upload 7 files

Browse files
Files changed (2) hide show
  1. app_gradio.py +8 -9
  2. app_gradio_backup.py +299 -0
app_gradio.py CHANGED
@@ -405,8 +405,8 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
405
 
406
  # Create mask based on selected mode
407
  if inpainting_mode == "smart":
408
- print(f"Creating smart mask for image size: {resized_image.size}")
409
- mask_image = create_smart_mask(resized_image)
410
 
411
  # Simple, direct furniture prompt for smart mode
412
  if room_type == "Living Room":
@@ -418,7 +418,7 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
418
  elif room_type == "Dining Room":
419
  furniture_items = "dining table, dining chairs, sideboard"
420
  elif room_type == "Home Office":
421
- furniture_items = "desk, office chair, bookshelf, filing cabinet"
422
  elif room_type == "Bathroom":
423
  furniture_items = "vanity, mirror, storage cabinet"
424
  else:
@@ -431,10 +431,9 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
431
  prompt = f"photorealistic interior design, {detailed_prompt}, professionally photographed, architectural photography, natural lighting, ultra-realistic, high resolution, sharp focus, interior design magazine quality, realistic textures, realistic materials"
432
  print("Using full mask mode")
433
 
434
- # Generate image with original project settings
435
- # Adjust strength for smart mode - much stronger
436
- actual_strength = float(strength) * 1.5 if inpainting_mode == "smart" else float(strength)
437
- actual_strength = min(actual_strength, 0.95) # Higher cap for smart mode
438
 
439
  print(f"Generation parameters:")
440
  print(f" - Mode: {inpainting_mode}")
@@ -452,9 +451,9 @@ def design_space(input_image, room_type, design_style, inpainting_mode, num_step
452
  image=resized_image,
453
  mask_image=mask_image,
454
  control_image=[seg_control, mlsd_image],
455
- controlnet_conditioning_scale=[0.8, 0.4] if inpainting_mode == "smart" else [0.4, 0.2],
456
  control_guidance_start=[0, 0.1],
457
- control_guidance_end=[0.8, 0.4] if inpainting_mode == "smart" else [0.5, 0.25],
458
  ).images[0]
459
 
460
  # Restore original size
 
405
 
406
  # Create mask based on selected mode
407
  if inpainting_mode == "smart":
408
+ # For now, use full mask but with modified prompt for furniture placement
409
+ mask_image = create_full_mask(resized_image)
410
 
411
  # Simple, direct furniture prompt for smart mode
412
  if room_type == "Living Room":
 
418
  elif room_type == "Dining Room":
419
  furniture_items = "dining table, dining chairs, sideboard"
420
  elif room_type == "Home Office":
421
+ furniture_items = "desk, office chair, bookshelf, filing cabinet"
422
  elif room_type == "Bathroom":
423
  furniture_items = "vanity, mirror, storage cabinet"
424
  else:
 
431
  prompt = f"photorealistic interior design, {detailed_prompt}, professionally photographed, architectural photography, natural lighting, ultra-realistic, high resolution, sharp focus, interior design magazine quality, realistic textures, realistic materials"
432
  print("Using full mask mode")
433
 
434
+ # Generate image with original project settings
435
+ # Use normal strength for both modes now
436
+ actual_strength = float(strength)
 
437
 
438
  print(f"Generation parameters:")
439
  print(f" - Mode: {inpainting_mode}")
 
451
  image=resized_image,
452
  mask_image=mask_image,
453
  control_image=[seg_control, mlsd_image],
454
+ controlnet_conditioning_scale=[0.4, 0.2],
455
  control_guidance_start=[0, 0.1],
456
+ control_guidance_end=[0.5, 0.25],
457
  ).images[0]
458
 
459
  # Restore original size
app_gradio_backup.py ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import numpy as np
4
+ from PIL import Image
5
+ import os
6
+
7
+ # ๋ชจ๋ธ import๋“ค
8
+ try:
9
+ from diffusers import ControlNetModel, StableDiffusionControlNetInpaintPipeline, UniPCMultistepScheduler
10
+ from transformers import AutoImageProcessor, SegformerForSemanticSegmentation
11
+ from controlnet_aux import MLSDdetector
12
+ MLSD_AVAILABLE = True
13
+ except ImportError as e:
14
+ print(f"์ผ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋”ฉ ์‹คํŒจ: {e}")
15
+ MLSD_AVAILABLE = False
16
+
17
+ class SpacelyFurnitureDesigner:
18
+ def __init__(self):
19
+ self.pipe = None
20
+ self.seg_processor = None
21
+ self.segmentor = None
22
+ self.mlsd_processor = None
23
+
24
+ # ํšŒ์‚ฌ์šฉ ํ”„๋กฌํ”„ํŠธ ํ…œํ”Œ๋ฆฟ
25
+ self.office_templates = {
26
+ "๊ฐœ์ธ์‚ฌ๋ฌด์‹ค": "modern private office with executive desk, ergonomic chair, bookshelf, and professional lighting",
27
+ "ํšŒ์˜์‹ค": "professional conference room with large meeting table, comfortable chairs, whiteboard, and corporate lighting",
28
+ "ํœด๊ฒŒ์‹ค": "corporate break room with comfortable seating, coffee table, plants, and relaxing atmosphere",
29
+ "์˜คํ”ˆ์˜คํ”ผ์Šค": "open office space with multiple workstations, modern desks, office chairs, and collaborative areas",
30
+ "๋ฆฌ์…‰์…˜": "elegant reception area with reception desk, waiting chairs, company logo wall, and welcoming ambiance",
31
+ "CEO์‹ค": "luxury executive office with premium wooden desk, leather chair, awards display, and elegant lighting"
32
+ }
33
+
34
+ self.quality_suffix = "professional interior design, corporate style, clean, modern, functional, well-lit, 4K, high quality"
35
+
36
+ def load_models(self):
37
+ """๋ชจ๋ธ ์ง€์—ฐ ๋กœ๋”ฉ"""
38
+ if self.pipe is None:
39
+ print("๐Ÿ”„ AI ๋ชจ๋ธ ๋กœ๋”ฉ ์ค‘...")
40
+
41
+ try:
42
+ if MLSD_AVAILABLE and torch.cuda.is_available():
43
+ # ์ „์ฒด ControlNet ์„ค์ •
44
+ controlnet = [
45
+ ControlNetModel.from_pretrained("BertChristiaens/controlnet-seg-room", torch_dtype=torch.float16),
46
+ ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-mlsd", torch_dtype=torch.float16)
47
+ ]
48
+ self.mlsd_processor = MLSDdetector.from_pretrained("lllyasviel/Annotators")
49
+ else:
50
+ # ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜๋งŒ ์‚ฌ์šฉ
51
+ controlnet = ControlNetModel.from_pretrained("BertChristiaens/controlnet-seg-room", torch_dtype=torch.float16)
52
+
53
+ # ๋ฉ”์ธ ํŒŒ์ดํ”„๋ผ์ธ
54
+ self.pipe = StableDiffusionControlNetInpaintPipeline.from_pretrained(
55
+ "SG161222/Realistic_Vision_V3.0_VAE",
56
+ controlnet=controlnet,
57
+ safety_checker=None,
58
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32
59
+ )
60
+
61
+ self.pipe.scheduler = UniPCMultistepScheduler.from_config(self.pipe.scheduler.config)
62
+
63
+ if torch.cuda.is_available():
64
+ self.pipe = self.pipe.to("cuda")
65
+ try:
66
+ self.pipe.enable_xformers_memory_efficient_attention()
67
+ except:
68
+ pass
69
+
70
+ # ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜ ๋ชจ๋ธ
71
+ self.seg_processor = AutoImageProcessor.from_pretrained("nvidia/segformer-b5-finetuned-ade-640-640")
72
+ self.segmentor = SegformerForSemanticSegmentation.from_pretrained("nvidia/segformer-b5-finetuned-ade-640-640")
73
+
74
+ print("โœ… ๋ชจ๋ธ ๋กœ๋”ฉ ์™„๋ฃŒ!")
75
+
76
+ except Exception as e:
77
+ print(f"โŒ ๋ชจ๋ธ ๋กœ๋”ฉ ์‹คํŒจ: {e}")
78
+ return False
79
+
80
+ return True
81
+
82
+ def resize_dimensions(self, dimensions, target_size=768):
83
+ """๋น„์œจ ์œ ์ง€ํ•˜๋ฉฐ ๋ฆฌ์‚ฌ์ด์ฆˆ"""
84
+ width, height = dimensions
85
+ if width < target_size and height < target_size:
86
+ return dimensions
87
+ if width > height:
88
+ aspect_ratio = height / width
89
+ return (target_size, int(target_size * aspect_ratio))
90
+ else:
91
+ aspect_ratio = width / height
92
+ return (int(target_size * aspect_ratio), target_size)
93
+
94
+ def create_simple_mask(self, image):
95
+ """๊ฐ„๋‹จํ•œ ๋งˆ์Šคํฌ ์ƒ์„ฑ"""
96
+ # ์ „์ฒด ์ด๋ฏธ์ง€๋ฅผ ๋ณ€๊ฒฝ ๋Œ€์ƒ์œผ๋กœ ์„ค์ •
97
+ mask = Image.new('RGB', image.size, (255, 255, 255))
98
+ return image, mask
99
+
100
+ def design_space(self, input_image, space_type, custom_prompt="", num_steps=30, guidance_scale=12):
101
+ """๊ณต๊ฐ„ ๋””์ž์ธ ์ƒ์„ฑ ๋ฉ”์ธ ํ•จ์ˆ˜"""
102
+
103
+ if input_image is None:
104
+ return None, "โŒ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ด์ฃผ์„ธ์š”!"
105
+
106
+ # ๋ชจ๋ธ ๋กœ๋”ฉ
107
+ if not self.load_models():
108
+ return None, "โŒ AI ๋ชจ๋ธ ๋กœ๋”ฉ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค."
109
+
110
+ try:
111
+ # ํ”„๋กฌํ”„ํŠธ ๊ตฌ์„ฑ
112
+ if custom_prompt.strip():
113
+ base_prompt = custom_prompt
114
+ else:
115
+ base_prompt = self.office_templates.get(space_type, self.office_templates["๊ฐœ์ธ์‚ฌ๋ฌด์‹ค"])
116
+
117
+ full_prompt = f"{base_prompt}, {self.quality_suffix}"
118
+
119
+ # ์ด๋ฏธ์ง€ ์ „์ฒ˜๋ฆฌ
120
+ orig_w, orig_h = input_image.size
121
+ new_width, new_height = self.resize_dimensions(input_image.size, 768)
122
+ resized_image = input_image.resize((new_width, new_height))
123
+
124
+ # ๋งˆ์Šคํฌ ์ƒ์„ฑ
125
+ seg_image, mask_image = self.create_simple_mask(resized_image)
126
+
127
+ # ControlNet ์ด๋ฏธ์ง€ ์ค€๋น„
128
+ if MLSD_AVAILABLE and self.mlsd_processor:
129
+ mlsd_image = self.mlsd_processor(resized_image)
130
+ mlsd_image = mlsd_image.resize(resized_image.size)
131
+ control_images = [seg_image, mlsd_image]
132
+ controlnet_conditioning_scale = [0.4, 0.2]
133
+ control_guidance_start = [0, 0.1]
134
+ control_guidance_end = [0.5, 0.25]
135
+ else:
136
+ control_images = seg_image
137
+ controlnet_conditioning_scale = 0.4
138
+ control_guidance_start = 0
139
+ control_guidance_end = 0.5
140
+
141
+ # AI ์ด๋ฏธ์ง€ ์ƒ์„ฑ
142
+ result = self.pipe(
143
+ prompt=full_prompt,
144
+ negative_prompt="lowres, watermark, blurry, unprofessional, cluttered, outdated furniture, bad quality",
145
+ num_inference_steps=num_steps,
146
+ strength=0.8,
147
+ guidance_scale=guidance_scale,
148
+ image=resized_image,
149
+ mask_image=mask_image,
150
+ control_image=control_images,
151
+ controlnet_conditioning_scale=controlnet_conditioning_scale,
152
+ control_guidance_start=control_guidance_start,
153
+ control_guidance_end=control_guidance_end
154
+ ).images[0]
155
+
156
+ # ์›๋ณธ ํฌ๊ธฐ๋กœ ๋ณต์›
157
+ final_image = result.resize((orig_w, orig_h), Image.Resampling.LANCZOS)
158
+
159
+ success_msg = f"โœ… {space_type} ๋””์ž์ธ ์™„๋ฃŒ!\n๐Ÿ“ ์‚ฌ์šฉ๋œ ํ”„๋กฌํ”„ํŠธ: {full_prompt[:100]}..."
160
+
161
+ return final_image, success_msg
162
+
163
+ except Exception as e:
164
+ error_msg = f"โŒ ๋””์ž์ธ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
165
+ print(error_msg)
166
+ return None, error_msg
167
+
168
+ # ์ „์—ญ ๋””์ž์ด๋„ˆ ์ธ์Šคํ„ด์Šค
169
+ designer = SpacelyFurnitureDesigner()
170
+
171
+ def create_ui():
172
+ """Gradio UI ์ƒ์„ฑ"""
173
+
174
+ with gr.Blocks(
175
+ title="๐Ÿข Spacely AI ๊ฐ€๊ตฌ ๋ฐฐ์น˜ ๋””์ž์ด๋„ˆ",
176
+ theme=gr.themes.Soft(),
177
+ css="""
178
+ .gradio-container {
179
+ max-width: 1200px !important;
180
+ }
181
+ .title {
182
+ text-align: center;
183
+ color: #2D3748;
184
+ margin-bottom: 20px;
185
+ }
186
+ """
187
+ ) as demo:
188
+
189
+ gr.HTML("""
190
+ <div class="title">
191
+ <h1>๐Ÿข Spacely AI ๊ฐ€๊ตฌ ๋ฐฐ์น˜ ๋””์ž์ด๋„ˆ</h1>
192
+ <p>๋นˆ ๋ฐฉ ์‚ฌ์ง„์„ ์—…๋กœ๋“œํ•˜๋ฉด AI๊ฐ€ ์ „๋ฌธ์ ์ธ ์˜คํ”ผ์Šค ๊ณต๊ฐ„์œผ๋กœ ๋””์ž์ธํ•ด๋“œ๋ฆฝ๋‹ˆ๋‹ค</p>
193
+ </div>
194
+ """)
195
+
196
+ with gr.Row():
197
+ # ์ž…๋ ฅ ์ปฌ๋Ÿผ
198
+ with gr.Column(scale=1):
199
+ gr.HTML("<h3>๐Ÿ“ ์ž…๋ ฅ ์„ค์ •</h3>")
200
+
201
+ input_image = gr.Image(
202
+ label="๋นˆ๋ฐฉ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ",
203
+ type="pil",
204
+ height=300
205
+ )
206
+
207
+ space_type = gr.Dropdown(
208
+ choices=list(designer.office_templates.keys()),
209
+ label="๊ณต๊ฐ„ ํƒ€์ž… ์„ ํƒ",
210
+ value="๊ฐœ์ธ์‚ฌ๋ฌด์‹ค"
211
+ )
212
+
213
+ custom_prompt = gr.Textbox(
214
+ label="์ปค์Šคํ…€ ํ”„๋กฌํ”„ํŠธ (์„ ํƒ์‚ฌํ•ญ)",
215
+ placeholder="์˜ˆ: minimalist CEO office with wooden desk...",
216
+ lines=3
217
+ )
218
+
219
+ with gr.Row():
220
+ num_steps = gr.Slider(
221
+ minimum=10,
222
+ maximum=50,
223
+ value=30,
224
+ step=5,
225
+ label="์ƒ์„ฑ ํ’ˆ์งˆ (๋†’์„์ˆ˜๋ก ๋А๋ฆผ)"
226
+ )
227
+
228
+ guidance_scale = gr.Slider(
229
+ minimum=5,
230
+ maximum=20,
231
+ value=12,
232
+ step=1,
233
+ label="ํ”„๋กฌํ”„ํŠธ ๋ฐ˜์˜๋„"
234
+ )
235
+
236
+ generate_btn = gr.Button(
237
+ "๐ŸŽจ AI ๋””์ž์ธ ์ƒ์„ฑ",
238
+ variant="primary",
239
+ size="lg"
240
+ )
241
+
242
+ # ์ถœ๋ ฅ ์ปฌ๋Ÿผ
243
+ with gr.Column(scale=1):
244
+ gr.HTML("<h3>โœจ ๋””์ž์ธ ๊ฒฐ๊ณผ</h3>")
245
+
246
+ output_image = gr.Image(
247
+ label="AI๊ฐ€ ๋””์ž์ธํ•œ ์˜คํ”ผ์Šค",
248
+ height=300
249
+ )
250
+
251
+ output_text = gr.Textbox(
252
+ label="์ƒ์„ฑ ๊ฒฐ๊ณผ",
253
+ lines=4,
254
+ max_lines=8
255
+ )
256
+
257
+ gr.HTML("""
258
+ <div style="margin-top: 20px; padding: 15px; background-color: #F7FAFC; border-radius: 10px;">
259
+ <h4>๐Ÿ’ก ์‚ฌ์šฉ ํŒ</h4>
260
+ <ul>
261
+ <li>๊น”๋”ํ•œ ๋นˆ๋ฐฉ ์‚ฌ์ง„์ผ์ˆ˜๋ก ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค</li>
262
+ <li>์ปค์Šคํ…€ ํ”„๋กฌํ”„ํŠธ๋กœ ์›ํ•˜๋Š” ๊ฐ€๊ตฌ๋‚˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค</li>
263
+ <li>์ƒ์„ฑ ํ’ˆ์งˆ์„ ๋†’์ด๋ฉด ๋” ์ •๊ตํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์ง€๋งŒ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค</li>
264
+ </ul>
265
+ </div>
266
+ """)
267
+
268
+ # ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
269
+ generate_btn.click(
270
+ fn=designer.design_space,
271
+ inputs=[input_image, space_type, custom_prompt, num_steps, guidance_scale],
272
+ outputs=[output_image, output_text]
273
+ )
274
+
275
+ # ์˜ˆ์‹œ ์ด๋ฏธ์ง€๋“ค
276
+ gr.HTML("<h3>๐Ÿ“ธ ์˜ˆ์‹œ ๊ฒฐ๊ณผ</h3>")
277
+
278
+ with gr.Row():
279
+ gr.Examples(
280
+ examples=[
281
+ ["๊ฐœ์ธ์‚ฌ๋ฌด์‹ค", "modern executive office with wooden desk"],
282
+ ["ํšŒ์˜์‹ค", "professional conference room for 10 people"],
283
+ ["ํœด๊ฒŒ์‹ค", "comfortable break room with plants and coffee area"],
284
+ ],
285
+ inputs=[space_type, custom_prompt],
286
+ label="๋น ๋ฅธ ์„ค์ • ์˜ˆ์‹œ"
287
+ )
288
+
289
+ return demo
290
+
291
+ # ์•ฑ ์‹คํ–‰
292
+ if __name__ == "__main__":
293
+ demo = create_ui()
294
+ demo.launch(
295
+ server_name="0.0.0.0",
296
+ server_port=7860,
297
+ show_error=True,
298
+ share=True # ๊ณต๊ฐœ URL ์ƒ์„ฑ
299
+ )