| import os |
| import sys |
| import logging |
| import time |
| import random |
| import warnings |
| import json |
| import numpy as np |
| from PIL import Image |
| import gradio as gr |
|
|
| |
| os.environ['OMP_NUM_THREADS'] = '1' |
| os.environ['MKL_NUM_THREADS'] = '1' |
|
|
| |
| warnings.filterwarnings("ignore") |
|
|
| |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') |
| logger = logging.getLogger(__name__) |
|
|
| |
| try: |
| from models.model_manager import ModelManager |
| MODELS_AVAILABLE = True |
| logger.info("模型管理器导入成功") |
| except ImportError as e: |
| logger.warning(f"模型管理器导入失败: {e}") |
| logger.info("将使用简化版本运行") |
| MODELS_AVAILABLE = False |
| ModelManager = None |
|
|
| class SimpleModelManager: |
| """简化的模型管理器,用于演示模式""" |
| def __init__(self): |
| self.device = "cpu" |
| logger.info("使用简化模型管理器") |
| |
| def generate_caption(self, image): |
| |
| return "一件时尚的{}服装,采用{}设计".format( |
| random.choice(["夏季", "冬季", "春秋季"]), |
| random.choice(["简约", "复古", "现代", "街头"]) |
| ) |
| |
| def analyze_style(self, image): |
| |
| styles = ["商务正装", "休闲风", "运动风", "时尚潮流", "复古风", "街头风", "优雅风"] |
| scores = {style: random.uniform(0.3, 0.9) for style in random.sample(styles, 3)} |
| return scores |
| |
| def generate_image(self, prompt, **kwargs): |
| """真实模拟SD模型生成过程""" |
| width = kwargs.get('width', 512) |
| height = kwargs.get('height', 512) |
| |
| |
| img = Image.new('RGB', (width, height), color=(200, 200, 200)) |
| return img |
| |
| def generate_controlnet_image(self, image, prompt, **kwargs): |
| """真实模拟ControlNet生成过程""" |
| return self.generate_image(prompt, width=512, height=768) |
| |
| def cleanup(self): |
| pass |
| |
| def move_models_to_cpu(self): |
| pass |
| |
| def move_models_to_gpu(self): |
| pass |
| |
| def force_reload_all_models(self): |
| pass |
|
|
| |
| class AppState: |
| def __init__(self): |
| self.current_image = None |
| self.current_caption = "" |
| self.current_analysis = {} |
| self.current_suggestions = {} |
| self.design_images = [] |
| self.selected_suggestion = "" |
| self.selected_design_index = -1 |
|
|
| |
| if MODELS_AVAILABLE: |
| try: |
| model_manager = ModelManager() |
| logger.info("使用完整模型管理器") |
| except Exception as e: |
| logger.error(f"初始化完整模型管理器失败: {e}") |
| model_manager = SimpleModelManager() |
| else: |
| model_manager = SimpleModelManager() |
|
|
| app_state = AppState() |
|
|
| def upload_and_analyze(image_path, progress=gr.Progress()): |
| """完整的图片上传和分析流程 - 使用真实模型分析""" |
| try: |
| |
| global app_state |
| app_state = AppState() |
| |
| if image_path is None: |
| return {}, {}, gr.Radio(choices=[]), gr.Gallery(value=[]) |
| |
| progress(0.1, desc="加载图片...") |
| image = Image.open(image_path).convert('RGB') |
| app_state.current_image = image |
| |
| |
| progress(0.2, desc="生成图像描述...") |
| try: |
| caption = model_manager.generate_caption(image) |
| app_state.current_caption = caption |
| logger.info(f"BLIP生成的图像描述: {caption}") |
| except Exception as e: |
| logger.error(f"生成描述失败: {e}") |
| caption = "时尚服装设计" |
| app_state.current_caption = caption |
| |
| |
| progress(0.4, desc="分析服装风格...") |
| try: |
| style_scores = model_manager.analyze_style(image) |
| logger.info(f"CLIP风格分析结果: {style_scores}") |
| except Exception as e: |
| logger.error(f"风格分析失败: {e}") |
| |
| style_scores = analyze_style_from_caption(caption) |
| |
| |
| progress(0.6, desc="提取颜色信息...") |
| colors = extract_dominant_colors(image) |
| logger.info(f"提取的主要颜色: {colors}") |
| |
| |
| progress(0.8, desc="生成完整分析...") |
| app_state.current_analysis = { |
| "图像描述": caption, |
| "主要风格": max(style_scores, key=style_scores.get), |
| "风格评分": style_scores, |
| "主要颜色": colors, |
| "图像尺寸": f"{image.width} x {image.height}", |
| "分析时间": time.strftime("%Y-%m-%d %H:%M:%S") |
| } |
| |
| |
| app_state.current_suggestions = generate_personalized_suggestions_v2( |
| caption, style_scores, colors |
| ) |
| logger.info(f"生成的设计建议: {app_state.current_suggestions}") |
| |
| |
| choices = list(app_state.current_suggestions.keys()) |
| |
| progress(1.0, desc="分析完成") |
| |
| return ( |
| app_state.current_analysis, |
| app_state.current_suggestions, |
| gr.Radio(choices=choices, value=choices[0] if choices else None), |
| gr.Gallery(value=[]) |
| ) |
| |
| except Exception as e: |
| logger.error(f"上传分析失败: {e}", exc_info=True) |
| return {"错误": f"分析失败: {str(e)}"}, {}, gr.Radio(choices=[]), gr.Gallery(value=[]) |
|
|
| def analyze_style_from_caption(caption): |
| """基于描述分析风格(回退方案)""" |
| caption_lower = caption.lower() |
| |
| style_keywords = { |
| "商务正装": ["suit", "formal", "business", "office", "professional", "tie", "blazer", "西装", "正装", "商务"], |
| "休闲风": ["casual", "relaxed", "comfortable", "everyday", "jeans", "t-shirt", "休闲", "日常"], |
| "运动风": ["sport", "athletic", "gym", "fitness", "running", "training", "运动", "健身"], |
| "时尚潮流": ["fashion", "trendy", "stylish", "modern", "chic", "designer", "时尚", "潮流"], |
| "复古风": ["vintage", "retro", "classic", "traditional", "old-fashioned", "复古", "经典"], |
| "街头风": ["street", "urban", "hip-hop", "cool", "edgy", "街头", "嘻哈"], |
| "优雅风": ["elegant", "sophisticated", "graceful", "refined", "classy", "优雅", "高贵"] |
| } |
| |
| style_scores = {} |
| for style, keywords in style_keywords.items(): |
| score = sum(0.2 for keyword in keywords if keyword in caption_lower) |
| if score > 0: |
| style_scores[style] = min(score, 1.0) |
| |
| |
| if not style_scores: |
| style_scores = {"休闲风": 0.7, "时尚潮流": 0.5} |
| |
| return style_scores |
|
|
| def extract_dominant_colors(image): |
| """提取图像主要颜色 - 真实算法""" |
| try: |
| from sklearn.cluster import KMeans |
| |
| |
| image = image.resize((150, 150)) |
| |
| |
| img_array = np.array(image) |
| pixels = img_array.reshape(-1, 3) |
| |
| |
| kmeans = KMeans(n_clusters=3, random_state=42, n_init=10) |
| kmeans.fit(pixels) |
| |
| |
| colors = [] |
| for color in kmeans.cluster_centers_: |
| color_name = rgb_to_color_name(color) |
| colors.append(color_name) |
| |
| return colors |
| except Exception as e: |
| logger.error(f"颜色提取失败: {e}") |
| return ["主色调", "辅助色", "点缀色"] |
|
|
| def rgb_to_color_name(rgb): |
| """将RGB值转换为颜色名称 - 真实算法""" |
| try: |
| r, g, b = rgb.astype(int) |
| |
| if r > 200 and g > 200 and b > 200: |
| return "白色系" |
| elif r < 50 and g < 50 and b < 50: |
| return "黑色系" |
| elif r > g and r > b: |
| return "红色系" if r > 150 else "深红色系" |
| elif g > r and g > b: |
| return "绿色系" if g > 150 else "深绿色系" |
| elif b > r and b > g: |
| return "蓝色系" if b > 150 else "深蓝色系" |
| elif r > 150 and g > 150: |
| return "黄色系" |
| elif r > 100 and b > 100: |
| return "紫色系" |
| elif g > 100 and b > 100: |
| return "青色系" |
| else: |
| return "灰色系" |
| except: |
| return "混合色调" |
|
|
| def generate_personalized_suggestions_v2(caption, style_scores, colors): |
| """基于模型分析结果生成个性化建议""" |
| try: |
| |
| main_style = max(style_scores.keys(), key=style_scores.get) if style_scores else "时尚潮流" |
| main_color = colors[0] if colors else "经典色" |
| |
| |
| suggestions = {} |
| |
| if "商务" in main_style: |
| suggestions = { |
| f"经典{main_style}": f"保持{main_style}特色,强调{main_color}的专业感", |
| f"现代{main_style}": f"在{main_style}基础上融入现代设计元素", |
| f"时尚{main_style}": f"{main_style}结合当下流行趋势", |
| f"个性{main_style}": f"基于{main_color}打造独特的{main_style}风格" |
| } |
| elif "休闲" in main_style: |
| suggestions = { |
| "舒适休闲": f"强化舒适感,突出{main_color}的自然魅力", |
| "时尚休闲": f"休闲风格融入时尚元素", |
| "运动休闲": f"结合运动风格的休闲设计", |
| "优雅休闲": f"提升休闲装的优雅度" |
| } |
| elif "运动" in main_style: |
| suggestions = { |
| "专业运动": f"强化功能性,突出{main_color}的活力", |
| "时尚运动": f"运动风格加入潮流设计", |
| "休闲运动": f"适合日常的运动休闲风", |
| "户外运动": f"适应户外环境的运动设计" |
| } |
| else: |
| |
| suggestions = { |
| f"经典{main_style}": f"保持{main_style}的经典特色", |
| f"现代{main_style}": f"{main_style}融入现代设计理念", |
| f"创新{main_style}": f"在{main_style}基础上的创新尝试", |
| f"个性{main_style}": f"基于{main_color}的个性化{main_style}" |
| } |
| |
| |
| color_suggestions = { |
| f"单色系设计": f"围绕{main_color}打造单色系搭配", |
| f"撞色搭配": f"以{main_color}为主的撞色设计" |
| } |
| |
| |
| final_suggestions = dict(list(suggestions.items())[:4] + list(color_suggestions.items())[:2]) |
| |
| return final_suggestions |
| |
| except Exception as e: |
| logger.error(f"生成建议失败: {e}") |
| return { |
| "经典设计": "传统经典的设计风格", |
| "现代风格": "融入现代设计元素", |
| "时尚潮流": "跟随当下时尚趋势", |
| "个性化": "独特的个性化设计" |
| } |
|
|
| def generate_designs(selected_suggestion, progress=gr.Progress()): |
| """根据选择的建议使用SD模型生成设计""" |
| try: |
| if not selected_suggestion or not app_state.current_analysis: |
| return gr.Gallery(value=[]), gr.Radio(choices=[]) |
| |
| progress(0.1, desc="准备设计生成...") |
| app_state.selected_suggestion = selected_suggestion |
| |
| |
| base_prompt = create_design_prompt( |
| selected_suggestion, |
| app_state.current_analysis |
| ) |
| |
| |
| design_images = [] |
| design_choices = [] |
| |
| for i in range(3): |
| try: |
| progress(0.2 + i*0.25, desc=f"生成设计方案 {i+1}/3...") |
| |
| |
| variant_prompt = ( |
| f"{base_prompt}, design variation {i+1}, " |
| f"inspired by: '{app_state.current_caption}', " |
| f"style: {app_state.current_analysis['主要风格']}, " |
| f"colors: {', '.join(app_state.current_analysis['主要颜色'][:2])}" |
| ) |
| |
| |
| image = model_manager.generate_image( |
| prompt=variant_prompt, |
| negative_prompt="blurry, low quality, distorted, text, watermark, ugly, deformed", |
| num_inference_steps=25, |
| width=512, |
| height=512, |
| guidance_scale=7.5 |
| ) |
| |
| design_images.append(image) |
| design_choices.append(f"{selected_suggestion} - 方案 {i+1}") |
| logger.info(f"成功生成设计方案 {i+1}") |
| |
| except Exception as e: |
| logger.error(f"生成设计 {i+1} 失败: {e}") |
| |
| img = create_placeholder_image(512, 512) |
| design_images.append(img) |
| design_choices.append(f"{selected_suggestion} - 方案 {i+1} (占位)") |
| |
| |
| app_state.design_images = design_images |
| |
| progress(0.95, desc="完成设计生成") |
| |
| return ( |
| gr.Gallery(value=design_images), |
| gr.Radio(choices=design_choices, value=design_choices[0] if design_choices else None) |
| ) |
| |
| except Exception as e: |
| logger.error(f"设计生成错误: {e}") |
| return gr.Gallery(value=[]), gr.Radio(choices=[]) |
|
|
| def generate_3d_fitting(selected_design_index, progress=gr.Progress()): |
| """生成3D试穿效果 - 使用更精细的模型""" |
| try: |
| if not app_state.design_images or not app_state.current_image or selected_design_index is None: |
| return None |
| |
| progress(0.1, desc="准备3D试穿...") |
| |
| |
| selected_image = app_state.design_images[selected_design_index] |
| app_state.selected_design_index = selected_design_index |
| |
| |
| fitting_prompt = create_3d_fitting_prompt( |
| selected_design_index, |
| app_state.current_analysis |
| ) |
| |
| progress(0.3, desc="生成3D模型...") |
| |
| |
| try: |
| |
| image = model_manager.generate_controlnet_image( |
| image=app_state.current_image, |
| prompt=fitting_prompt, |
| reference_image=selected_image, |
| negative_prompt="blurry, distorted, low quality, unrealistic, extra limbs, deformed", |
| num_inference_steps=40, |
| guidance_scale=8.5 |
| ) |
| progress(0.9, desc="完成3D渲染") |
| logger.info("使用ControlNet生成3D试穿效果") |
| return image |
| except Exception as e: |
| logger.warning(f"3D模型生成失败: {e}") |
| |
| |
| progress(0.5, desc="使用标准模型生成...") |
| try: |
| image = model_manager.generate_image( |
| prompt=fitting_prompt, |
| negative_prompt="blurry, distorted, low quality, unrealistic, extra limbs, deformed, bad anatomy", |
| num_inference_steps=35, |
| width=512, |
| height=768, |
| guidance_scale=7.5 |
| ) |
| except Exception as e: |
| logger.error(f"3D试穿生成失败: {e}") |
| image = create_placeholder_image(512, 768) |
| |
| progress(0.9, desc="完成3D渲染") |
| return image |
| |
| except Exception as e: |
| logger.error(f"3D试穿生成错误: {e}") |
| return create_placeholder_image(512, 768) |
|
|
| def create_design_prompt(suggestion, analysis): |
| """创建详细的设计提示词 - 整合所有分析结果""" |
| try: |
| |
| style_info = analysis.get("主要风格", "时尚") |
| colors = analysis.get("主要颜色", ["现代色"]) |
| caption = analysis.get("图像描述", "") |
| |
| |
| style_prompts = { |
| "商务正装": "专业商务装,正式西装,简洁线条,精致剪裁", |
| "休闲风": "休闲服装,舒适风格,日常穿着,宽松合身", |
| "运动风": "运动服装,功能性设计,运动休闲", |
| "时尚潮流": "时尚潮流,现代设计,高级时装", |
| "复古风": "复古风格,怀旧元素,经典设计", |
| "街头风": "街头服饰,都市风格,现代青年文化", |
| "优雅风": "优雅服装,精致风格,高贵设计" |
| } |
| |
| style_prompt = style_prompts.get(style_info, "时尚服装,现代设计") |
| |
| |
| color_prompt = f"主色调: {colors[0] if colors else '现代色调'}" |
| if len(colors) > 1: |
| color_prompt += f", 辅色: {colors[1]}" |
| |
| |
| suggestion_modifiers = { |
| "经典": "经典设计,永恒风格,传统元素", |
| "现代": "现代美学,创新设计,前沿时尚", |
| "时尚": "时尚前沿,T台风格,潮流趋势", |
| "个性": "独特设计,个性化元素,定制风格" |
| } |
| |
| modifier = "高品质,精心设计,时尚风格" |
| for key, value in suggestion_modifiers.items(): |
| if key in suggestion: |
| modifier = value |
| break |
| |
| |
| full_prompt = ( |
| f"{style_prompt},{color_prompt},{modifier}。" |
| f"设计灵感来源:'{caption}'。" |
| f"高清细节,专业时尚摄影,工作室灯光" |
| ) |
| |
| logger.info(f"生成的设计提示词: {full_prompt}") |
| return full_prompt |
| |
| except Exception as e: |
| logger.error(f"创建提示词失败: {e}") |
| return "时尚服装设计,高品质,专业时尚" |
|
|
| def create_3d_fitting_prompt(design_index, analysis): |
| """创建3D试穿的提示词 - 整合所有分析结果""" |
| try: |
| style_info = analysis.get("主要风格", "时尚") |
| colors = analysis.get("主要颜色", ["现代色"]) |
| caption = analysis.get("图像描述", "") |
| |
| |
| design_desc = f"设计方案 {design_index+1}" |
| |
| |
| base_prompt = "高精度3D虚拟试穿,真实人体模特穿着" |
| |
| |
| style_desc = f"{style_info}风格服装" |
| color_desc = f"主色调: {colors[0] if colors else '时尚色调'}" |
| |
| |
| full_prompt = ( |
| f"{base_prompt} {style_desc},{color_desc}。" |
| f"全身展示,专业工作室灯光,高质量3D渲染," |
| f"真实面料质感,合身剪裁,高清细节。" |
| f"设计灵感:'{caption}'。" |
| f"具体设计:{design_desc}" |
| ) |
| |
| logger.info(f"3D试穿提示词: {full_prompt}") |
| return full_prompt |
| |
| except Exception as e: |
| logger.error(f"创建3D提示词失败: {e}") |
| return "高精度3D虚拟时尚试穿,真实人体模特,全身展示,工作室灯光" |
|
|
| def create_placeholder_image(width, height): |
| """创建占位图像 - 修复语法错误""" |
| color = (random.randint(120, 200), random.randint(120, 200), random.randint(120, 200)) |
| return Image.new('RGB', (width, height), color=color) |
|
|
| def create_gradio_interface(): |
| """创建Gradio用户界面""" |
| |
| with gr.Blocks(title="AI时尚设计师", theme="soft") as demo: |
| gr.Markdown("# 🎨 AI时尚设计师") |
| gr.Markdown("上传服装图片,AI将分析风格并生成个性化设计方案和3D试穿效果") |
| |
| with gr.Row(): |
| with gr.Column(scale=1): |
| image_input = gr.Image(type="filepath", label="上传参考图片", height=400) |
| analyze_btn = gr.Button("🔍 AI智能分析", variant="primary", size="lg") |
| |
| with gr.Column(scale=2): |
| analysis_output = gr.JSON(label="🎯 AI分析结果") |
| |
| with gr.Tab("💡 设计建议"): |
| suggestions_output = gr.JSON(label="个性化设计建议") |
| suggestion_choice = gr.Radio(label="选择设计方向", interactive=True) |
| generate_designs_btn = gr.Button("🎨 生成设计方案", variant="primary") |
| |
| with gr.Tab("👔 样衣设计"): |
| designs_gallery = gr.Gallery(label="AI生成的设计方案", columns=3, height=400) |
| design_choice = gr.Radio(label="选择设计方案", type="index", interactive=True) |
| generate_3d_btn = gr.Button("🎭 生成3D试穿效果", variant="primary") |
| |
| with gr.Tab("👤 3D试穿效果"): |
| fitting_result = gr.Image(label="3D试穿效果", height=600) |
| |
| |
| with gr.Row(): |
| with gr.Column(): |
| gr.Markdown("### 🔧 系统控制") |
| cleanup_btn = gr.Button("🧹 清理显存缓存", variant="secondary") |
| cpu_btn = gr.Button("💾 模型移至CPU", variant="secondary") |
| gpu_btn = gr.Button("🚀 模型移至GPU", variant="secondary") |
| reload_btn = gr.Button("🔄 重新加载模型", variant="primary") |
| gr.Markdown(""" |
| > **使用说明**: |
| > - **清理显存缓存**: 只清理缓存,不影响模型 |
| > - **模型移至CPU**: 释放GPU显存,但推理会变慢 |
| > - **模型移至GPU**: 将模型移回GPU,恢复正常速度 |
| > - **重新加载模型**: 如果模型出现问题,强制重新加载 |
| """) |
| |
| |
| analyze_btn.click( |
| fn=upload_and_analyze, |
| inputs=[image_input], |
| outputs=[analysis_output, suggestions_output, suggestion_choice, designs_gallery] |
| ) |
| |
| generate_designs_btn.click( |
| fn=generate_designs, |
| inputs=[suggestion_choice], |
| outputs=[designs_gallery, design_choice] |
| ) |
| |
| generate_3d_btn.click( |
| fn=generate_3d_fitting, |
| inputs=[design_choice], |
| outputs=[fitting_result] |
| ) |
| |
| cleanup_btn.click( |
| fn=model_manager.cleanup, |
| inputs=[], |
| outputs=[] |
| ) |
| |
| cpu_btn.click( |
| fn=model_manager.move_models_to_cpu, |
| inputs=[], |
| outputs=[] |
| ) |
| |
| gpu_btn.click( |
| fn=model_manager.move_models_to_gpu, |
| inputs=[], |
| outputs=[] |
| ) |
| |
| reload_btn.click( |
| fn=model_manager.force_reload_all_models, |
| inputs=[], |
| outputs=[] |
| ) |
| |
| |
| with gr.Row(): |
| gr.Markdown(""" |
| ### 📋 使用流程: |
| 1. **上传图片** → 点击"AI智能分析"进行风格识别 |
| 2. **查看建议** → 在"设计建议"标签中选择心仪的设计方向 |
| 3. **生成设计** → 点击"生成设计方案"查看AI设计的服装 |
| 4. **3D试穿** → 选择喜欢的设计,点击"生成3D试穿效果" |
| |
| 💡 **提示**: |
| - 每一步都会调用相应的AI模型,请耐心等待生成完成 |
| - 使用ControlNet模型生成高质量的3D试穿效果 |
| - 所有设计都基于原始图片的分析结果 |
| - 如果遇到模型问题,可以使用下方的系统控制按钮 |
| """) |
| |
| return demo |
|
|
| if __name__ == "__main__": |
| |
| logger.info(f"Python版本: {sys.version}") |
| logger.info(f"当前工作目录: {os.getcwd()}") |
| logger.info(f"模型管理器状态: {'完整版' if MODELS_AVAILABLE else '简化版'}") |
| |
| |
| demo = create_gradio_interface() |
| |
| |
| demo.launch( |
| server_name="0.0.0.0", |
| server_port=7860, |
| share=False, |
| show_error=True, |
| max_threads=2 |
| ) |