romi2001 commited on
Commit
0fd7577
·
verified ·
1 Parent(s): 7d63be3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -30
app.py CHANGED
@@ -143,20 +143,23 @@ def pil_to_base64(img, max_size=280):
143
  return base64.b64encode(buf.getvalue()).decode("utf-8")
144
 
145
  # ---------------------------------------------------------------------------
146
- # EMBEDDING + FAISS SEARCH (תיקון סופי ומאובטח לחילוץ הוקטורים מחבילת CLIP)
147
  # ---------------------------------------------------------------------------
148
  @torch.no_grad()
149
  def embed_query_image(pil_image):
150
  inputs = win_processor(images=pil_image, return_tensors="pt").to(DEVICE)
151
- outputs = win_model.get_image_features(**inputs)
152
- # חילוץ בטוח באמצעות בדיקת סוג האובייקט והפיכתו לטנסור טהור
153
- if hasattr(outputs, "image_embeds"):
 
154
  feats = outputs.image_embeds
155
- elif isinstance(outputs, getattr(gr, "__package__", object)) or not hasattr(outputs, "cpu"):
156
- feats = outputs[0] if (isinstance(outputs, tuple) or isinstance(outputs, list)) else outputs
 
 
157
  else:
158
  feats = outputs
159
-
160
  if hasattr(feats, "detach"):
161
  feats = feats.detach()
162
  return feats.cpu().numpy().astype("float32")
@@ -164,12 +167,15 @@ def embed_query_image(pil_image):
164
  @torch.no_grad()
165
  def embed_query_text(sentence):
166
  inputs = win_processor(text=[sentence], return_tensors="pt", padding=True, truncation=True).to(DEVICE)
167
- outputs = win_model.get_text_features(**inputs)
168
- # חילוץ בטוח באמצעות בדיקת סוג האובייקט והפיכתו לטנסור טהור
169
- if hasattr(outputs, "text_embeds"):
 
170
  feats = outputs.text_embeds
171
- elif isinstance(outputs, getattr(gr, "__package__", object)) or not hasattr(outputs, "cpu"):
172
- feats = outputs[0] if (isinstance(outputs, tuple) or isinstance(outputs, list)) else outputs
 
 
173
  else:
174
  feats = outputs
175
 
@@ -193,7 +199,7 @@ def faiss_filtered_search(query_emb, top_k=3, exclude_idx=None, gender=None, age
193
  if idx == -1 or (exclude_idx is not None and idx == exclude_idx):
194
  continue
195
  row = df.iloc[idx]
196
- if require_gender and gender and str(row["gender"]).lower() != str(gender).lower():
197
  continue
198
  if require_age and age_group and str(row["age_group"]).lower() != str(age_group).lower():
199
  continue
@@ -256,7 +262,6 @@ def generate_new_outfit_image(pil_image, row, target_gender=None):
256
  resized_protect_img = Image.fromarray(protect.astype(np.uint8) * 255).resize((head_w, head_h), resample=Image.NEAREST)
257
 
258
  canvas = Image.new("RGB", (canvas_w, canvas_h), color=(240, 238, 235))
259
- # תיקון קריטי: הגדרת משתני המיקום המקומיים לחישוב הקנבס
260
  paste_x = (canvas_w - head_w) // 2
261
  paste_y = int(canvas_h * 0.03)
262
  canvas.paste(resized_face_crop, (paste_x, paste_y))
@@ -292,18 +297,6 @@ def build_style_card_html(row, caption):
292
  html += f'</div>'
293
  return html
294
 
295
- def to_shop_link(retailer, value, gender=None):
296
- g = str(gender).strip().lower() if gender is not None else ""
297
- dept = "men" if g in ("male", "man", "men", "m") else "women"
298
- query_enc = urllib.parse.quote(str(value))
299
- if retailer == "zara":
300
- return f"https://www.zara.com/us/en/search?searchTerm={query_enc}"
301
- if retailer == "asos":
302
- return f"https://www.asos.com/us/search/?q={query_enc}"
303
- if retailer == "hm":
304
- return f"https://www2.hm.com/en_us/search-results.html?q={query_enc}"
305
- return f"https://www.google.com/search?q={retailer}+{query_enc}"
306
-
307
  def build_outfit_component_cards_html(row):
308
  colors = [c.strip() for c in str(row["recommended_colors"]).split(",") if c.strip()] or ["neutral"]
309
  components = [
@@ -423,6 +416,15 @@ h1, h2, h3, p, span, label, input, select, textarea, button { color: #2C2A29 !im
423
  .dark-panel { background: #FFFFFF !important; border-radius: 16px !important; padding: 24px !important; border: 1px solid #ECE4D6 !important; margin-bottom: 20px; }
424
  .dark-panel label, .dark-panel span { color: #2C2A29 !important; font-weight: 600; }
425
 
 
 
 
 
 
 
 
 
 
426
  .palette-premium-banner { background: #FAF3ED; padding: 24px; border-radius: 12px; margin-bottom: 20px; border-left: 5px solid #C69E6E; }
427
  .section-split { display: grid !important; grid-template-columns: repeat(2, 1fr) !important; gap: 20px !important; margin-top: 20px !important; width: 100% !important; }
428
  @media (max-width: 768px) { .section-split { grid-template-columns: 1fr !important; } }
@@ -446,7 +448,6 @@ h1, h2, h3, p, span, label, input, select, textarea, button { color: #2C2A29 !im
446
  .prod-title { font-size: 15px; font-weight: 700; color: #111111 !important; margin: 0 0 4px 0; line-height: 1.3; min-height: 40px; display: flex; align-items: center; }
447
  .prod-brand { font-size: 13px; color: #999999 !important; margin-bottom: 14px; display: block; }
448
 
449
- /* כפתורי הרכישה המקוריים */
450
  .shop-btn { display: block; width: 100%; background: #161617; color: #FFFFFF !important; text-align: center; padding: 11px 0; border-radius: 8px; font-size: 13px; font-weight: 700; text-decoration: none !important; letter-spacing: 0.5px; }
451
  .shop-btn:hover { background: #2D2D2F; color: #FFFFFF !important; }
452
  .more-matches-label { font-size: 11px; font-weight: 700; color: #9C8E82 !important; letter-spacing: 1.6px; text-transform: uppercase; margin: 24px 0 12px; }
@@ -487,7 +488,7 @@ with gr.Blocks(title="Personal Color Styling") as demo:
487
  [style_card_a, new_img_a, answer_a, outfit_cards_a],
488
  )
489
 
490
- # תיקון: הגדרת מערך ערכים מלא ומדויק לכל הפרמטרים של ה-Examples כדי למנוע את שגיאת ה-load_example
491
  gr.Examples(
492
  examples=[
493
  [SAMPLE_PHOTOS[0], "woman", "adult", "What style would suit me best?"],
@@ -497,7 +498,7 @@ with gr.Blocks(title="Personal Color Styling") as demo:
497
  inputs=[photo_in, gender_a, age_a, question_a],
498
  outputs=[style_card_a, new_img_a, answer_a, outfit_cards_a],
499
  fn=recommend_from_photo,
500
- cache_examples=True,
501
  label="Quick Starters",
502
  )
503
 
@@ -530,5 +531,4 @@ with gr.Blocks(title="Personal Color Styling") as demo:
530
  )
531
 
532
  if __name__ == "__main__":
533
- # העברת פרמטרי ה-CSS וה-Theme באופן בטוח לתוך פונקציית הריצה הסופית כנדרש בגרדיו 6
534
  demo.launch(css=CUSTOM_CSS, theme=gr.themes.Soft(primary_hue="amber"))
 
143
  return base64.b64encode(buf.getvalue()).decode("utf-8")
144
 
145
  # ---------------------------------------------------------------------------
146
+ # EMBEDDING + FAISS SEARCH (תיקון ה-TypeError וה-AttributeError לחילוץ וקטורים)
147
  # ---------------------------------------------------------------------------
148
  @torch.no_grad()
149
  def embed_query_image(pil_image):
150
  inputs = win_processor(images=pil_image, return_tensors="pt").to(DEVICE)
151
+ outputs = win_model(**inputs)
152
+
153
+ # שימוש ישיר ובטוח בחילוץ הוקטור ללא תלות בסוג העטיפה של BaseModelOutput
154
+ if hasattr(outputs, "image_embeds") and outputs.image_embeds is not None:
155
  feats = outputs.image_embeds
156
+ elif hasattr(outputs, "pooler_output") and outputs.pooler_output is not None:
157
+ feats = outputs.pooler_output
158
+ elif isinstance(outputs, tuple) or isinstance(outputs, list):
159
+ feats = outputs[0]
160
  else:
161
  feats = outputs
162
+
163
  if hasattr(feats, "detach"):
164
  feats = feats.detach()
165
  return feats.cpu().numpy().astype("float32")
 
167
  @torch.no_grad()
168
  def embed_query_text(sentence):
169
  inputs = win_processor(text=[sentence], return_tensors="pt", padding=True, truncation=True).to(DEVICE)
170
+ outputs = win_model(**inputs)
171
+
172
+ # שימוש ישיר ובטוח בחילוץ הוקטור ללא תלות בסוג העטיפה של BaseModelOutput
173
+ if hasattr(outputs, "text_embeds") and outputs.text_embeds is not None:
174
  feats = outputs.text_embeds
175
+ elif hasattr(outputs, "pooler_output") and outputs.pooler_output is not None:
176
+ feats = outputs.pooler_output
177
+ elif isinstance(outputs, tuple) or isinstance(outputs, list):
178
+ feats = outputs[0]
179
  else:
180
  feats = outputs
181
 
 
199
  if idx == -1 or (exclude_idx is not None and idx == exclude_idx):
200
  continue
201
  row = df.iloc[idx]
202
+ if require_gender && gender and str(row["gender"]).lower() != str(gender).lower():
203
  continue
204
  if require_age and age_group and str(row["age_group"]).lower() != str(age_group).lower():
205
  continue
 
262
  resized_protect_img = Image.fromarray(protect.astype(np.uint8) * 255).resize((head_w, head_h), resample=Image.NEAREST)
263
 
264
  canvas = Image.new("RGB", (canvas_w, canvas_h), color=(240, 238, 235))
 
265
  paste_x = (canvas_w - head_w) // 2
266
  paste_y = int(canvas_h * 0.03)
267
  canvas.paste(resized_face_crop, (paste_x, paste_y))
 
297
  html += f'</div>'
298
  return html
299
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  def build_outfit_component_cards_html(row):
301
  colors = [c.strip() for c in str(row["recommended_colors"]).split(",") if c.strip()] or ["neutral"]
302
  components = [
 
416
  .dark-panel { background: #FFFFFF !important; border-radius: 16px !important; padding: 24px !important; border: 1px solid #ECE4D6 !important; margin-bottom: 20px; }
417
  .dark-panel label, .dark-panel span { color: #2C2A29 !important; font-weight: 600; }
418
 
419
+ input, select, .secondary, .wrap, .slots, .single-select, .select-wrap {
420
+ color: #2C2A29 !important;
421
+ background-color: #FFFFFF !important;
422
+ border: 1px solid #E3DFDA !important;
423
+ border-radius: 4px !important;
424
+ }
425
+ div.form { background: transparent !important; border: none !important; box-shadow: none !important; }
426
+ fieldset { display: flex !important; justify-content: center !important; gap: 24px !important; border: none !important; background: transparent !important; }
427
+
428
  .palette-premium-banner { background: #FAF3ED; padding: 24px; border-radius: 12px; margin-bottom: 20px; border-left: 5px solid #C69E6E; }
429
  .section-split { display: grid !important; grid-template-columns: repeat(2, 1fr) !important; gap: 20px !important; margin-top: 20px !important; width: 100% !important; }
430
  @media (max-width: 768px) { .section-split { grid-template-columns: 1fr !important; } }
 
448
  .prod-title { font-size: 15px; font-weight: 700; color: #111111 !important; margin: 0 0 4px 0; line-height: 1.3; min-height: 40px; display: flex; align-items: center; }
449
  .prod-brand { font-size: 13px; color: #999999 !important; margin-bottom: 14px; display: block; }
450
 
 
451
  .shop-btn { display: block; width: 100%; background: #161617; color: #FFFFFF !important; text-align: center; padding: 11px 0; border-radius: 8px; font-size: 13px; font-weight: 700; text-decoration: none !important; letter-spacing: 0.5px; }
452
  .shop-btn:hover { background: #2D2D2F; color: #FFFFFF !important; }
453
  .more-matches-label { font-size: 11px; font-weight: 700; color: #9C8E82 !important; letter-spacing: 1.6px; text-transform: uppercase; margin: 24px 0 12px; }
 
488
  [style_card_a, new_img_a, answer_a, outfit_cards_a],
489
  )
490
 
491
+ # תיקון: הגדרת cache_examples=False כדי למנוע קריסות והדמיית קלט כפויה
492
  gr.Examples(
493
  examples=[
494
  [SAMPLE_PHOTOS[0], "woman", "adult", "What style would suit me best?"],
 
498
  inputs=[photo_in, gender_a, age_a, question_a],
499
  outputs=[style_card_a, new_img_a, answer_a, outfit_cards_a],
500
  fn=recommend_from_photo,
501
+ cache_examples=False,
502
  label="Quick Starters",
503
  )
504
 
 
531
  )
532
 
533
  if __name__ == "__main__":
 
534
  demo.launch(css=CUSTOM_CSS, theme=gr.themes.Soft(primary_hue="amber"))