aryanprooo commited on
Commit
cb98570
Β·
verified Β·
1 Parent(s): 6425179

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -91
app.py CHANGED
@@ -95,15 +95,11 @@ def remove_background(image):
95
  # ======================
96
  # Dominant Color Detection using K-Means
97
  # ======================
98
- def get_dominant_color(image, n_colors=1):
99
  """
100
- Get THE most dominant color from clothing using K-means clustering
101
 
102
- Steps:
103
- 1. Remove background
104
- 2. Extract only clothing pixels
105
- 3. Use K-means to find dominant color cluster
106
- 4. Convert to color name
107
  """
108
  try:
109
  # Step 1: Remove background
@@ -115,23 +111,14 @@ def get_dominant_color(image, n_colors=1):
115
 
116
  # Step 3: Extract only non-transparent pixels (clothing only)
117
  if img_array.shape[-1] == 4: # RGBA
118
- # Get alpha channel
119
  alpha = img_array[:, :, 3]
120
-
121
- # Only pixels that are NOT transparent (alpha > 100)
122
  mask = alpha > 100
123
-
124
- # Get RGB pixels of clothing only
125
  pixels = img_array[:, :, :3][mask]
126
  else: # RGB
127
- # Reshape all pixels
128
  pixels = img_array.reshape(-1, 3)
129
 
130
- # Step 4: Filter out pure white and pure black (background remnants)
131
- # Remove whites (background)
132
  pixels = pixels[~((pixels[:, 0] > 240) & (pixels[:, 1] > 240) & (pixels[:, 2] > 240))]
133
-
134
- # Remove blacks (shadows)
135
  pixels = pixels[~((pixels[:, 0] < 15) & (pixels[:, 1] < 15) & (pixels[:, 2] < 15))]
136
 
137
  if len(pixels) < 10:
@@ -139,26 +126,24 @@ def get_dominant_color(image, n_colors=1):
139
 
140
  print(f"[INFO] πŸ“Š Analyzing {len(pixels)} clothing pixels...")
141
 
142
- # Step 5: Sample pixels if too many (for speed)
143
  if len(pixels) > 5000:
144
  indices = np.random.choice(len(pixels), 5000, replace=False)
145
  pixels = pixels[indices]
146
 
147
- # Step 6: Use K-Means clustering to find dominant colors
148
  kmeans = KMeans(n_clusters=min(n_colors, len(pixels)), random_state=42, n_init=10)
149
  kmeans.fit(pixels)
150
 
151
- # Step 7: Get the cluster centers (dominant colors in RGB)
152
  dominant_colors_rgb = kmeans.cluster_centers_
153
 
154
- # Step 8: Count pixels in each cluster to find THE most dominant
155
  labels = kmeans.labels_
156
  label_counts = np.bincount(labels)
157
-
158
- # Sort by frequency
159
  sorted_indices = np.argsort(label_counts)[::-1]
160
 
161
- # Step 9: Convert dominant colors to color names
162
  color_names = []
163
  color_rgb_values = []
164
 
@@ -166,12 +151,11 @@ def get_dominant_color(image, n_colors=1):
166
  rgb = dominant_colors_rgb[idx].astype(int)
167
  color_name = rgb_to_color_name(tuple(rgb))
168
 
169
- # Avoid duplicates
170
  if color_name not in color_names:
171
  color_names.append(color_name)
172
  color_rgb_values.append(rgb)
173
 
174
- print(f"[INFO] 🎨 Dominant color detected: {color_names[0]}")
175
 
176
  return color_names, color_rgb_values
177
 
@@ -185,14 +169,9 @@ def get_dominant_color(image, n_colors=1):
185
  def rgb_to_color_name(rgb):
186
  """
187
  Convert RGB to human-readable color name
188
- Enhanced with more color ranges
189
  """
190
  r, g, b = rgb
191
 
192
- # Calculate color properties
193
- max_val = max(r, g, b)
194
- min_val = min(r, g, b)
195
-
196
  # White
197
  if r > 220 and g > 220 and b > 220:
198
  return "White"
@@ -297,7 +276,7 @@ def rgb_to_color_name(rgb):
297
  if r > 180 and g > 160 and b > 200:
298
  return "Lavender"
299
 
300
- # Default - multicolor
301
  return "Multicolor"
302
 
303
 
@@ -319,15 +298,55 @@ def detect_clothing_type(category):
319
  return "🌍 Western Wear"
320
 
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  # ======================
323
  # Prediction Function
324
  # ======================
325
  def predict_fashion(image, custom_categories=None):
326
  """
327
- Classify fashion item + detect dominant color
328
  """
329
  if image is None:
330
- return "⚠️ Please upload an image first!", {}, None
331
 
332
  try:
333
  # Step 1: Categories
@@ -356,18 +375,13 @@ def predict_fashion(image, custom_categories=None):
356
  top_confidence = probs[top_prob_idx].item()
357
 
358
  # Step 3: Dominant Color Detection
359
- print("[INFO] 🎨 Detecting dominant color...")
360
  dominant_colors, rgb_values = get_dominant_color(image, n_colors=3)
361
 
362
  # Step 4: Type Detection
363
  clothing_type = detect_clothing_type(top_category)
364
 
365
- # Step 5: Create color preview image
366
- color_preview = None
367
- if rgb_values is not None and len(rgb_values) > 0:
368
- color_preview = create_color_preview(rgb_values, dominant_colors)
369
-
370
- # Step 6: Format result
371
  result = f"""
372
  ### 🎯 Fashion Item Detected
373
 
@@ -377,13 +391,32 @@ def predict_fashion(image, custom_categories=None):
377
 
378
  ---
379
 
380
- ### 🎨 Dominant Color Analysis
381
 
382
- **Primary Color:** {dominant_colors[0] if dominant_colors else 'Unknown'} ✨
383
  """
384
 
385
- if len(dominant_colors) > 1:
386
- result += f"**Secondary Colors:** {', '.join(dominant_colors[1:])} 🌈\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
  result += f"""
389
  ---
@@ -413,6 +446,33 @@ def predict_fashion(image, custom_categories=None):
413
  - Suitable for casual/formal settings
414
  """
415
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  # Top predictions
417
  top_probs, top_indices = torch.topk(probs, k=min(5, len(categories)))
418
  top_predictions = {}
@@ -420,50 +480,12 @@ def predict_fashion(image, custom_categories=None):
420
  category = categories[idx.item()]
421
  top_predictions[category] = float(prob.item())
422
 
423
- return result, top_predictions, color_preview
424
 
425
  except Exception as e:
426
  import traceback
427
  error_msg = f"❌ Error: {str(e)}\n\n{traceback.format_exc()}"
428
- return error_msg, {}, None
429
-
430
-
431
- def create_color_preview(rgb_values, color_names):
432
- """
433
- Create a visual preview of detected colors
434
- """
435
- try:
436
- # Create image with color swatches
437
- num_colors = len(rgb_values)
438
- swatch_height = 100
439
- swatch_width = 200
440
-
441
- img = Image.new('RGB', (swatch_width, swatch_height * num_colors), 'white')
442
-
443
- import PIL.ImageDraw as ImageDraw
444
- import PIL.ImageFont as ImageFont
445
-
446
- draw = ImageDraw.Draw(img)
447
-
448
- for i, (rgb, name) in enumerate(zip(rgb_values, color_names)):
449
- y_start = i * swatch_height
450
- y_end = (i + 1) * swatch_height
451
-
452
- # Draw color swatch
453
- draw.rectangle([0, y_start, swatch_width, y_end], fill=tuple(rgb))
454
-
455
- # Add text (color name)
456
- text = f"{name}\nRGB: {rgb[0]}, {rgb[1]}, {rgb[2]}"
457
-
458
- # Use white or black text depending on background
459
- text_color = 'white' if sum(rgb) < 384 else 'black'
460
- draw.text((10, y_start + 30), text, fill=text_color)
461
-
462
- return img
463
-
464
- except Exception as e:
465
- print(f"[ERROR] Color preview failed: {e}")
466
- return None
467
 
468
 
469
  # ======================
@@ -473,7 +495,7 @@ with gr.Blocks(title="Fashion-CLIP + Color Detection", theme=gr.themes.Soft()) a
473
 
474
  gr.Markdown("""
475
  # πŸ‘— AI Fashion Classifier with Smart Color Detection
476
- ### Background Removal + K-Means Clustering for Accurate Colors
477
  """)
478
 
479
  status = "🟒 High Quality (rembg)" if REMBG_AVAILABLE else "🟑 Standard (GrabCut)"
@@ -481,13 +503,15 @@ with gr.Blocks(title="Fashion-CLIP + Color Detection", theme=gr.themes.Soft()) a
481
  gr.Markdown(f"""
482
  **Model:** Fashion-CLIP
483
  **Color Detection:** K-Means Clustering
484
- **Background Removal:** {status}
 
485
 
486
  ### ✨ How it works:
487
  1. πŸ–ΌοΈ **Upload** your fashion item image
488
  2. πŸ”„ **Background** is automatically removed
489
- 3. 🎨 **K-means** finds the dominant color from clothing only
490
  4. πŸ‘— **Fashion-CLIP** classifies the item type
 
491
  """)
492
 
493
  with gr.Row():
@@ -507,6 +531,7 @@ with gr.Blocks(title="Fashion-CLIP + Color Detection", theme=gr.themes.Soft()) a
507
  - Clear, well-lit photos work best
508
  - Single clothing item preferred
509
  - Background will be auto-removed
 
510
 
511
  **πŸ“¦ For Best Results:**
512
  ```bash
@@ -517,13 +542,12 @@ with gr.Blocks(title="Fashion-CLIP + Color Detection", theme=gr.themes.Soft()) a
517
  with gr.Column():
518
  output_text = gr.Markdown(label="πŸ“‹ Results")
519
  output_label = gr.Label(label="πŸ“Š Top 5 Predictions", num_top_classes=5)
520
- color_preview = gr.Image(label="🎨 Detected Colors", type="pil")
521
 
522
  # Event
523
  predict_btn.click(
524
  fn=predict_fashion,
525
  inputs=[input_image, custom_categories],
526
- outputs=[output_text, output_label, color_preview]
527
  )
528
 
529
  gr.Markdown("""
@@ -539,10 +563,24 @@ with gr.Blocks(title="Fashion-CLIP + Color Detection", theme=gr.themes.Soft()) a
539
 
540
  ---
541
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  **πŸš€ Powered by:**
543
  - Fashion-CLIP (patrickjohncyh/fashion-clip)
544
  - K-Means Clustering for dominant colors
545
  - rembg/GrabCut for background removal
 
546
  """)
547
 
548
  # ======================
@@ -550,12 +588,13 @@ with gr.Blocks(title="Fashion-CLIP + Color Detection", theme=gr.themes.Soft()) a
550
  # ======================
551
  if __name__ == "__main__":
552
  print("\n" + "="*60)
553
- print("πŸš€ FASHION CLASSIFIER WITH SMART COLOR DETECTION")
554
  print("="*60)
555
  print(f"βœ… Fashion-CLIP Model: Loaded")
556
  print(f"βœ… Categories: {len(FASHION_CATEGORIES)}")
557
  print(f"βœ… Background Removal: {'rembg (High Quality)' if REMBG_AVAILABLE else 'GrabCut (Standard)'}")
558
  print(f"βœ… Color Detection: K-Means Clustering")
 
559
  print("="*60 + "\n")
560
 
561
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
95
  # ======================
96
  # Dominant Color Detection using K-Means
97
  # ======================
98
+ def get_dominant_color(image, n_colors=3):
99
  """
100
+ Get THE most dominant colors from clothing using K-means clustering
101
 
102
+ Returns: List of color names and their RGB values
 
 
 
 
103
  """
104
  try:
105
  # Step 1: Remove background
 
111
 
112
  # Step 3: Extract only non-transparent pixels (clothing only)
113
  if img_array.shape[-1] == 4: # RGBA
 
114
  alpha = img_array[:, :, 3]
 
 
115
  mask = alpha > 100
 
 
116
  pixels = img_array[:, :, :3][mask]
117
  else: # RGB
 
118
  pixels = img_array.reshape(-1, 3)
119
 
120
+ # Step 4: Filter out pure white and pure black
 
121
  pixels = pixels[~((pixels[:, 0] > 240) & (pixels[:, 1] > 240) & (pixels[:, 2] > 240))]
 
 
122
  pixels = pixels[~((pixels[:, 0] < 15) & (pixels[:, 1] < 15) & (pixels[:, 2] < 15))]
123
 
124
  if len(pixels) < 10:
 
126
 
127
  print(f"[INFO] πŸ“Š Analyzing {len(pixels)} clothing pixels...")
128
 
129
+ # Step 5: Sample pixels if too many
130
  if len(pixels) > 5000:
131
  indices = np.random.choice(len(pixels), 5000, replace=False)
132
  pixels = pixels[indices]
133
 
134
+ # Step 6: K-Means clustering
135
  kmeans = KMeans(n_clusters=min(n_colors, len(pixels)), random_state=42, n_init=10)
136
  kmeans.fit(pixels)
137
 
138
+ # Step 7: Get cluster centers
139
  dominant_colors_rgb = kmeans.cluster_centers_
140
 
141
+ # Step 8: Sort by frequency
142
  labels = kmeans.labels_
143
  label_counts = np.bincount(labels)
 
 
144
  sorted_indices = np.argsort(label_counts)[::-1]
145
 
146
+ # Step 9: Convert to color names
147
  color_names = []
148
  color_rgb_values = []
149
 
 
151
  rgb = dominant_colors_rgb[idx].astype(int)
152
  color_name = rgb_to_color_name(tuple(rgb))
153
 
 
154
  if color_name not in color_names:
155
  color_names.append(color_name)
156
  color_rgb_values.append(rgb)
157
 
158
+ print(f"[INFO] 🎨 Dominant colors detected: {', '.join(color_names)}")
159
 
160
  return color_names, color_rgb_values
161
 
 
169
  def rgb_to_color_name(rgb):
170
  """
171
  Convert RGB to human-readable color name
 
172
  """
173
  r, g, b = rgb
174
 
 
 
 
 
175
  # White
176
  if r > 220 and g > 220 and b > 220:
177
  return "White"
 
276
  if r > 180 and g > 160 and b > 200:
277
  return "Lavender"
278
 
279
+ # Default
280
  return "Multicolor"
281
 
282
 
 
298
  return "🌍 Western Wear"
299
 
300
 
301
+ def get_color_emoji(color_name):
302
+ """
303
+ Get emoji for color (visual representation)
304
+ """
305
+ color_emojis = {
306
+ "Red": "πŸ”΄",
307
+ "Blue": "πŸ”΅",
308
+ "Green": "🟒",
309
+ "Yellow": "🟑",
310
+ "Orange": "🟠",
311
+ "Purple": "🟣",
312
+ "Pink": "🩷",
313
+ "Brown": "🟀",
314
+ "Black": "⚫",
315
+ "White": "βšͺ",
316
+ "Gray": "⚫",
317
+ "Light Gray": "βšͺ",
318
+ "Dark Gray": "⚫",
319
+ "Navy": "πŸ”΅",
320
+ "Sky Blue": "πŸ”΅",
321
+ "Light Green": "🟒",
322
+ "Dark Green": "🟒",
323
+ "Maroon": "πŸ”΄",
324
+ "Coral": "🩷",
325
+ "Gold": "🟑",
326
+ "Beige": "🟀",
327
+ "Cream": "βšͺ",
328
+ "Olive": "🟒",
329
+ "Cyan": "πŸ”΅",
330
+ "Magenta": "🟣",
331
+ "Violet": "🟣",
332
+ "Lavender": "🟣",
333
+ "Light Yellow": "🟑",
334
+ "Dark Brown": "🟀",
335
+ "Multicolor": "🌈"
336
+ }
337
+
338
+ return color_emojis.get(color_name, "🎨")
339
+
340
+
341
  # ======================
342
  # Prediction Function
343
  # ======================
344
  def predict_fashion(image, custom_categories=None):
345
  """
346
+ Classify fashion item + detect dominant color (TEXT OUTPUT)
347
  """
348
  if image is None:
349
+ return "⚠️ Please upload an image first!", {}
350
 
351
  try:
352
  # Step 1: Categories
 
375
  top_confidence = probs[top_prob_idx].item()
376
 
377
  # Step 3: Dominant Color Detection
378
+ print("[INFO] 🎨 Detecting dominant colors...")
379
  dominant_colors, rgb_values = get_dominant_color(image, n_colors=3)
380
 
381
  # Step 4: Type Detection
382
  clothing_type = detect_clothing_type(top_category)
383
 
384
+ # Step 5: Format result with TEXT COLORS
 
 
 
 
 
385
  result = f"""
386
  ### 🎯 Fashion Item Detected
387
 
 
391
 
392
  ---
393
 
394
+ ### 🎨 Detected Colors (Text Format)
395
 
 
396
  """
397
 
398
+ # βœ… DISPLAY COLORS AS TEXT
399
+ if dominant_colors and dominant_colors[0] != "Unable to detect":
400
+ # Primary Color
401
+ primary_color = dominant_colors[0]
402
+ primary_emoji = get_color_emoji(primary_color)
403
+ primary_rgb = rgb_values[0] if rgb_values else [0, 0, 0]
404
+
405
+ result += f"**Primary Color:** {primary_emoji} **{primary_color}** ✨\n"
406
+ result += f"*RGB Values: ({primary_rgb[0]}, {primary_rgb[1]}, {primary_rgb[2]})*\n\n"
407
+
408
+ # Secondary Colors
409
+ if len(dominant_colors) > 1:
410
+ result += "**Secondary Colors:**\n"
411
+ for i, (color, rgb) in enumerate(zip(dominant_colors[1:], rgb_values[1:]), 1):
412
+ emoji = get_color_emoji(color)
413
+ result += f" {i}. {emoji} **{color}** - RGB({rgb[0]}, {rgb[1]}, {rgb[2]})\n"
414
+ result += "\n"
415
+
416
+ # Color Summary
417
+ result += f"**Color Summary:** {', '.join(dominant_colors)} 🌈\n"
418
+ else:
419
+ result += "⚠️ Unable to detect colors from image\n"
420
 
421
  result += f"""
422
  ---
 
446
  - Suitable for casual/formal settings
447
  """
448
 
449
+ # Color-based suggestions
450
+ if dominant_colors[0] != "Unable to detect":
451
+ primary = dominant_colors[0].lower()
452
+
453
+ result += f"\n**Color Styling Tips for {dominant_colors[0]}:**\n"
454
+
455
+ if "black" in primary:
456
+ result += "- Classic and versatile ⚫\n- Pairs well with any color\n- Perfect for formal events\n"
457
+ elif "white" in primary:
458
+ result += "- Clean and fresh look βšͺ\n- Great for summer\n- Easy to accessorize\n"
459
+ elif "red" in primary:
460
+ result += "- Bold and confident πŸ”΄\n- Statement piece\n- Pair with neutral colors\n"
461
+ elif "blue" in primary:
462
+ result += "- Cool and calming πŸ”΅\n- Professional look\n- Versatile for day/night\n"
463
+ elif "green" in primary:
464
+ result += "- Natural and refreshing 🟒\n- Great for outdoor events\n- Pairs with earth tones\n"
465
+ elif "yellow" in primary or "gold" in primary:
466
+ result += "- Bright and cheerful 🟑\n- Perfect for festivities\n- Eye-catching choice\n"
467
+ elif "pink" in primary:
468
+ result += "- Soft and feminine 🩷\n- Romantic vibe\n- Great for parties\n"
469
+ elif "purple" in primary or "violet" in primary:
470
+ result += "- Royal and elegant 🟣\n- Sophisticated choice\n- Unique statement\n"
471
+ elif "brown" in primary or "beige" in primary:
472
+ result += "- Earthy and warm 🟀\n- Natural aesthetic\n- Timeless appeal\n"
473
+ elif "gray" in primary:
474
+ result += "- Neutral and modern ⚫\n- Professional look\n- Easy to style\n"
475
+
476
  # Top predictions
477
  top_probs, top_indices = torch.topk(probs, k=min(5, len(categories)))
478
  top_predictions = {}
 
480
  category = categories[idx.item()]
481
  top_predictions[category] = float(prob.item())
482
 
483
+ return result, top_predictions
484
 
485
  except Exception as e:
486
  import traceback
487
  error_msg = f"❌ Error: {str(e)}\n\n{traceback.format_exc()}"
488
+ return error_msg, {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
 
490
 
491
  # ======================
 
495
 
496
  gr.Markdown("""
497
  # πŸ‘— AI Fashion Classifier with Smart Color Detection
498
+ ### Background Removal + K-Means Clustering for Accurate Colors (Text Output)
499
  """)
500
 
501
  status = "🟒 High Quality (rembg)" if REMBG_AVAILABLE else "🟑 Standard (GrabCut)"
 
503
  gr.Markdown(f"""
504
  **Model:** Fashion-CLIP
505
  **Color Detection:** K-Means Clustering
506
+ **Background Removal:** {status}
507
+ **Output Format:** Text-based color names with RGB values
508
 
509
  ### ✨ How it works:
510
  1. πŸ–ΌοΈ **Upload** your fashion item image
511
  2. πŸ”„ **Background** is automatically removed
512
+ 3. 🎨 **K-means** finds the dominant colors from clothing only
513
  4. πŸ‘— **Fashion-CLIP** classifies the item type
514
+ 5. πŸ“ **Colors displayed as text** with emojis and RGB values
515
  """)
516
 
517
  with gr.Row():
 
531
  - Clear, well-lit photos work best
532
  - Single clothing item preferred
533
  - Background will be auto-removed
534
+ - Colors shown as text with RGB values
535
 
536
  **πŸ“¦ For Best Results:**
537
  ```bash
 
542
  with gr.Column():
543
  output_text = gr.Markdown(label="πŸ“‹ Results")
544
  output_label = gr.Label(label="πŸ“Š Top 5 Predictions", num_top_classes=5)
 
545
 
546
  # Event
547
  predict_btn.click(
548
  fn=predict_fashion,
549
  inputs=[input_image, custom_categories],
550
+ outputs=[output_text, output_label]
551
  )
552
 
553
  gr.Markdown("""
 
563
 
564
  ---
565
 
566
+ ### 🎨 Color Output Format:
567
+
568
+ **Primary Color:** πŸ”΄ **Red** ✨
569
+ *RGB Values: (255, 0, 0)*
570
+
571
+ **Secondary Colors:**
572
+ 1. βšͺ **White** - RGB(255, 255, 255)
573
+ 2. ⚫ **Black** - RGB(0, 0, 0)
574
+
575
+ **Color Summary:** Red, White, Black 🌈
576
+
577
+ ---
578
+
579
  **πŸš€ Powered by:**
580
  - Fashion-CLIP (patrickjohncyh/fashion-clip)
581
  - K-Means Clustering for dominant colors
582
  - rembg/GrabCut for background removal
583
+ - Text-based color output with emojis
584
  """)
585
 
586
  # ======================
 
588
  # ======================
589
  if __name__ == "__main__":
590
  print("\n" + "="*60)
591
+ print("πŸš€ FASHION CLASSIFIER WITH SMART COLOR DETECTION (TEXT)")
592
  print("="*60)
593
  print(f"βœ… Fashion-CLIP Model: Loaded")
594
  print(f"βœ… Categories: {len(FASHION_CATEGORIES)}")
595
  print(f"βœ… Background Removal: {'rembg (High Quality)' if REMBG_AVAILABLE else 'GrabCut (Standard)'}")
596
  print(f"βœ… Color Detection: K-Means Clustering")
597
+ print(f"βœ… Output Format: Text with RGB values")
598
  print("="*60 + "\n")
599
 
600
  demo.launch(server_name="0.0.0.0", server_port=7860)