matanzig commited on
Commit
55d216b
ยท
verified ยท
1 Parent(s): f86e620

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -121
app.py CHANGED
@@ -4,13 +4,13 @@ import numpy as np
4
  import torch
5
  from transformers import CLIPProcessor, CLIPModel
6
  from datasets import load_dataset
7
- from diffusers import StableDiffusionPipeline, StableDiffusionInpaintPipeline
8
  from sklearn.metrics.pairwise import cosine_similarity
9
- from PIL import Image
10
  import warnings
11
  warnings.filterwarnings('ignore')
12
 
13
  custom_css = """
 
14
  body {
15
  background-image: url('https://huggingface.co/spaces/matanzig/Interior-Design-GenAI/resolve/main/viss.jpeg');
16
  background-size: 130% 130%;
@@ -32,6 +32,7 @@ body {
32
  border: 1px solid rgba(255, 255, 255, 0.1);
33
  }
34
 
 
35
  .visionary-title {
36
  font-size: 3.5rem;
37
  font-weight: 900;
@@ -48,6 +49,25 @@ body {
48
  cursor: pointer;
49
  }
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  .custom-card {
52
  background: rgba(15, 15, 15, 0.6) !important;
53
  border-radius: 20px !important;
@@ -57,10 +77,32 @@ body {
57
  box-shadow: 0 4px 15px rgba(0,0,0,0.4) !important;
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  .custom-score {
61
  background: rgba(10, 10, 10, 0.8) !important;
62
  border-radius: 12px !important;
63
  border: 1px solid rgba(255, 215, 0, 0.1) !important;
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
  button.primary {
@@ -68,26 +110,17 @@ button.primary {
68
  border: 1px solid rgba(255, 215, 0, 0.4) !important;
69
  color: #ffd700 !important;
70
  text-transform: uppercase;
 
71
  font-weight: bold !important;
 
72
  }
73
 
74
  button.primary:hover {
75
  background: linear-gradient(90deg, #252525, #353535) !important;
76
  border: 1px solid rgba(255, 215, 0, 0.8) !important;
 
77
  transform: translateY(-2px) !important;
78
  }
79
-
80
- .edit-btn {
81
- background: rgba(20, 20, 20, 0.8) !important;
82
- border: 1px solid rgba(255, 215, 0, 0.3) !important;
83
- color: #ffd700 !important;
84
- margin-top: 5px !important;
85
- }
86
-
87
- .edit-btn:hover {
88
- background: rgba(255, 215, 0, 0.15) !important;
89
- border: 1px solid rgba(255, 215, 0, 0.8) !important;
90
- }
91
  """
92
 
93
  # --- 1. Load Dataset & Embeddings ---
@@ -111,11 +144,6 @@ pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4",
111
  pipe = pipe.to(device)
112
  pipe.enable_attention_slicing()
113
 
114
- print("Loading Stable Diffusion Inpainting Model...")
115
- inpaint_pipe = StableDiffusionInpaintPipeline.from_pretrained("runwayml/stable-diffusion-inpainting", torch_dtype=torch.float32)
116
- inpaint_pipe = inpaint_pipe.to(device)
117
- inpaint_pipe.enable_attention_slicing()
118
-
119
  # --- 3. Core Engine Logic ---
120
 
121
  def get_recommendations_from_vector(user_vector):
@@ -128,66 +156,48 @@ def get_recommendations_from_vector(user_vector):
128
  return recs[0], scores[0], recs[1], scores[1], recs[2], scores[2]
129
 
130
  def search_by_image(user_image):
131
- if user_image is None: return None, "", None, "", None, ""
 
 
132
  inputs = processor(images=user_image, return_tensors="pt").to(device)
133
  with torch.no_grad():
134
  features = clip_model.get_image_features(**inputs)
135
- features = features.pooler_output if hasattr(features, 'pooler_output') else features[0]
 
 
136
  user_vector = features.cpu().numpy().flatten().reshape(1, -1)
137
  return get_recommendations_from_vector(user_vector)
138
 
139
  def search_by_text_only(prompt):
140
- if not prompt: return None, "", None, "", None, ""
 
 
141
  inputs = processor(text=[prompt], return_tensors="pt", padding=True).to(device)
142
  with torch.no_grad():
143
  features = clip_model.get_text_features(**inputs)
144
- features = features.pooler_output if hasattr(features, 'pooler_output') else features[0]
 
 
145
  user_vector = features.cpu().numpy().flatten().reshape(1, -1)
146
  return get_recommendations_from_vector(user_vector)
147
 
148
  def generate_and_recommend(prompt):
149
- if not prompt: return None, None, "", None, "", None, ""
 
 
150
  generated_image = pipe(prompt, num_inference_steps=15).images[0]
 
151
  inputs = processor(images=generated_image, return_tensors="pt").to(device)
152
  with torch.no_grad():
153
  features = clip_model.get_image_features(**inputs)
154
- features = features.pooler_output if hasattr(features, 'pooler_output') else features[0]
 
 
155
  user_vector = features.cpu().numpy().flatten().reshape(1, -1)
156
  rec1, score1, rec2, score2, rec3, score3 = get_recommendations_from_vector(user_vector)
 
157
  return generated_image, rec1, score1, rec2, score2, rec3, score3
158
 
159
- # ืœื•ื’ื™ืงืช ื”ืžืขืงืฃ (Bypass) ื”ื—ื“ืฉื”
160
- def send_to_holding_state(img):
161
- """ ืฉื•ืžืจ ืืช ื”ืชืžื•ื ื” ื‘ื–ื™ื›ืจื•ืŸ ื”ืฉืจืช ื•ืžืขื‘ื™ืจ ืœื˜ืื‘ ื”ืžื˜ืจื” """
162
- return img, gr.update(selected="tab_magic")
163
-
164
- def load_into_editor(img_from_state):
165
- """ ื˜ื•ืขืŸ ืืช ื”ืชืžื•ื ื” ืœืชื•ืš ื”ืขื•ืจืš ื‘ืฆื•ืจื” ื‘ื˜ื•ื—ื” ื›ืฉื”ืžืกืš ืคืชื•ื— """
166
- if img_from_state is None:
167
- return None
168
- return {"background": img_from_state, "layers": [], "composite": None}
169
-
170
- def process_magic_edit(edit_dict, prompt):
171
- if not edit_dict or not prompt:
172
- return None
173
- try:
174
- bg = edit_dict.get("background")
175
- if not bg: return None
176
- bg = bg.convert("RGB").resize((512, 512))
177
-
178
- layers = edit_dict.get("layers", [])
179
- if layers and len(layers) > 0:
180
- mask = layers[0].convert("RGBA").split()[-1].resize((512, 512))
181
- else:
182
- mask = Image.new("L", (512, 512), 0)
183
-
184
- edited_image = inpaint_pipe(prompt=prompt, image=bg, mask_image=mask, num_inference_steps=20).images[0]
185
- return edited_image
186
- except Exception as e:
187
- print(f"Error during Magic Edit process: {e}")
188
- return None
189
-
190
-
191
  # --- 4. Gradio User Interface (Premium UI) ---
192
 
193
  custom_theme = gr.themes.Monochrome(
@@ -196,121 +206,108 @@ custom_theme = gr.themes.Monochrome(
196
  font=[gr.themes.GoogleFont("Montserrat"), "ui-sans-serif", "system-ui", "sans-serif"]
197
  )
198
 
199
- with gr.Blocks(title="Visionary | AI Interior Design", css=custom_css, theme=custom_theme) as demo:
200
-
201
- # ื”ื–ื™ื›ืจื•ืŸ ื”ื—ื‘ื•ื™ ืฉืœื ื•
202
- shared_edit_image = gr.State()
203
 
 
204
  gr.HTML("""
205
  <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 20px;">
206
  <img src="https://huggingface.co/spaces/matanzig/Interior-Design-GenAI/resolve/main/viss1.jpeg"
207
  style="height: 110px; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.8); margin-bottom: 10px;">
 
208
  <h1 class="visionary-title">VISIONARY</h1>
209
  <div class="visionary-subtitle">AI-Powered Interior Design Engine</div>
210
  </div>
211
  """)
212
 
213
- with gr.Tabs() as main_tabs:
214
 
215
- # --- TAB 1 ---
216
- with gr.TabItem("๐Ÿ–ผ๏ธ Search by Image", id="tab1"):
 
217
  with gr.Row():
218
  with gr.Column(scale=1):
219
  image_input = gr.Image(label="Upload Inspiration", type="pil", elem_classes="custom-card")
220
  img_submit_btn = gr.Button("Find Matches (Instant)", variant="primary")
 
221
  with gr.Column(scale=2):
222
  with gr.Row():
223
  with gr.Column():
224
- img_rec1 = gr.Image(label="Top Match", type="pil", elem_classes="custom-card")
225
  img_score1 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
226
- img_edit_btn1 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
227
  with gr.Column():
228
- img_rec2 = gr.Image(label="2nd Match", type="pil", elem_classes="custom-card")
229
  img_score2 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
230
- img_edit_btn2 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
231
  with gr.Column():
232
- img_rec3 = gr.Image(label="3rd Match", type="pil", elem_classes="custom-card")
233
  img_score3 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
234
- img_edit_btn3 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
235
- img_submit_btn.click(fn=search_by_image, inputs=[image_input], outputs=[img_rec1, img_score1, img_rec2, img_score2, img_rec3, img_score3])
236
-
237
- # --- TAB 2 ---
238
- with gr.TabItem("๐Ÿ” Fast Text Search", id="tab2"):
 
 
 
 
239
  with gr.Row():
240
  with gr.Column(scale=1):
241
  fast_text_input = gr.Textbox(label="Search Query", placeholder="e.g., A minimalist industrial bedroom...", lines=3)
242
  fast_txt_submit_btn = gr.Button("Search Catalog (Instant)", variant="primary")
243
- gr.Examples(["A minimalist industrial bedroom with concrete walls", "Luxury modern bathroom with marble and warm lights"], inputs=fast_text_input)
 
 
 
 
 
 
 
 
 
244
  with gr.Column(scale=2):
245
  with gr.Row():
246
  with gr.Column():
247
- ft_rec1 = gr.Image(label="Top Match", type="pil", elem_classes="custom-card")
248
  ft_score1 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
249
- ft_edit_btn1 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
250
  with gr.Column():
251
- ft_rec2 = gr.Image(label="2nd Match", type="pil", elem_classes="custom-card")
252
  ft_score2 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
253
- ft_edit_btn2 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
254
  with gr.Column():
255
- ft_rec3 = gr.Image(label="3rd Match", type="pil", elem_classes="custom-card")
256
  ft_score3 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
257
- ft_edit_btn3 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
258
- fast_txt_submit_btn.click(fn=search_by_text_only, inputs=[fast_text_input], outputs=[ft_rec1, ft_score1, ft_rec2, ft_score2, ft_rec3, ft_score3])
259
 
260
- # --- TAB 3 ---
261
- with gr.TabItem("โœจ AI Design Studio", id="tab3"):
 
 
 
 
 
 
262
  with gr.Row():
263
  with gr.Column(scale=1):
264
  text_input = gr.Textbox(label="Concept Description", placeholder="e.g., A cozy modern living room...", lines=3)
265
  txt_submit_btn = gr.Button("Generate Concept & Match", variant="primary")
266
  gen_output = gr.Image(label="AI Drafted Concept", type="pil", elem_classes="custom-card")
 
267
  with gr.Column(scale=2):
268
  with gr.Row():
269
  with gr.Column():
270
- txt_rec1 = gr.Image(label="Top Match", type="pil", elem_classes="custom-card")
271
  txt_score1 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
272
- txt_edit_btn1 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
273
  with gr.Column():
274
- txt_rec2 = gr.Image(label="2nd Match", type="pil", elem_classes="custom-card")
275
  txt_score2 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
276
- txt_edit_btn2 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
277
  with gr.Column():
278
- txt_rec3 = gr.Image(label="3rd Match", type="pil", elem_classes="custom-card")
279
  txt_score3 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
280
- txt_edit_btn3 = gr.Button("๐Ÿช„ Edit Match", elem_classes="edit-btn")
281
- txt_submit_btn.click(fn=generate_and_recommend, inputs=[text_input], outputs=[gen_output, txt_rec1, txt_score1, txt_rec2, txt_score2, txt_rec3, txt_score3])
282
-
283
- # --- TAB 4: Magic Edit (ื”ืžืขืงืฃ) ---
284
- with gr.TabItem("๐ŸŽจ Magic Edit", id="tab_magic"):
285
- gr.Markdown("Your selected match has been sent here. **Please follow the steps below to edit.**")
286
- with gr.Row():
287
- with gr.Column(scale=1):
288
- # ื›ืคืชื•ืจ ื”ื˜ืขื™ื ื” ื”ื—ื“ืฉ ืฉืคื•ืชืจ ืืช ื”ื‘ืื’
289
- load_magic_btn = gr.Button("1๏ธโƒฃ CLICK HERE FIRST: Load Image to Editor", variant="primary")
290
- magic_editor = gr.ImageEditor(label="2๏ธโƒฃ Paint over object", type="pil", elem_classes="custom-card", brush=gr.Brush(colors=["#FFFFFF"]))
291
- magic_prompt = gr.Textbox(label="3๏ธโƒฃ What do you want instead?", placeholder="e.g., A modern yellow leather sofa", lines=2)
292
- magic_submit_btn = gr.Button("4๏ธโƒฃ Apply Magic Edit", variant="primary")
293
-
294
- with gr.Column(scale=1):
295
- magic_output = gr.Image(label="Magic Result", type="pil", elem_classes="custom-card")
296
 
297
- # ืคืขื•ืœืช ื”ื˜ืขื™ื ื” ื”ื™ืฉื™ืจื”
298
- load_magic_btn.click(fn=load_into_editor, inputs=[shared_edit_image], outputs=[magic_editor])
299
-
300
- # ืคืขื•ืœืช ื”ืขืจื™ื›ื”
301
- magic_submit_btn.click(fn=process_magic_edit, inputs=[magic_editor, magic_prompt], outputs=[magic_output])
302
 
303
- # --- TAB 5 ---
304
- with gr.TabItem("๐ŸŽฅ Presentation Video", id="tab_video"):
 
305
  gr.Video(value="https://huggingface.co/spaces/matanzig/Interior-Design-GenAI/resolve/main/A3.presentation.mp4", interactive=False)
306
 
307
- # ื—ื™ื•ื•ื˜ ื”ื›ืคืชื•ืจื™ื ืืœ ื”ื–ื™ื›ืจื•ืŸ ื”ื—ื‘ื•ื™ ื•ื”ื—ืœืคืช ื”ื˜ืื‘
308
- edit_buttons_and_sources = [
309
- (img_edit_btn1, img_rec1), (img_edit_btn2, img_rec2), (img_edit_btn3, img_rec3),
310
- (ft_edit_btn1, ft_rec1), (ft_edit_btn2, ft_rec2), (ft_edit_btn3, ft_rec3),
311
- (txt_edit_btn1, txt_rec1), (txt_edit_btn2, txt_rec2), (txt_edit_btn3, txt_rec3)
312
- ]
313
- for btn, source_img in edit_buttons_and_sources:
314
- btn.click(fn=send_to_holding_state, inputs=[source_img], outputs=[shared_edit_image, main_tabs])
315
-
316
  demo.launch()
 
4
  import torch
5
  from transformers import CLIPProcessor, CLIPModel
6
  from datasets import load_dataset
7
+ from diffusers import StableDiffusionPipeline
8
  from sklearn.metrics.pairwise import cosine_similarity
 
9
  import warnings
10
  warnings.filterwarnings('ignore')
11
 
12
  custom_css = """
13
+
14
  body {
15
  background-image: url('https://huggingface.co/spaces/matanzig/Interior-Design-GenAI/resolve/main/viss.jpeg');
16
  background-size: 130% 130%;
 
32
  border: 1px solid rgba(255, 255, 255, 0.1);
33
  }
34
 
35
+
36
  .visionary-title {
37
  font-size: 3.5rem;
38
  font-weight: 900;
 
49
  cursor: pointer;
50
  }
51
 
52
+ .visionary-title:hover {
53
+ transform: scale(1.03);
54
+ text-shadow: 0px 0px 20px rgba(255, 215, 0, 0.4);
55
+ }
56
+
57
+ @keyframes goldShine {
58
+ 0% { background-position: 0% 50%; }
59
+ 50% { background-position: 100% 50%; }
60
+ 100% { background-position: 0% 50%; }
61
+ }
62
+
63
+ .visionary-subtitle {
64
+ text-align: center;
65
+ color: rgba(255, 255, 255, 0.7);
66
+ font-size: 1.2rem;
67
+ letter-spacing: 2px;
68
+ margin-bottom: 30px;
69
+ }
70
+
71
  .custom-card {
72
  background: rgba(15, 15, 15, 0.6) !important;
73
  border-radius: 20px !important;
 
77
  box-shadow: 0 4px 15px rgba(0,0,0,0.4) !important;
78
  }
79
 
80
+ .custom-card:hover {
81
+ transform: translateY(-5px) scale(1.01) !important;
82
+ border: 1px solid rgba(255, 215, 0, 0.6) !important;
83
+ box-shadow: 0 10px 30px rgba(255, 215, 0, 0.15) !important;
84
+ }
85
+
86
+ .custom-card img {
87
+ transition: transform 0.4s ease !important;
88
+ }
89
+ .custom-card:hover img {
90
+ transform: scale(1.05) !important;
91
+ }
92
+
93
  .custom-score {
94
  background: rgba(10, 10, 10, 0.8) !important;
95
  border-radius: 12px !important;
96
  border: 1px solid rgba(255, 215, 0, 0.1) !important;
97
+ transition: all 0.3s ease !important;
98
+ }
99
+
100
+ .custom-score:hover {
101
+ border: 1px solid rgba(255, 215, 0, 0.4) !important;
102
+ box-shadow: 0 0 15px rgba(255, 215, 0, 0.1) !important;
103
+ }
104
+ .custom-score:hover textarea {
105
+ color: #ffd700 !important;
106
  }
107
 
108
  button.primary {
 
110
  border: 1px solid rgba(255, 215, 0, 0.4) !important;
111
  color: #ffd700 !important;
112
  text-transform: uppercase;
113
+ letter-spacing: 1px;
114
  font-weight: bold !important;
115
+ transition: all 0.3s ease !important;
116
  }
117
 
118
  button.primary:hover {
119
  background: linear-gradient(90deg, #252525, #353535) !important;
120
  border: 1px solid rgba(255, 215, 0, 0.8) !important;
121
+ box-shadow: 0 0 15px rgba(255, 215, 0, 0.2) !important;
122
  transform: translateY(-2px) !important;
123
  }
 
 
 
 
 
 
 
 
 
 
 
 
124
  """
125
 
126
  # --- 1. Load Dataset & Embeddings ---
 
144
  pipe = pipe.to(device)
145
  pipe.enable_attention_slicing()
146
 
 
 
 
 
 
147
  # --- 3. Core Engine Logic ---
148
 
149
  def get_recommendations_from_vector(user_vector):
 
156
  return recs[0], scores[0], recs[1], scores[1], recs[2], scores[2]
157
 
158
  def search_by_image(user_image):
159
+ if user_image is None:
160
+ return None, "", None, "", None, ""
161
+
162
  inputs = processor(images=user_image, return_tensors="pt").to(device)
163
  with torch.no_grad():
164
  features = clip_model.get_image_features(**inputs)
165
+ if not isinstance(features, torch.Tensor):
166
+ features = features.pooler_output if hasattr(features, 'pooler_output') else features[0]
167
+
168
  user_vector = features.cpu().numpy().flatten().reshape(1, -1)
169
  return get_recommendations_from_vector(user_vector)
170
 
171
  def search_by_text_only(prompt):
172
+ if not prompt:
173
+ return None, "", None, "", None, ""
174
+
175
  inputs = processor(text=[prompt], return_tensors="pt", padding=True).to(device)
176
  with torch.no_grad():
177
  features = clip_model.get_text_features(**inputs)
178
+ if not isinstance(features, torch.Tensor):
179
+ features = features.pooler_output if hasattr(features, 'pooler_output') else features[0]
180
+
181
  user_vector = features.cpu().numpy().flatten().reshape(1, -1)
182
  return get_recommendations_from_vector(user_vector)
183
 
184
  def generate_and_recommend(prompt):
185
+ if not prompt:
186
+ return None, None, "", None, "", None, ""
187
+
188
  generated_image = pipe(prompt, num_inference_steps=15).images[0]
189
+
190
  inputs = processor(images=generated_image, return_tensors="pt").to(device)
191
  with torch.no_grad():
192
  features = clip_model.get_image_features(**inputs)
193
+ if not isinstance(features, torch.Tensor):
194
+ features = features.pooler_output if hasattr(features, 'pooler_output') else features[0]
195
+
196
  user_vector = features.cpu().numpy().flatten().reshape(1, -1)
197
  rec1, score1, rec2, score2, rec3, score3 = get_recommendations_from_vector(user_vector)
198
+
199
  return generated_image, rec1, score1, rec2, score2, rec3, score3
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  # --- 4. Gradio User Interface (Premium UI) ---
202
 
203
  custom_theme = gr.themes.Monochrome(
 
206
  font=[gr.themes.GoogleFont("Montserrat"), "ui-sans-serif", "system-ui", "sans-serif"]
207
  )
208
 
 
 
 
 
209
 
210
+ with gr.Blocks(title="Visionary | AI Interior Design", css=custom_css, theme=custom_theme) as demo:
211
  gr.HTML("""
212
  <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 20px;">
213
  <img src="https://huggingface.co/spaces/matanzig/Interior-Design-GenAI/resolve/main/viss1.jpeg"
214
  style="height: 110px; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.8); margin-bottom: 10px;">
215
+
216
  <h1 class="visionary-title">VISIONARY</h1>
217
  <div class="visionary-subtitle">AI-Powered Interior Design Engine</div>
218
  </div>
219
  """)
220
 
221
+ with gr.Tabs():
222
 
223
+ # --- TAB 1: Classic Search by Image ---
224
+ with gr.TabItem("๐Ÿ–ผ๏ธ Search by Image"):
225
+ gr.Markdown("Upload an inspiration photo to instantly discover visually and stylistically similar rooms from our curated catalog.")
226
  with gr.Row():
227
  with gr.Column(scale=1):
228
  image_input = gr.Image(label="Upload Inspiration", type="pil", elem_classes="custom-card")
229
  img_submit_btn = gr.Button("Find Matches (Instant)", variant="primary")
230
+
231
  with gr.Column(scale=2):
232
  with gr.Row():
233
  with gr.Column():
234
+ img_rec1 = gr.Image(label="Top Match", elem_classes="custom-card")
235
  img_score1 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
236
  with gr.Column():
237
+ img_rec2 = gr.Image(label="2nd Match", elem_classes="custom-card")
238
  img_score2 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
239
  with gr.Column():
240
+ img_rec3 = gr.Image(label="3rd Match", elem_classes="custom-card")
241
  img_score3 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
242
+
243
+ img_submit_btn.click(
244
+ fn=search_by_image, inputs=[image_input],
245
+ outputs=[img_rec1, img_score1, img_rec2, img_score2, img_rec3, img_score3]
246
+ )
247
+
248
+ # --- TAB 2: Fast Text Search (CLIP Multi-modal) ---
249
+ with gr.TabItem("๐Ÿ” Fast Text Search"):
250
+ gr.Markdown("Describe a room in text. Our multi-modal vision engine will instantly search the catalog for matching designs.")
251
  with gr.Row():
252
  with gr.Column(scale=1):
253
  fast_text_input = gr.Textbox(label="Search Query", placeholder="e.g., A minimalist industrial bedroom...", lines=3)
254
  fast_txt_submit_btn = gr.Button("Search Catalog (Instant)", variant="primary")
255
+
256
+ gr.Examples(
257
+ examples=[
258
+ "A minimalist industrial bedroom with concrete walls",
259
+ "Luxury modern bathroom with marble and warm lights",
260
+ "Bohemian living room with lots of plants and wood"
261
+ ],
262
+ inputs=fast_text_input
263
+ )
264
+
265
  with gr.Column(scale=2):
266
  with gr.Row():
267
  with gr.Column():
268
+ ft_rec1 = gr.Image(label="Top Match", elem_classes="custom-card")
269
  ft_score1 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
270
  with gr.Column():
271
+ ft_rec2 = gr.Image(label="2nd Match", elem_classes="custom-card")
272
  ft_score2 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
273
  with gr.Column():
274
+ ft_rec3 = gr.Image(label="3rd Match", elem_classes="custom-card")
275
  ft_score3 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
 
276
 
277
+ fast_txt_submit_btn.click(
278
+ fn=search_by_text_only, inputs=[fast_text_input],
279
+ outputs=[ft_rec1, ft_score1, ft_rec2, ft_score2, ft_rec3, ft_score3]
280
+ )
281
+
282
+ # --- TAB 3: Advanced GenAI Search ---
283
+ with gr.TabItem("โœจ AI Design Studio"):
284
+ gr.Markdown("Describe your ideal space. Our Generative AI will draft a concept from scratch, and then find the closest real-world equivalents.")
285
  with gr.Row():
286
  with gr.Column(scale=1):
287
  text_input = gr.Textbox(label="Concept Description", placeholder="e.g., A cozy modern living room...", lines=3)
288
  txt_submit_btn = gr.Button("Generate Concept & Match", variant="primary")
289
  gen_output = gr.Image(label="AI Drafted Concept", type="pil", elem_classes="custom-card")
290
+
291
  with gr.Column(scale=2):
292
  with gr.Row():
293
  with gr.Column():
294
+ txt_rec1 = gr.Image(label="Top Match", elem_classes="custom-card")
295
  txt_score1 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
296
  with gr.Column():
297
+ txt_rec2 = gr.Image(label="2nd Match", elem_classes="custom-card")
298
  txt_score2 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
299
  with gr.Column():
300
+ txt_rec3 = gr.Image(label="3rd Match", elem_classes="custom-card")
301
  txt_score3 = gr.Textbox(label="Confidence", interactive=False, elem_classes="custom-score")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
 
303
+ txt_submit_btn.click(
304
+ fn=generate_and_recommend, inputs=[text_input],
305
+ outputs=[gen_output, txt_rec1, txt_score1, txt_rec2, txt_score2, txt_rec3, txt_score3]
306
+ )
 
307
 
308
+ # --- TAB 4: Presentation Video ---
309
+ with gr.TabItem("๐ŸŽฅ Presentation Video"):
310
+ gr.Markdown("### ๐ŸŽ“ Project Presentation & Walkthrough \nWatch the video below to see a full walkthrough of the dataset, EDA, model pipeline, and the live application.")
311
  gr.Video(value="https://huggingface.co/spaces/matanzig/Interior-Design-GenAI/resolve/main/A3.presentation.mp4", interactive=False)
312
 
 
 
 
 
 
 
 
 
 
313
  demo.launch()