Humphreykowl commited on
Commit
acec099
·
verified ·
1 Parent(s): 22f3343
Files changed (1) hide show
  1. app.py +1046 -0
app.py ADDED
@@ -0,0 +1,1046 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py (Fixed AI Fashion Designer for Hugging Face Spaces)
2
+ import gradio as gr
3
+ import requests
4
+ from PIL import Image, ImageDraw, ImageFont
5
+ import numpy as np
6
+ from sklearn.cluster import KMeans
7
+ import time
8
+ import random
9
+ import os
10
+ import torch
11
+ import logging
12
+ from typing import Dict, List, Tuple, Optional
13
+ import json
14
+ from datetime import datetime
15
+
16
+ # Hugging Face specific imports
17
+ from transformers import pipeline, BlipProcessor, BlipForConditionalGeneration
18
+ from diffusers import StableDiffusionPipeline, ControlNetModel, StableDiffusionControlNetPipeline
19
+ import cv2
20
+
21
+ # Setup logging
22
+ logging.basicConfig(level=logging.INFO)
23
+ logger = logging.getLogger(__name__)
24
+
25
+ class FashionAnalyzer:
26
+ """Enhanced fashion analysis engine with proper image understanding"""
27
+
28
+ def __init__(self):
29
+ self.style_keywords = {
30
+ "商务正装": ["suit", "formal", "business", "office", "professional", "tie", "blazer", "西装", "正装", "商务", "dress shirt", "formal wear"],
31
+ "休闲风": ["casual", "relaxed", "comfortable", "everyday", "jeans", "t-shirt", "休闲", "日常", "weekend", "laid-back"],
32
+ "运动风": ["sport", "athletic", "gym", "fitness", "running", "training", "运动", "健身", "activewear", "yoga"],
33
+ "时尚潮流": ["fashion", "trendy", "stylish", "modern", "chic", "designer", "时尚", "潮流", "avant-garde", "runway"],
34
+ "复古风": ["vintage", "retro", "classic", "traditional", "old-fashioned", "复古", "经典", "throwback", "nostalgic"],
35
+ "街头风": ["street", "urban", "hip-hop", "cool", "edgy", "街头", "嘻哈", "streetwear", "grunge"],
36
+ "优雅风": ["elegant", "sophisticated", "graceful", "refined", "classy", "优雅", "高贵", "glamorous", "luxurious"],
37
+ "波西米亚风": ["bohemian", "boho", "free-spirited", "artistic", "flowing", "ethnic", "波西米亚", "民族风"],
38
+ "极简风": ["minimalist", "clean", "simple", "basic", "understated", "极简", "简约", "nordic"]
39
+ }
40
+
41
+ self.color_palette = {
42
+ "春季色彩": ["粉色", "嫩绿", "天蓝", "柠檬黄", "薰衣草紫"],
43
+ "夏季色彩": ["白色", "海军蓝", "珊瑚色", "薄荷绿", "阳光橙"],
44
+ "秋季色彩": ["棕色", "橙色", "深红", "金黄", "橄榄绿"],
45
+ "冬季色彩": ["黑色", "深灰", "酒红", "深蓝", "银色"]
46
+ }
47
+
48
+ def extract_advanced_colors(self, image: Image.Image, n_colors: int = 5) -> List[Dict]:
49
+ """Extract dominant colors with more detailed analysis"""
50
+ try:
51
+ # Resize for processing efficiency
52
+ image_resized = image.resize((150, 150))
53
+ img_array = np.array(image_resized)
54
+ pixels = img_array.reshape(-1, 3)
55
+
56
+ # Remove near-black and near-white pixels for better color analysis
57
+ mask = np.all(pixels > 30, axis=1) & np.all(pixels < 225, axis=1)
58
+ filtered_pixels = pixels[mask]
59
+
60
+ if len(filtered_pixels) < 50: # Fallback if too few pixels
61
+ filtered_pixels = pixels
62
+
63
+ # K-means clustering
64
+ n_colors = min(n_colors, len(filtered_pixels))
65
+ kmeans = KMeans(n_clusters=n_colors, random_state=42, n_init=10)
66
+ kmeans.fit(filtered_pixels)
67
+
68
+ colors_info = []
69
+ for i, color in enumerate(kmeans.cluster_centers_):
70
+ color_rgb = color.astype(int)
71
+ color_name = self.rgb_to_advanced_color_name(color_rgb)
72
+ color_hex = '#{:02x}{:02x}{:02x}'.format(*color_rgb)
73
+
74
+ # Calculate color properties
75
+ brightness = np.mean(color_rgb)
76
+ saturation = (np.max(color_rgb) - np.min(color_rgb)) / 255.0
77
+
78
+ colors_info.append({
79
+ "name": color_name,
80
+ "rgb": color_rgb.tolist(),
81
+ "hex": color_hex,
82
+ "brightness": round(brightness, 2),
83
+ "saturation": round(saturation, 2),
84
+ "season_match": self.get_season_match(color_name)
85
+ })
86
+
87
+ return colors_info
88
+ except Exception as e:
89
+ logger.error(f"Color extraction failed: {e}")
90
+ return [{"name": "未知颜色", "rgb": [128, 128, 128], "hex": "#808080", "brightness": 0.5, "saturation": 0}]
91
+
92
+ def rgb_to_advanced_color_name(self, rgb: np.ndarray) -> str:
93
+ """Enhanced RGB to color name mapping"""
94
+ r, g, b = rgb
95
+
96
+ # Advanced color detection
97
+ if r > 200 and g > 200 and b > 200:
98
+ return "象牙白" if min(r, g, b) > 240 else "米白色"
99
+ elif r < 50 and g < 50 and b < 50:
100
+ return "墨黑" if max(r, g, b) < 30 else "炭灰"
101
+ elif r > max(g, b) + 30:
102
+ if r > 180:
103
+ return "鲜红" if g < 100 and b < 100 else "珊瑚红"
104
+ elif r > 120:
105
+ return "深红" if g < 80 and b < 80 else "玫瑰红"
106
+ else:
107
+ return "暗红"
108
+ elif g > max(r, b) + 30:
109
+ if g > 180:
110
+ return "翠绿" if r < 100 and b < 100 else "苹果绿"
111
+ elif g > 120:
112
+ return "森林绿" if r < 80 and b < 80 else "橄榄绿"
113
+ else:
114
+ return "深绿"
115
+ elif b > max(r, g) + 30:
116
+ if b > 180:
117
+ return "天蓝" if r < 100 and g < 150 else "钴蓝"
118
+ elif b > 120:
119
+ return "海军蓝" if r < 80 and g < 80 else "宝蓝"
120
+ else:
121
+ return "深蓝"
122
+ elif r > 150 and g > 150 and b < 100:
123
+ return "柠檬黄" if r > 200 and g > 200 else "金黄"
124
+ elif r > 120 and g < 100 and b > 120:
125
+ return "紫罗兰" if r > 150 and b > 150 else "深紫"
126
+ elif g > 120 and b > 120 and r < 100:
127
+ return "青绿" if g > 150 and b > 150 else "青色"
128
+ elif abs(r - g) < 30 and abs(g - b) < 30:
129
+ if r > 150:
130
+ return "浅灰"
131
+ elif r > 100:
132
+ return "中灰"
133
+ else:
134
+ return "深灰"
135
+ else:
136
+ return "混合色"
137
+
138
+ def get_season_match(self, color_name: str) -> str:
139
+ """Determine which season a color best matches"""
140
+ for season, colors in self.color_palette.items():
141
+ if any(season_color in color_name for season_color in colors):
142
+ return season
143
+ return "四季通用"
144
+
145
+ def analyze_style_confidence_from_image(self, image: Image.Image, caption: str) -> Dict[str, float]:
146
+ """Analyze style confidence using both image features and caption"""
147
+ caption_lower = caption.lower()
148
+ style_scores = {}
149
+
150
+ # 1. Caption-based analysis (existing logic)
151
+ for style, keywords in self.style_keywords.items():
152
+ score = sum(1 for keyword in keywords if keyword in caption_lower)
153
+ confidence = min(score / len(keywords) * 100, 100)
154
+ if confidence > 0:
155
+ style_scores[style] = confidence
156
+
157
+ # 2. Image-based analysis using color and shape features
158
+ colors_info = self.extract_advanced_colors(image, n_colors=3)
159
+
160
+ # Business style indicators: neutral colors, structured shapes
161
+ if any(color["name"] in ["黑色", "深灰", "海军蓝", "白色"] for color in colors_info):
162
+ style_scores["商务正装"] = style_scores.get("商务正装", 0) + 20
163
+
164
+ # Casual style indicators: bright colors, relaxed tones
165
+ if any(color["name"] in ["天蓝", "苹果绿", "米白色"] for color in colors_info):
166
+ style_scores["休闲风"] = style_scores.get("休闲风", 0) + 15
167
+
168
+ # Fashion style indicators: vibrant colors, high saturation
169
+ avg_saturation = np.mean([color["saturation"] for color in colors_info])
170
+ if avg_saturation > 0.6:
171
+ style_scores["时尚潮流"] = style_scores.get("时尚潮流", 0) + 25
172
+
173
+ # Normalize scores to 0-100 range
174
+ if style_scores:
175
+ max_score = max(style_scores.values())
176
+ if max_score > 100:
177
+ style_scores = {k: min(v, 100) for k, v in style_scores.items()}
178
+
179
+ # Sort by confidence
180
+ return dict(sorted(style_scores.items(), key=lambda x: x[1], reverse=True))
181
+
182
+ class ModelManager:
183
+ """Enhanced model management with Hugging Face integration"""
184
+
185
+ def __init__(self):
186
+ self.caption_model = None
187
+ self.caption_processor = None
188
+ self.sd_pipeline = None
189
+ self.controlnet_pipeline = None
190
+ self._load_models()
191
+
192
+ def _load_models(self):
193
+ """Load AI models with Hugging Face integration"""
194
+ try:
195
+ logger.info("Loading models from Hugging Face...")
196
+
197
+ # 1. Load BLIP for image captioning (FIXED: Now actually using image understanding)
198
+ try:
199
+ self.caption_processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
200
+ self.caption_model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
201
+ logger.info("✅ BLIP image captioning model loaded")
202
+ except Exception as e:
203
+ logger.warning(f"Failed to load BLIP model: {e}")
204
+ # Fallback to a smaller model for Hugging Face Spaces
205
+ try:
206
+ self.caption_model = pipeline("image-to-text", model="nlpconnect/vit-gpt2-image-captioning")
207
+ logger.info("✅ Fallback image captioning model loaded")
208
+ except Exception as e2:
209
+ logger.error(f"Failed to load fallback model: {e2}")
210
+
211
+ # 2. Load Stable Diffusion for design generation
212
+ try:
213
+ # Use a lightweight SD model suitable for Spaces
214
+ model_id = "runwayml/stable-diffusion-v1-5"
215
+ self.sd_pipeline = StableDiffusionPipeline.from_pretrained(
216
+ model_id,
217
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
218
+ safety_checker=None,
219
+ requires_safety_checker=False
220
+ )
221
+
222
+ if torch.cuda.is_available():
223
+ self.sd_pipeline = self.sd_pipeline.to("cuda")
224
+
225
+ # Enable memory efficient attention
226
+ self.sd_pipeline.enable_attention_slicing()
227
+ logger.info("✅ Stable Diffusion pipeline loaded")
228
+
229
+ except Exception as e:
230
+ logger.warning(f"Failed to load SD pipeline: {e}")
231
+
232
+ # 3. Load ControlNet for better 3D fitting (FIXED: Better 3D model)
233
+ try:
234
+ controlnet = ControlNetModel.from_pretrained(
235
+ "lllyasviel/sd-controlnet-openpose",
236
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32
237
+ )
238
+
239
+ self.controlnet_pipeline = StableDiffusionControlNetPipeline.from_pretrained(
240
+ "runwayml/stable-diffusion-v1-5",
241
+ controlnet=controlnet,
242
+ torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
243
+ safety_checker=None,
244
+ requires_safety_checker=False
245
+ )
246
+
247
+ if torch.cuda.is_available():
248
+ self.controlnet_pipeline = self.controlnet_pipeline.to("cuda")
249
+
250
+ self.controlnet_pipeline.enable_attention_slicing()
251
+ logger.info("✅ ControlNet pipeline loaded for enhanced 3D fitting")
252
+
253
+ except Exception as e:
254
+ logger.warning(f"Failed to load ControlNet: {e}")
255
+
256
+ self._models_ready = True
257
+ logger.info("All models initialized successfully")
258
+
259
+ except Exception as e:
260
+ logger.error(f"Model loading failed: {e}")
261
+ self._models_ready = False
262
+
263
+ def generate_caption(self, image: Image.Image) -> str:
264
+ """Generate image caption using actual AI model (FIXED)"""
265
+ try:
266
+ if not self._models_ready:
267
+ return "图像分析暂不可用 - 模型未加载"
268
+
269
+ # Method 1: Use BLIP with processor
270
+ if self.caption_processor and self.caption_model:
271
+ inputs = self.caption_processor(image, return_tensors="pt")
272
+ out = self.caption_model.generate(**inputs, max_length=50)
273
+ caption = self.caption_processor.decode(out[0], skip_special_tokens=True)
274
+ return caption
275
+
276
+ # Method 2: Use pipeline fallback
277
+ elif hasattr(self.caption_model, '__call__'):
278
+ result = self.caption_model(image)
279
+ if isinstance(result, list) and len(result) > 0:
280
+ return result[0].get('generated_text', 'Fashion image analysis')
281
+
282
+ # Fallback: basic analysis
283
+ return "时尚服装图片 - 需要进一步分析"
284
+
285
+ except Exception as e:
286
+ logger.error(f"Caption generation failed: {e}")
287
+ return f"图像描述生成失败: {str(e)}"
288
+
289
+ def generate_image(self, prompt: str, negative_prompt: str = "", **kwargs) -> Optional[Image.Image]:
290
+ """Generate design image using Stable Diffusion (FIXED: Uses analysis results)"""
291
+ try:
292
+ if not self._models_ready or not self.sd_pipeline:
293
+ return self._create_placeholder_image("Stable Diffusion未就绪")
294
+
295
+ # Enhanced prompt engineering based on analysis
296
+ enhanced_prompt = f"high quality fashion design, {prompt}, professional photography, detailed, 4k"
297
+ enhanced_negative = f"blurry, low quality, distorted, text, watermark, deformed, ugly, {negative_prompt}"
298
+
299
+ # Generate with optimized parameters for Spaces
300
+ with torch.autocast("cuda" if torch.cuda.is_available() else "cpu"):
301
+ result = self.sd_pipeline(
302
+ prompt=enhanced_prompt,
303
+ negative_prompt=enhanced_negative,
304
+ num_inference_steps=kwargs.get('num_inference_steps', 20), # Reduced for speed
305
+ guidance_scale=kwargs.get('guidance_scale', 7.5),
306
+ width=kwargs.get('width', 512),
307
+ height=kwargs.get('height', 512),
308
+ generator=torch.Generator().manual_seed(random.randint(0, 2147483647))
309
+ )
310
+
311
+ return result.images[0]
312
+
313
+ except Exception as e:
314
+ logger.error(f"Image generation failed: {e}")
315
+ return self._create_placeholder_image(f"生成失败: {str(e)[:30]}...")
316
+
317
+ def generate_3d_fitting(self, prompt: str, pose_image: Optional[Image.Image] = None) -> Optional[Image.Image]:
318
+ """Generate enhanced 3D fitting using ControlNet (FIXED: Better 3D precision)"""
319
+ try:
320
+ if not self._models_ready:
321
+ return self._create_placeholder_image("3D模型未就绪")
322
+
323
+ # If ControlNet is available and we have pose guidance
324
+ if self.controlnet_pipeline and pose_image:
325
+ enhanced_prompt = f"3D virtual fashion model wearing {prompt}, photorealistic, professional studio lighting, full body, fashion photography, detailed textures"
326
+
327
+ with torch.autocast("cuda" if torch.cuda.is_available() else "cpu"):
328
+ result = self.controlnet_pipeline(
329
+ prompt=enhanced_prompt,
330
+ image=pose_image,
331
+ num_inference_steps=25,
332
+ guidance_scale=8.0,
333
+ controlnet_conditioning_scale=1.0
334
+ )
335
+ return result.images[0]
336
+
337
+ # Fallback to regular SD with enhanced 3D prompt
338
+ elif self.sd_pipeline:
339
+ enhanced_3d_prompt = f"3D rendered fashion model, {prompt}, volumetric lighting, realistic human proportions, fashion photography, professional quality, detailed fabric textures, studio lighting"
340
+
341
+ return self.generate_image(
342
+ prompt=enhanced_3d_prompt,
343
+ negative_prompt="flat, 2D, cartoon, anime, low quality, distorted proportions, bad anatomy",
344
+ num_inference_steps=30,
345
+ guidance_scale=8.5,
346
+ width=512,
347
+ height=768 # Taller for full body
348
+ )
349
+
350
+ return self._create_placeholder_image("3D生成功能不可用")
351
+
352
+ except Exception as e:
353
+ logger.error(f"3D fitting generation failed: {e}")
354
+ return self._create_placeholder_image("3D生成失败")
355
+
356
+ def _create_placeholder_image(self, text: str) -> Image.Image:
357
+ """Create placeholder image with text"""
358
+ img = Image.new('RGB', (512, 512), color=(240, 240, 245))
359
+ draw = ImageDraw.Draw(img)
360
+
361
+ # Calculate text position
362
+ text_lines = text.split('\n')
363
+ total_height = len(text_lines) * 20
364
+ start_y = (512 - total_height) // 2
365
+
366
+ for i, line in enumerate(text_lines):
367
+ text_width = len(line) * 8 # Approximate character width
368
+ x = (512 - text_width) // 2
369
+ y = start_y + i * 25
370
+ draw.text((x, y), line, fill=(100, 100, 100))
371
+
372
+ return img
373
+
374
+ def create_pose_reference(self, width: int = 512, height: int = 768) -> Image.Image:
375
+ """Create a simple pose reference for ControlNet"""
376
+ # Create a basic human pose outline
377
+ img = np.zeros((height, width, 3), dtype=np.uint8)
378
+
379
+ # Define key points for a standing pose (simplified)
380
+ # Head
381
+ cv2.circle(img, (width//2, height//6), 30, (255, 255, 255), 2)
382
+
383
+ # Body
384
+ cv2.line(img, (width//2, height//6 + 30), (width//2, height//2), (255, 255, 255), 3)
385
+
386
+ # Arms
387
+ cv2.line(img, (width//2, height//3), (width//2 - 60, height//2 - 20), (255, 255, 255), 2)
388
+ cv2.line(img, (width//2, height//3), (width//2 + 60, height//2 - 20), (255, 255, 255), 2)
389
+
390
+ # Legs
391
+ cv2.line(img, (width//2, height//2), (width//2 - 30, height - 50), (255, 255, 255), 3)
392
+ cv2.line(img, (width//2, height//2), (width//2 + 30, height - 50), (255, 255, 255), 3)
393
+
394
+ return Image.fromarray(img)
395
+
396
+ def cleanup(self):
397
+ """Clean up GPU memory for Hugging Face Spaces"""
398
+ try:
399
+ if torch.cuda.is_available():
400
+ torch.cuda.empty_cache()
401
+
402
+ # Force garbage collection
403
+ import gc
404
+ gc.collect()
405
+
406
+ logger.info("GPU memory and cache cleaned up")
407
+ return "✅ 内存已清理"
408
+ except Exception as e:
409
+ logger.error(f"Cleanup failed: {e}")
410
+ return f"❌ 清理失败: {str(e)}"
411
+
412
+ # Global instances
413
+ fashion_analyzer = FashionAnalyzer()
414
+ model_manager = ModelManager()
415
+
416
+ def upload_and_analyze(image_path):
417
+ """Enhanced image analysis with proper AI integration (FIXED)"""
418
+ try:
419
+ if image_path is None:
420
+ return {}, {}, gr.Radio(choices=[])
421
+
422
+ logger.info(f"Analyzing image: {image_path}")
423
+
424
+ # Load and validate image
425
+ try:
426
+ image = Image.open(image_path).convert('RGB')
427
+ except Exception as e:
428
+ return {"错误": f"无法打开图像文件: {str(e)}"}, {}, gr.Radio(choices=[])
429
+
430
+ # Generate comprehensive analysis
431
+ analysis_start = time.time()
432
+
433
+ # 1. Generate caption using actual AI model (FIXED)
434
+ caption = model_manager.generate_caption(image)
435
+ logger.info(f"Generated caption: {caption}")
436
+
437
+ # 2. Advanced color analysis from actual image
438
+ colors_info = fashion_analyzer.extract_advanced_colors(image)
439
+
440
+ # 3. Style analysis using BOTH image and caption (FIXED)
441
+ style_scores = fashion_analyzer.analyze_style_confidence_from_image(image, caption)
442
+ primary_style = list(style_scores.keys())[0] if style_scores else "休闲风"
443
+
444
+ # 4. Enhanced clothing category detection
445
+ clothing_category = infer_clothing_category(caption)
446
+
447
+ # 5. Scene recommendations based on analysis
448
+ suitable_scenes = get_enhanced_suitable_scenes(primary_style, colors_info)
449
+
450
+ # 6. Fashion trends analysis
451
+ trend_analysis = analyze_fashion_trends(primary_style, colors_info)
452
+
453
+ analysis_time = round(time.time() - analysis_start, 2)
454
+
455
+ # Comprehensive analysis result
456
+ analysis_result = {
457
+ "图像描述": caption,
458
+ "主要颜色": [color["name"] for color in colors_info[:3]],
459
+ "详细色彩分析": colors_info,
460
+ "风格分析": style_scores,
461
+ "主要风格": primary_style,
462
+ "服装类别": clothing_category,
463
+ "适合场景": suitable_scenes,
464
+ "流行趋势匹配": trend_analysis,
465
+ "图像尺寸": f"{image.width} x {image.height}",
466
+ "分析耗时": f"{analysis_time}秒",
467
+ "分析时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
468
+ "AI模型状态": "✅ 已连接" if model_manager._models_ready else "❌ 离线模式"
469
+ }
470
+
471
+ # Generate personalized suggestions BASED ON ANALYSIS (FIXED)
472
+ suggestions = generate_enhanced_suggestions(analysis_result)
473
+
474
+ # Create choice options
475
+ choices = list(suggestions.keys())
476
+
477
+ logger.info(f"Analysis completed in {analysis_time}s")
478
+ return analysis_result, suggestions, gr.Radio(choices=choices, value=choices[0] if choices else None)
479
+
480
+ except Exception as e:
481
+ logger.error(f"Analysis failed: {e}")
482
+ error_result = {"错误": f"分析过程中出现错误: {str(e)}"}
483
+ return error_result, {}, gr.Radio(choices=[])
484
+
485
+ def generate_designs(selected_suggestion, analysis_result, progress=gr.Progress()):
486
+ """Enhanced design generation using analysis results (FIXED)"""
487
+ try:
488
+ if not selected_suggestion:
489
+ return [], gr.Radio(choices=[])
490
+
491
+ logger.info(f"Generating designs for: {selected_suggestion}")
492
+
493
+ progress(0.1, desc="分析设计需求...")
494
+
495
+ # Extract key information from analysis (FIXED: Now uses actual analysis)
496
+ primary_style = analysis_result.get("主要风格", "休闲风") if analysis_result else "休闲风"
497
+ main_colors = analysis_result.get("主要颜色", ["蓝色"]) if analysis_result else ["蓝色"]
498
+ clothing_category = analysis_result.get("服装类别", "时尚单品") if analysis_result else "时尚单品"
499
+
500
+ # Generate design prompts based on actual analysis
501
+ design_prompts = create_analysis_based_prompts(selected_suggestion, primary_style, main_colors, clothing_category)
502
+
503
+ design_images = []
504
+ design_choices = []
505
+
506
+ total_designs = 4
507
+
508
+ for i in range(total_designs):
509
+ try:
510
+ progress_val = 0.2 + (i / total_designs) * 0.7
511
+ progress(progress_val, desc=f"生成设计方案 {i+1}/{total_designs}...")
512
+
513
+ prompt = design_prompts[i % len(design_prompts)]
514
+
515
+ # Generate image with analysis-based parameters
516
+ image = model_manager.generate_image(
517
+ prompt=prompt,
518
+ negative_prompt="blurry, low quality, distorted, text, watermark, deformed, ugly",
519
+ width=512,
520
+ height=512,
521
+ num_inference_steps=25, # Optimized for Spaces
522
+ guidance_scale=7.5
523
+ )
524
+
525
+ if image:
526
+ design_images.append(image)
527
+ design_choices.append(f"{selected_suggestion} - 方案{i+1}")
528
+ logger.info(f"Generated design {i+1} based on {primary_style} style")
529
+
530
+ except Exception as e:
531
+ logger.error(f"Failed to generate design {i+1}: {e}")
532
+ # Create error placeholder
533
+ error_img = model_manager._create_placeholder_image(f"方案{i+1}\n生成中...")
534
+ design_images.append(error_img)
535
+ design_choices.append(f"{selected_suggestion} - 方案{i+1}")
536
+
537
+ progress(0.95, desc="完成设计生成")
538
+ logger.info(f"Generated {len(design_images)} designs based on analysis results")
539
+
540
+ return design_images, gr.Radio(
541
+ choices=design_choices,
542
+ value=design_choices[0] if design_choices else None
543
+ )
544
+
545
+ except Exception as e:
546
+ logger.error(f"Design generation error: {e}")
547
+ return [], gr.Radio(choices=[])
548
+
549
+ def create_analysis_based_prompts(suggestion: str, style: str, colors: List[str], category: str) -> List[str]:
550
+ """Create prompts based on actual image analysis results (FIXED)"""
551
+
552
+ color_desc = ", ".join(colors[:2]) if colors else "neutral colors"
553
+
554
+ prompts = [
555
+ f"professional fashion design, {style} style, {category}, featuring {color_desc}, high quality, detailed, studio photography",
556
+ f"modern {category} design, {style} aesthetic, {color_desc} color palette, innovative cut, premium materials",
557
+ f"elegant {category}, {style} inspiration, {color_desc} tones, contemporary fashion, artistic design",
558
+ f"luxury {category} piece, {style} influence, {color_desc} color scheme, high-end fashion, detailed textures"
559
+ ]
560
+
561
+ # Add style-specific enhancements
562
+ if "商务" in style:
563
+ prompts = [p + ", professional, office appropriate, tailored fit" for p in prompts]
564
+ elif "休闲" in style:
565
+ prompts = [p + ", comfortable, everyday wear, relaxed fit" for p in prompts]
566
+ elif "运动" in style:
567
+ prompts = [p + ", athletic, functional, performance fabric" for p in prompts]
568
+ elif "时尚" in style:
569
+ prompts = [p + ", trendy, runway inspired, fashion forward" for p in prompts]
570
+
571
+ return prompts
572
+
573
+ def generate_3d_fitting(selected_design, progress=gr.Progress()):
574
+ """Enhanced 3D fitting generation with better precision (FIXED)"""
575
+ try:
576
+ if not selected_design:
577
+ return None
578
+
579
+ logger.info(f"Generating enhanced 3D fitting for: {selected_design}")
580
+
581
+ progress(0.1, desc="准备3D试穿环境...")
582
+
583
+ # Create pose reference for ControlNet
584
+ pose_image = model_manager.create_pose_reference()
585
+
586
+ progress(0.3, desc="生成人体模型...")
587
+
588
+ # Extract design details from selection
589
+ design_prompt = f"wearing {selected_design}, fashion model, full body view"
590
+
591
+ progress(0.6, desc="应用服装设计...")
592
+
593
+ # Generate 3D fitting with enhanced pipeline
594
+ image = model_manager.generate_3d_fitting(
595
+ prompt=design_prompt,
596
+ pose_image=pose_image
597
+ )
598
+
599
+ progress(0.9, desc="完成3D渲染")
600
+ logger.info("Enhanced 3D fitting generated successfully")
601
+
602
+ return image
603
+
604
+ except Exception as e:
605
+ logger.error(f"3D fitting generation error: {e}")
606
+ return model_manager._create_placeholder_image("3D试穿\n生成失败")
607
+
608
+ # Additional utility functions (keeping the existing ones but fixing issues)
609
+
610
+ def analyze_fashion_trends(style: str, colors_info: List[Dict]) -> Dict:
611
+ """Analyze current fashion trends"""
612
+ trends = {
613
+ "2024流行趋势": [],
614
+ "颜色趋势": [],
615
+ "材质趋势": [],
616
+ "设计元素": []
617
+ }
618
+
619
+ # Style-based trend analysis
620
+ if "商务" in style:
621
+ trends["2024流行趋势"].extend(["可持续面料", "多功能设计", "性别中性"])
622
+ trends["材质趋势"].extend(["有机棉", "再生纤维", "功能性面料"])
623
+ elif "休闲" in style:
624
+ trends["2024流行趋势"].extend(["舒适至上", "居家办公风", "运动休闲"])
625
+ trends["材质趋势"].extend(["弹性面料", "透气材质", "抗菌纤维"])
626
+
627
+ # Color trend analysis
628
+ dominant_colors = [color["name"] for color in colors_info[:2]]
629
+ if any("绿" in color for color in dominant_colors):
630
+ trends["颜色趋势"].append("生态绿色")
631
+ if any("蓝" in color for color in dominant_colors):
632
+ trends["颜色趋势"].append("经典蓝调")
633
+
634
+ trends["设计元素"] = ["极简线条", "功能细节", "可调节设计", "层次搭配"]
635
+
636
+ return trends
637
+
638
+ def get_enhanced_suitable_scenes(style_type: str, colors_info: List[Dict]) -> List[str]:
639
+ """Enhanced scene recommendations based on style and colors"""
640
+ base_scenes = {
641
+ "商务正装": ["高级办公环境", "商务会议", "正式谈判", "企业活动", "专业面试"],
642
+ "休闲风": ["咖啡厅约会", "周末购物", "朋友聚会", "公园散步", "居家办公"],
643
+ "运动风": ["健身房训练", "户外跑步", "瑜伽课程", "运动赛事", "休闲运动"],
644
+ "时尚潮流": ["时装周活动", "艺术展开幕", "网红打卡点", "时尚派对", "创意工作环境"],
645
+ "复古风": ["文艺咖啡厅", "古典音乐会", "复古主题派对", "艺术博物馆", "文化活动"],
646
+ "街头风": ["音乐节现场", "街头涂鸦区", "潮流市集", "滑板公园", "创意园区"],
647
+ "优雅风": ["高端晚宴", "歌剧院", "五星酒店", "慈善晚会", "高级社交场合"]
648
+ }
649
+
650
+ scenes = base_scenes.get(style_type, ["日常生活", "社交活动", "休闲娱乐"])
651
+
652
+ # Add season-specific scenes based on colors
653
+ seasons = [color.get("season_match", "") for color in colors_info]
654
+ if "春季" in seasons:
655
+ scenes.extend(["春日踏青", "花园聚会"])
656
+ elif "夏季" in seasons:
657
+ scenes.extend(["海滩度假", "夏日音乐节"])
658
+ elif "秋季" in seasons:
659
+ scenes.extend(["秋日登山", "文艺展览"])
660
+ elif "冬季" in seasons:
661
+ scenes.extend(["冬日聚会", "温暖室内活动"])
662
+
663
+ return list(set(scenes))
664
+
665
+ def infer_clothing_category(caption: str) -> str:
666
+ """Enhanced clothing category detection"""
667
+ caption_lower = caption.lower()
668
+
669
+ categories = {
670
+ "连衣裙": ["dress", "gown", "frock", "sundress", "连衣裙", "礼服", "长裙"],
671
+ "上衣": ["shirt", "blouse", "top", "sweater", "hoodie", "cardigan", "衬衫", "上衣", "毛衣"],
672
+ "外套": ["jacket", "coat", "blazer", "cardigan", "outerwear", "外套", "大衣", "夹克"],
673
+ "下装": ["pants", "jeans", "trousers", "skirt", "shorts", "裤子", "短裤", "裙子"],
674
+ "套装": ["suit", "ensemble", "matching set", "套装", "西装", "套服"],
675
+ "配饰": ["accessories", "hat", "bag", "shoes", "jewelry", "scarf", "帽子", "包", "鞋子", "配饰"],
676
+ "内衣": ["underwear", "lingerie", "bra", "内衣", "文胸"],
677
+ "运动装": ["sportswear", "athletic wear", "gym clothes", "运动装", "健身服"],
678
+ "睡衣": ["pajamas", "nightwear", "sleepwear", "睡衣", "家居服"]
679
+ }
680
+
681
+ # Calculate scores for each category
682
+ category_scores = {}
683
+ for category, keywords in categories.items():
684
+ score = sum(1 for keyword in keywords if keyword in caption_lower)
685
+ if score > 0:
686
+ category_scores[category] = score
687
+
688
+ if category_scores:
689
+ return max(category_scores.keys(), key=lambda x: category_scores[x])
690
+
691
+ return "时尚单品"
692
+
693
+ def generate_enhanced_suggestions(analysis_result: Dict) -> Dict:
694
+ """Generate enhanced personalized suggestions based on analysis"""
695
+ primary_style = analysis_result.get("主要风格", "休闲风")
696
+ colors = analysis_result.get("主要颜色", ["蓝色"])
697
+ trend_analysis = analysis_result.get("流行趋势匹配", {})
698
+
699
+ suggestions = {}
700
+
701
+ # Base style suggestions
702
+ style_variations = {
703
+ "商务正装": {
704
+ "现代商务精英": f"融合{primary_style}与现代设计,主打{colors[0]}色调",
705
+ "轻奢商务": f"{primary_style}加入轻奢元素,提升品质感",
706
+ "可持续商务": f"环保理念的{primary_style},使用可持续面料",
707
+ "多功能商务": f"一衣多穿的{primary_style}设计"
708
+ },
709
+ "休闲风": {
710
+ "都市休闲": f"现代都市感的{primary_style},主色调{colors[0]}",
711
+ "舒适至上": f"极致舒适的{primary_style}体验",
712
+ "运动休闲融合": f"{primary_style}与运动元素完美结合",
713
+ "艺术休闲": f"加入艺术元素的{primary_style}"
714
+ },
715
+ "运动风": {
716
+ "专业运动": f"专业级{primary_style},注重功能性",
717
+ "时尚运动": f"{primary_style}融入时尚潮流元素",
718
+ "户外探险": f"户外功能性{primary_style}设计",
719
+ "瑜伽冥想": f"身心和谐的{primary_style}体验"
720
+ }
721
+ }
722
+
723
+ # Get style-specific suggestions
724
+ if primary_style in style_variations:
725
+ suggestions.update(style_variations[primary_style])
726
+ else:
727
+ # Generic suggestions for other styles
728
+ suggestions = {
729
+ f"经典{primary_style}": f"保持{primary_style}的经典魅力",
730
+ f"现代{primary_style}": f"{primary_style}与现代元素结合",
731
+ f"个性{primary_style}": f"展现独特个性的{primary_style}",
732
+ f"趋势{primary_style}": f"紧跟2024流行趋势的{primary_style}"
733
+ }
734
+
735
+ # Add trend-based suggestions
736
+ if "可持续面料" in trend_analysis.get("2024流行趋势", []):
737
+ suggestions["环保时尚"] = f"可持续发展理念的{primary_style}设计"
738
+
739
+ return suggestions
740
+
741
+ def create_gradio_interface():
742
+ """Create Gradio interface optimized for Hugging Face Spaces"""
743
+
744
+ # Custom CSS optimized for Spaces
745
+ custom_css = """
746
+ .gradio-container {
747
+ font-family: 'Inter', sans-serif;
748
+ max-width: 1200px;
749
+ margin: 0 auto;
750
+ }
751
+ .main-header {
752
+ text-align: center;
753
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
754
+ color: white;
755
+ padding: 20px;
756
+ border-radius: 15px;
757
+ margin-bottom: 20px;
758
+ box-shadow: 0 4px 15px rgba(0,0,0,0.1);
759
+ }
760
+ .status-box {
761
+ background: #f8f9fa;
762
+ border: 1px solid #dee2e6;
763
+ border-radius: 8px;
764
+ padding: 10px;
765
+ margin: 5px 0;
766
+ }
767
+ """
768
+
769
+ with gr.Blocks(
770
+ title="AI时尚设计师 Pro - Hugging Face Spaces",
771
+ theme=gr.themes.Soft(),
772
+ css=custom_css
773
+ ) as demo:
774
+
775
+ # Header optimized for Spaces
776
+ gr.HTML("""
777
+ <div class="main-header">
778
+ <h1>🎨 AI时尚设计师 Pro</h1>
779
+ <p>基于 Hugging Face 的专业时尚设计平台</p>
780
+ <p>✨ BLIP图像理解 + Stable Diffusion设计生成 + ControlNet 3D试穿</p>
781
+ </div>
782
+ """)
783
+
784
+ # System status for debugging
785
+ with gr.Row():
786
+ with gr.Column():
787
+ system_info = gr.HTML(f"""
788
+ <div class="status-box">
789
+ <strong>系统状态:</strong>
790
+ CUDA可用: {torch.cuda.is_available()} |
791
+ 设备: {'GPU' if torch.cuda.is_available() else 'CPU'} |
792
+ 模型状态: {'✅ 就绪' if model_manager._models_ready else '⏳ 加载中'}
793
+ </div>
794
+ """)
795
+
796
+ # Main interface
797
+ with gr.Row():
798
+ # Left panel - Image upload and analysis
799
+ with gr.Column(scale=1):
800
+ gr.Markdown("## 📸 图片分析")
801
+
802
+ image_input = gr.Image(
803
+ type="filepath",
804
+ label="上传时尚图片",
805
+ height=300
806
+ )
807
+
808
+ with gr.Row():
809
+ analyze_btn = gr.Button(
810
+ "🔍 AI智能分析",
811
+ variant="primary",
812
+ size="lg"
813
+ )
814
+
815
+ # Analysis stats
816
+ with gr.Row():
817
+ with gr.Column():
818
+ analysis_time = gr.Textbox(label="分析耗时", interactive=False, container=False)
819
+ with gr.Column():
820
+ model_status = gr.Textbox(label="AI状态", interactive=False, container=False)
821
+
822
+ # Right panel - Results
823
+ with gr.Column(scale=2):
824
+ gr.Markdown("## 📊 分析结果")
825
+
826
+ with gr.Tabs():
827
+ with gr.Tab("🔬 详细分析"):
828
+ analysis_output = gr.JSON(label="完整分析报告")
829
+
830
+ with gr.Tab("🎨 色彩分析"):
831
+ color_analysis = gr.DataFrame(
832
+ headers=["颜色名称", "RGB值", "十六进制", "亮度", "饱和度", "季节匹配"],
833
+ label="色彩详细信息"
834
+ )
835
+
836
+ # Design suggestions section
837
+ gr.Markdown("## 💡 个性化设计建议")
838
+
839
+ with gr.Row():
840
+ with gr.Column(scale=2):
841
+ suggestions_output = gr.JSON(label="基于AI分析的设计建议")
842
+ with gr.Column(scale=1):
843
+ suggestion_choice = gr.Radio(label="选择设计方向", interactive=True)
844
+ generate_designs_btn = gr.Button("🚀 生成设计方案", variant="primary")
845
+
846
+ # Design results
847
+ with gr.Tabs():
848
+ with gr.Tab("🎯 设计方案"):
849
+ designs_gallery = gr.Gallery(
850
+ label="AI生成的设计方案 (基于图像分析)",
851
+ columns=2,
852
+ rows=2,
853
+ height=400
854
+ )
855
+ design_choice = gr.Radio(label="选择方案进行3D试穿", interactive=True)
856
+ generate_3d_btn = gr.Button("👤 生成3D试穿", variant="primary")
857
+
858
+ with gr.Tab("👥 3D试穿效果"):
859
+ fitting_result = gr.Image(label="ControlNet增强3D试穿效果", height=500)
860
+
861
+ with gr.Row():
862
+ gr.Markdown("""
863
+ **3D试穿技术说明:**
864
+ - 使用 ControlNet + OpenPose 实现精确人体建模
865
+ - 基于图像分析结果生成逼真试穿效果
866
+ - 支持全身服装展示和细节呈现
867
+ """)
868
+
869
+ # Performance controls for Spaces
870
+ with gr.Accordion("⚙️ 系统控制", open=False):
871
+ with gr.Row():
872
+ cleanup_btn = gr.Button("🧹 清理GPU内存", variant="secondary")
873
+ reload_models_btn = gr.Button("🔄 重新加载模型", variant="secondary")
874
+ memory_status = gr.Textbox(label="内存状态", interactive=False)
875
+
876
+ # Examples for quick testing
877
+ gr.Markdown("## 🌟 快速体验")
878
+
879
+ examples = [
880
+ ["examples/business_suit.jpg"] if os.path.exists("examples/business_suit.jpg") else None,
881
+ ["examples/casual_wear.jpg"] if os.path.exists("examples/casual_wear.jpg") else None,
882
+ ["examples/sport_outfit.jpg"] if os.path.exists("examples/sport_outfit.jpg") else None,
883
+ ]
884
+ examples = [ex for ex in examples if ex is not None]
885
+
886
+ if examples:
887
+ gr.Examples(
888
+ examples=examples,
889
+ inputs=image_input,
890
+ label="点击体验示例"
891
+ )
892
+
893
+ # Hidden state for passing data between functions
894
+ analysis_state = gr.State({})
895
+
896
+ # Event handlers with proper data flow
897
+
898
+ def enhanced_analysis(image_path):
899
+ """Enhanced analysis with better error handling"""
900
+ try:
901
+ result = upload_and_analyze(image_path)
902
+ analysis_result, suggestions, suggestion_radio = result
903
+
904
+ # Update analysis state
905
+ analysis_state.value = analysis_result
906
+
907
+ # Prepare color analysis table
908
+ color_data = []
909
+ if "详细色彩分析" in analysis_result:
910
+ for color_info in analysis_result["详细色彩分析"]:
911
+ color_data.append([
912
+ color_info.get("name", "未知"),
913
+ str(color_info.get("rgb", [0, 0, 0])),
914
+ color_info.get("hex", "#000000"),
915
+ f"{color_info.get('brightness', 0):.2f}",
916
+ f"{color_info.get('saturation', 0):.2f}",
917
+ color_info.get("season_match", "未知")
918
+ ])
919
+
920
+ # Extract timing and status
921
+ time_taken = analysis_result.get("分析耗时", "未知")
922
+ ai_status = analysis_result.get("AI模型状态", "未知")
923
+
924
+ return (
925
+ analysis_result,
926
+ suggestions,
927
+ suggestion_radio,
928
+ color_data,
929
+ time_taken,
930
+ ai_status,
931
+ analysis_result # Update state
932
+ )
933
+
934
+ except Exception as e:
935
+ logger.error(f"Enhanced analysis failed: {e}")
936
+ error_result = {"错误": f"分析失败: {str(e)}"}
937
+ return error_result, {}, gr.Radio(choices=[]), [], "错误", "❌ 分析失败", {}
938
+
939
+ # Bind main analysis event
940
+ analyze_btn.click(
941
+ fn=enhanced_analysis,
942
+ inputs=[image_input],
943
+ outputs=[
944
+ analysis_output,
945
+ suggestions_output,
946
+ suggestion_choice,
947
+ color_analysis,
948
+ analysis_time,
949
+ model_status,
950
+ analysis_state
951
+ ]
952
+ )
953
+
954
+ # Design generation with analysis integration
955
+ generate_designs_btn.click(
956
+ fn=lambda suggestion, analysis: generate_designs(suggestion, analysis),
957
+ inputs=[suggestion_choice, analysis_state],
958
+ outputs=[designs_gallery, design_choice]
959
+ )
960
+
961
+ # 3D fitting generation
962
+ generate_3d_btn.click(
963
+ fn=generate_3d_fitting,
964
+ inputs=[design_choice],
965
+ outputs=[fitting_result]
966
+ )
967
+
968
+ # System controls
969
+ cleanup_btn.click(
970
+ fn=model_manager.cleanup,
971
+ inputs=[],
972
+ outputs=[memory_status]
973
+ )
974
+
975
+ def reload_models():
976
+ try:
977
+ model_manager.__init__() # Reinitialize
978
+ return "✅ 模型重新加载完成"
979
+ except Exception as e:
980
+ return f"❌ 重新加载失败: {str(e)}"
981
+
982
+ reload_models_btn.click(
983
+ fn=reload_models,
984
+ inputs=[],
985
+ outputs=[memory_status]
986
+ )
987
+
988
+ # Footer with Spaces-specific information
989
+ gr.Markdown("""
990
+ ---
991
+ ### 🚀 Hugging Face Spaces 优化版
992
+
993
+ **技术栈:**
994
+ - 🔤 BLIP: 图像理解与描述生成
995
+ - 🎨 Stable Diffusion 1.5: 设计方案生成
996
+ - 🏃 ControlNet + OpenPose: 精确3D试穿
997
+ - 📊 scikit-learn: 智能色彩分析
998
+
999
+ **性能优化:**
1000
+ - ⚡ 针对 Spaces GPU/CPU 环境优化
1001
+ - 🧠 智能内存管理,避免OOM
1002
+ - 🔄 自动模型清理和重载
1003
+ - 📱 响应式界面设计
1004
+
1005
+ > 💡 **提示**: 首次运行需要下载模型,请稍等片刻。生成过程中可能需要1-3分钟。
1006
+ """)
1007
+
1008
+ return demo
1009
+
1010
+ def main():
1011
+ """Main function optimized for Hugging Face Spaces"""
1012
+ try:
1013
+ # Create necessary directories
1014
+ os.makedirs("examples", exist_ok=True)
1015
+
1016
+ logger.info("Starting AI Fashion Designer Pro on Hugging Face Spaces...")
1017
+ logger.info(f"CUDA Available: {torch.cuda.is_available()}")
1018
+ logger.info(f"PyTorch Version: {torch.__version__}")
1019
+
1020
+ # Create and launch interface
1021
+ demo = create_gradio_interface()
1022
+
1023
+ # Configure for Spaces
1024
+ demo.queue(
1025
+ concurrency_count=1, # Limited concurrency for Spaces
1026
+ max_size=5,
1027
+ api_open=False
1028
+ )
1029
+
1030
+ # Launch with Spaces-optimized settings
1031
+ demo.launch(
1032
+ server_name="0.0.0.0",
1033
+ server_port=7860,
1034
+ share=False, # Spaces handles sharing
1035
+ show_error=True,
1036
+ quiet=False,
1037
+ favicon_path=None
1038
+ )
1039
+
1040
+ except Exception as e:
1041
+ logger.error(f"Application startup failed: {e}")
1042
+ print(f"Error: {e}")
1043
+ raise
1044
+
1045
+ if __name__ == "__main__":
1046
+ main()