Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- README.md +7 -8
- app.py +197 -0
- requirements.txt +5 -0
README.md
CHANGED
|
@@ -1,13 +1,12 @@
|
|
| 1 |
---
|
| 2 |
-
title: TrendSurfer
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 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: TrendSurfer AI - Fashion Recognition
|
| 3 |
+
emoji: 👔
|
| 4 |
+
colorFrom: purple
|
| 5 |
+
colorTo: pink
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 4.0.0
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: mit
|
| 11 |
+
short_description: AI destekli kıyafet analizi ve ürün linkleme.
|
| 12 |
+
---
|
|
|
app.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from transformers import BlipProcessor, BlipForConditionalGeneration
|
| 3 |
+
from PIL import Image
|
| 4 |
+
import torch
|
| 5 |
+
import re
|
| 6 |
+
from urllib.parse import quote
|
| 7 |
+
|
| 8 |
+
# Model yükleme (BLIP-2 detaylı görsel açıklama için)
|
| 9 |
+
processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-large")
|
| 10 |
+
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-large")
|
| 11 |
+
|
| 12 |
+
# Desteklenen markalar ve arama URL'leri
|
| 13 |
+
BRANDS = {
|
| 14 |
+
"Zara": "https://www.zara.com/tr/en/search?searchTerm=",
|
| 15 |
+
"Mango": "https://shop.mango.com/tr/kadin/arama?q=",
|
| 16 |
+
"H&M": "https://www2.hm.com/tr_tr/search-results.html?q=",
|
| 17 |
+
"Bershka": "https://www.bershka.com/tr/search?searchTerm=",
|
| 18 |
+
"Pull&Bear": "https://www.pullandbear.com/tr/search?searchTerm="
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
# Kıyafet kategorileri ve anahtar kelimeler
|
| 22 |
+
CLOTHING_KEYWORDS = {
|
| 23 |
+
'jacket': ['jacket', 'blazer', 'coat', 'cardigan', 'bomber'],
|
| 24 |
+
'top': ['shirt', 'blouse', 't-shirt', 'top', 'sweater', 'hoodie'],
|
| 25 |
+
'pants': ['pants', 'trousers', 'jeans', 'shorts'],
|
| 26 |
+
'skirt': ['skirt', 'mini skirt', 'maxi skirt'],
|
| 27 |
+
'dress': ['dress', 'gown'],
|
| 28 |
+
'shoes': ['shoes', 'boots', 'sneakers', 'heels', 'sandals'],
|
| 29 |
+
'accessories': ['bag', 'purse', 'hat', 'scarf', 'belt', 'sunglasses']
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
def analyze_fashion_image(image):
|
| 33 |
+
"""Görseli analiz edip detaylı kıyafet açıklaması çıkarır"""
|
| 34 |
+
if image is None:
|
| 35 |
+
return "❌ Lütfen bir görsel yükleyin", ""
|
| 36 |
+
|
| 37 |
+
# Görseli işle
|
| 38 |
+
inputs = processor(image, return_tensors="pt")
|
| 39 |
+
|
| 40 |
+
# Detaylı açıklama üret
|
| 41 |
+
with torch.no_grad():
|
| 42 |
+
out = model.generate(**inputs, max_length=100, num_beams=5)
|
| 43 |
+
|
| 44 |
+
description = processor.decode(out[0], skip_special_tokens=True)
|
| 45 |
+
|
| 46 |
+
# Kıyafet parçalarını tespit et
|
| 47 |
+
detected_items = extract_clothing_items(description)
|
| 48 |
+
|
| 49 |
+
if not detected_items:
|
| 50 |
+
detected_items = [description] # Eğer spesifik parça bulunamazsa genel açıklamayı kullan
|
| 51 |
+
|
| 52 |
+
# Sonuçları formatla
|
| 53 |
+
result_html = create_fashion_cards(detected_items)
|
| 54 |
+
|
| 55 |
+
return f"🔍 **Analiz Sonucu:** {description}", result_html
|
| 56 |
+
|
| 57 |
+
def extract_clothing_items(description):
|
| 58 |
+
"""Açıklamadan kıyafet parçalarını çıkarır"""
|
| 59 |
+
items = []
|
| 60 |
+
description_lower = description.lower()
|
| 61 |
+
|
| 62 |
+
# Her kategori için kontrol et
|
| 63 |
+
for category, keywords in CLOTHING_KEYWORDS.items():
|
| 64 |
+
for keyword in keywords:
|
| 65 |
+
if keyword in description_lower:
|
| 66 |
+
# Kelime çevresindeki bağlamı al
|
| 67 |
+
start_idx = max(0, description_lower.index(keyword) - 20)
|
| 68 |
+
end_idx = min(len(description), description_lower.index(keyword) + len(keyword) + 30)
|
| 69 |
+
context = description[start_idx:end_idx].strip()
|
| 70 |
+
|
| 71 |
+
# Renkler ve stili bul
|
| 72 |
+
colors = extract_colors(context)
|
| 73 |
+
|
| 74 |
+
item_desc = f"{colors} {keyword}".strip() if colors else keyword
|
| 75 |
+
if item_desc not in items:
|
| 76 |
+
items.append(item_desc)
|
| 77 |
+
break
|
| 78 |
+
|
| 79 |
+
return items if items else [description]
|
| 80 |
+
|
| 81 |
+
def extract_colors(text):
|
| 82 |
+
"""Metinden renk bilgilerini çıkarır"""
|
| 83 |
+
colors = ['black', 'white', 'blue', 'red', 'green', 'yellow', 'pink', 'purple',
|
| 84 |
+
'brown', 'gray', 'grey', 'beige', 'navy', 'cream', 'olive', 'burgundy',
|
| 85 |
+
'siyah', 'beyaz', 'mavi', 'kırmızı', 'yeşil', 'sarı', 'pembe', 'mor',
|
| 86 |
+
'kahverengi', 'gri', 'bej', 'lacivert', 'krem']
|
| 87 |
+
|
| 88 |
+
text_lower = text.lower()
|
| 89 |
+
found_colors = [color for color in colors if color in text_lower]
|
| 90 |
+
|
| 91 |
+
return ' '.join(found_colors) if found_colors else ''
|
| 92 |
+
|
| 93 |
+
def create_fashion_cards(items):
|
| 94 |
+
"""Instagram-style kıyafet kartları oluşturur"""
|
| 95 |
+
cards_html = '<div style="display: flex; flex-direction: column; gap: 20px; margin-top: 20px;">'
|
| 96 |
+
|
| 97 |
+
for idx, item in enumerate(items, 1):
|
| 98 |
+
search_query = quote(item)
|
| 99 |
+
|
| 100 |
+
# Her kıyafet parçası için kart
|
| 101 |
+
card_html = f'''
|
| 102 |
+
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 103 |
+
border-radius: 15px; padding: 20px; color: white;
|
| 104 |
+
box-shadow: 0 10px 30px rgba(0,0,0,0.3);">
|
| 105 |
+
<h3 style="margin: 0 0 15px 0; font-size: 18px; text-transform: uppercase;
|
| 106 |
+
letter-spacing: 1px;">
|
| 107 |
+
👔 {item}
|
| 108 |
+
</h3>
|
| 109 |
+
<div style="display: flex; flex-wrap: wrap; gap: 10px;">
|
| 110 |
+
'''
|
| 111 |
+
|
| 112 |
+
# Her marka için buton
|
| 113 |
+
for brand, base_url in BRANDS.items():
|
| 114 |
+
brand_url = f"{base_url}{search_query}"
|
| 115 |
+
card_html += f'''
|
| 116 |
+
<a href="{brand_url}" target="_blank"
|
| 117 |
+
style="background: rgba(255,255,255,0.2); border: 2px solid white;
|
| 118 |
+
color: white; padding: 10px 20px; border-radius: 25px;
|
| 119 |
+
text-decoration: none; font-weight: bold;
|
| 120 |
+
transition: all 0.3s; display: inline-block;
|
| 121 |
+
backdrop-filter: blur(10px);">
|
| 122 |
+
{brand} 🔗
|
| 123 |
+
</a>
|
| 124 |
+
'''
|
| 125 |
+
|
| 126 |
+
card_html += '''
|
| 127 |
+
</div>
|
| 128 |
+
</div>
|
| 129 |
+
'''
|
| 130 |
+
|
| 131 |
+
cards_html += card_html
|
| 132 |
+
|
| 133 |
+
cards_html += '</div>'
|
| 134 |
+
|
| 135 |
+
return cards_html
|
| 136 |
+
|
| 137 |
+
# Gradio Arayüzü
|
| 138 |
+
with gr.Blocks(css="""
|
| 139 |
+
.gradio-container {
|
| 140 |
+
font-family: 'Arial', sans-serif;
|
| 141 |
+
max-width: 1200px;
|
| 142 |
+
margin: auto;
|
| 143 |
+
}
|
| 144 |
+
.title {
|
| 145 |
+
text-align: center;
|
| 146 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 147 |
+
-webkit-background-clip: text;
|
| 148 |
+
-webkit-text-fill-color: transparent;
|
| 149 |
+
font-size: 48px;
|
| 150 |
+
font-weight: bold;
|
| 151 |
+
margin-bottom: 10px;
|
| 152 |
+
}
|
| 153 |
+
.subtitle {
|
| 154 |
+
text-align: center;
|
| 155 |
+
color: #666;
|
| 156 |
+
font-size: 18px;
|
| 157 |
+
margin-bottom: 30px;
|
| 158 |
+
}
|
| 159 |
+
""") as demo:
|
| 160 |
+
|
| 161 |
+
gr.HTML("""
|
| 162 |
+
<div class="title">✨ TrendSurfer AI</div>
|
| 163 |
+
<div class="subtitle">
|
| 164 |
+
Zaratrendsetter tarzında kıyafet analizi 🎯<br>
|
| 165 |
+
Fotoğraf yükleyin, trendleri keşfedin!
|
| 166 |
+
</div>
|
| 167 |
+
""")
|
| 168 |
+
|
| 169 |
+
with gr.Row():
|
| 170 |
+
with gr.Column(scale=1):
|
| 171 |
+
image_input = gr.Image(type="pil", label="📸 Kombin Fotoğrafı Yükleyin")
|
| 172 |
+
analyze_btn = gr.Button("🔍 Analiz Et", variant="primary", size="lg")
|
| 173 |
+
|
| 174 |
+
with gr.Column(scale=1):
|
| 175 |
+
result_text = gr.Markdown(label="Analiz Sonucu")
|
| 176 |
+
result_html = gr.HTML(label="Ürün Linkleri")
|
| 177 |
+
|
| 178 |
+
analyze_btn.click(
|
| 179 |
+
fn=analyze_fashion_image,
|
| 180 |
+
inputs=image_input,
|
| 181 |
+
outputs=[result_text, result_html]
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
# Örnek görseller
|
| 185 |
+
gr.Examples(
|
| 186 |
+
examples=[
|
| 187 |
+
["https://images.unsplash.com/photo-1490481651871-ab68de25d43d?w=400"],
|
| 188 |
+
["https://images.unsplash.com/photo-1487222477894-8943e31ef7b2?w=400"],
|
| 189 |
+
],
|
| 190 |
+
inputs=image_input,
|
| 191 |
+
label="Örnek Görseller"
|
| 192 |
+
)
|
| 193 |
+
|
| 194 |
+
# Uygulamayı başlat
|
| 195 |
+
if __name__ == "__main__":
|
| 196 |
+
demo.launch()
|
| 197 |
+
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=4.0.0
|
| 2 |
+
transformers>=4.30.0
|
| 3 |
+
torch>=2.0.0
|
| 4 |
+
pillow>=9.0.0
|
| 5 |
+
accelerate>=0.20.0
|