Update app.py
Browse files
app.py
CHANGED
|
@@ -155,4 +155,826 @@ def advanced_color_analysis(image):
|
|
| 155 |
|
| 156 |
for i, (color, percentage) in enumerate(color_data):
|
| 157 |
color_name = rgb_to_detailed_color_name(color)
|
| 158 |
-
color_emotion =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
for i, (color, percentage) in enumerate(color_data):
|
| 157 |
color_name = rgb_to_detailed_color_name(color)
|
| 158 |
+
color_emotion = get_color_emotion(color)
|
| 159 |
+
dominant_colors.append(color_name)
|
| 160 |
+
|
| 161 |
+
color_palette[f"颜色{i+1}"] = {
|
| 162 |
+
"name": color_name,
|
| 163 |
+
"rgb": color.tolist(),
|
| 164 |
+
"hex": rgb_to_hex(color),
|
| 165 |
+
"percentage": f"{percentage:.1%}",
|
| 166 |
+
"emotion": color_emotion,
|
| 167 |
+
"fashion_application": get_fashion_application(color_name)
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
return {
|
| 171 |
+
"dominant_colors": dominant_colors[:3], # 前3种主要颜色
|
| 172 |
+
"color_palette": color_palette,
|
| 173 |
+
"color_harmony": analyze_color_harmony(colors[:3]),
|
| 174 |
+
"season_analysis": analyze_seasonal_colors(colors[:3])
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
except Exception as e:
|
| 178 |
+
logger.error(f"高级颜色分析失败: {e}")
|
| 179 |
+
return {
|
| 180 |
+
"dominant_colors": ["经典色调"],
|
| 181 |
+
"color_palette": {"颜色1": {"name": "经典色调", "emotion": "中性"}},
|
| 182 |
+
"color_harmony": "单色调",
|
| 183 |
+
"season_analysis": "四季通用"
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
def rgb_to_detailed_color_name(rgb):
|
| 187 |
+
"""更详细的RGB到颜色名称转换"""
|
| 188 |
+
r, g, b = rgb
|
| 189 |
+
|
| 190 |
+
# 转换到HSV空间进行更精确的颜色分类
|
| 191 |
+
h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
|
| 192 |
+
h = h * 360
|
| 193 |
+
s = s * 100
|
| 194 |
+
v = v * 100
|
| 195 |
+
|
| 196 |
+
# 基于HSV值进行精确分类
|
| 197 |
+
if v < 20:
|
| 198 |
+
return "深黑色"
|
| 199 |
+
elif v > 90 and s < 10:
|
| 200 |
+
return "纯白色"
|
| 201 |
+
elif s < 15:
|
| 202 |
+
if v < 30:
|
| 203 |
+
return "深灰色"
|
| 204 |
+
elif v < 70:
|
| 205 |
+
return "中灰色"
|
| 206 |
+
else:
|
| 207 |
+
return "浅灰色"
|
| 208 |
+
|
| 209 |
+
# 彩色分类
|
| 210 |
+
color_ranges = [
|
| 211 |
+
(0, 15, "深红色"), (15, 45, "橙红色"), (45, 75, "金黄色"),
|
| 212 |
+
(75, 105, "草绿色"), (105, 135, "翠绿色"), (135, 165, "青绿色"),
|
| 213 |
+
(165, 195, "天蓝色"), (195, 225, "宝蓝色"), (225, 255, "紫蓝色"),
|
| 214 |
+
(255, 285, "紫色"), (285, 315, "紫红色"), (315, 345, "玫红色"),
|
| 215 |
+
(345, 360, "深红色")
|
| 216 |
+
]
|
| 217 |
+
|
| 218 |
+
for start, end, color_name in color_ranges:
|
| 219 |
+
if start <= h < end:
|
| 220 |
+
if v < 40:
|
| 221 |
+
return f"深{color_name}"
|
| 222 |
+
elif v > 80:
|
| 223 |
+
return f"亮{color_name}"
|
| 224 |
+
else:
|
| 225 |
+
return color_name
|
| 226 |
+
|
| 227 |
+
return "混合色调"
|
| 228 |
+
|
| 229 |
+
def rgb_to_hex(rgb):
|
| 230 |
+
"""RGB转十六进制"""
|
| 231 |
+
return "#{:02x}{:02x}{:02x}".format(int(rgb[0]), int(rgb[1]), int(rgb[2]))
|
| 232 |
+
|
| 233 |
+
def get_color_emotion(rgb):
|
| 234 |
+
"""获取颜色的情感属性"""
|
| 235 |
+
r, g, b = rgb
|
| 236 |
+
|
| 237 |
+
# 基于颜色心理学的情感映射
|
| 238 |
+
if r > 180 and g < 100 and b < 100:
|
| 239 |
+
return "热情、力量、激情"
|
| 240 |
+
elif r < 100 and g > 150 and b < 100:
|
| 241 |
+
return "自然、平静、成长"
|
| 242 |
+
elif r < 100 and g < 100 and b > 150:
|
| 243 |
+
return "专业、信任、稳定"
|
| 244 |
+
elif r > 150 and g > 150 and b < 100:
|
| 245 |
+
return "温暖、活力、创意"
|
| 246 |
+
elif r > 100 and g < 100 and b > 150:
|
| 247 |
+
return "神秘、高贵、优雅"
|
| 248 |
+
elif r < 50 and g < 50 and b < 50:
|
| 249 |
+
return "经典、正式、权威"
|
| 250 |
+
elif r > 200 and g > 200 and b > 200:
|
| 251 |
+
return "纯洁、简约、现代"
|
| 252 |
+
else:
|
| 253 |
+
return "平衡、和谐、中性"
|
| 254 |
+
|
| 255 |
+
def get_fashion_application(color_name):
|
| 256 |
+
"""获取颜色在时尚中的应用建议"""
|
| 257 |
+
applications = {
|
| 258 |
+
"深红色": "晚装、正装细节、配饰",
|
| 259 |
+
"橙红色": "夏季休闲、运动装、配饰",
|
| 260 |
+
"金黄色": "夏季单品、配饰、装饰细节",
|
| 261 |
+
"草绿色": "春夏装、休闲装、自然风格",
|
| 262 |
+
"翠绿色": "春装、度假装、民族风格",
|
| 263 |
+
"天蓝色": "衬衫、夏装、商务休闲",
|
| 264 |
+
"宝蓝色": "正装、晚装、经典款式",
|
| 265 |
+
"紫色": "晚装、艺术风格、个性单品",
|
| 266 |
+
"深黑色": "基础款、正装、经典设计",
|
| 267 |
+
"纯白色": "基础款、夏装、简约风格",
|
| 268 |
+
"深灰色": "商务装、基础款、现代风格"
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
return applications.get(color_name, "通用时尚单品")
|
| 272 |
+
|
| 273 |
+
def analyze_color_harmony(colors):
|
| 274 |
+
"""分析颜色和谐度"""
|
| 275 |
+
if len(colors) < 2:
|
| 276 |
+
return "单色调"
|
| 277 |
+
|
| 278 |
+
# 转换为HSV进行分析
|
| 279 |
+
hsv_colors = []
|
| 280 |
+
for color in colors:
|
| 281 |
+
h, s, v = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0)
|
| 282 |
+
hsv_colors.append((h*360, s*100, v*100))
|
| 283 |
+
|
| 284 |
+
h_values = [hsv[0] for hsv in hsv_colors]
|
| 285 |
+
|
| 286 |
+
# 判断配色方案
|
| 287 |
+
h_diff = max(h_values) - min(h_values)
|
| 288 |
+
|
| 289 |
+
if h_diff < 30:
|
| 290 |
+
return "同色系配色"
|
| 291 |
+
elif h_diff < 60:
|
| 292 |
+
return "相邻色配色"
|
| 293 |
+
elif 150 < h_diff < 210:
|
| 294 |
+
return "对比色配色"
|
| 295 |
+
else:
|
| 296 |
+
return "多色调配色"
|
| 297 |
+
|
| 298 |
+
def analyze_seasonal_colors(colors):
|
| 299 |
+
"""分析季节色彩倾向"""
|
| 300 |
+
# 计算平均饱和度和明度
|
| 301 |
+
total_s, total_v = 0, 0
|
| 302 |
+
|
| 303 |
+
for color in colors:
|
| 304 |
+
h, s, v = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0)
|
| 305 |
+
total_s += s
|
| 306 |
+
total_v += v
|
| 307 |
+
|
| 308 |
+
avg_s = total_s / len(colors)
|
| 309 |
+
avg_v = total_v / len(colors)
|
| 310 |
+
|
| 311 |
+
if avg_s > 0.6 and avg_v > 0.6:
|
| 312 |
+
return "春季色彩(明亮、清新)"
|
| 313 |
+
elif avg_s > 0.6 and avg_v < 0.6:
|
| 314 |
+
return "秋季色彩(浓郁、温暖)"
|
| 315 |
+
elif avg_s < 0.6 and avg_v > 0.6:
|
| 316 |
+
return "夏季色彩(柔和、清淡)"
|
| 317 |
+
else:
|
| 318 |
+
return "冬季色彩(深沉、对比)"
|
| 319 |
+
|
| 320 |
+
def analyze_fabric_texture(image):
|
| 321 |
+
"""分析面料和质地(基于图像特征)"""
|
| 322 |
+
try:
|
| 323 |
+
# 转换为灰度图进行纹理分析
|
| 324 |
+
gray_image = image.convert('L')
|
| 325 |
+
img_array = np.array(gray_image)
|
| 326 |
+
|
| 327 |
+
# 计算纹理特征
|
| 328 |
+
# 1. 计算标准差(纹理粗糙度)
|
| 329 |
+
texture_variance = np.std(img_array)
|
| 330 |
+
|
| 331 |
+
# 2. 计算边缘密度
|
| 332 |
+
from scipy import ndimage
|
| 333 |
+
edges = ndimage.sobel(img_array)
|
| 334 |
+
edge_density = np.mean(np.abs(edges))
|
| 335 |
+
|
| 336 |
+
# 基于特征推断面料类型
|
| 337 |
+
if texture_variance < 20:
|
| 338 |
+
if edge_density < 10:
|
| 339 |
+
fabric_type = "丝绸"
|
| 340 |
+
texture = "光滑丝滑"
|
| 341 |
+
else:
|
| 342 |
+
fabric_type = "棉质"
|
| 343 |
+
texture = "柔软光滑"
|
| 344 |
+
elif texture_variance < 40:
|
| 345 |
+
fabric_type = "混纺"
|
| 346 |
+
texture = "适中质感"
|
| 347 |
+
else:
|
| 348 |
+
if edge_density > 30:
|
| 349 |
+
fabric_type = "牛仔"
|
| 350 |
+
texture = "粗糙硬挺"
|
| 351 |
+
else:
|
| 352 |
+
fabric_type = "毛呢"
|
| 353 |
+
texture = "厚实温暖"
|
| 354 |
+
|
| 355 |
+
return {
|
| 356 |
+
"predicted_fabric": fabric_type,
|
| 357 |
+
"texture": texture,
|
| 358 |
+
"texture_score": texture_variance,
|
| 359 |
+
"edge_score": edge_density,
|
| 360 |
+
"fabric_properties": get_fabric_properties(fabric_type)
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
except Exception as e:
|
| 364 |
+
logger.error(f"面料分析失败: {e}")
|
| 365 |
+
return {
|
| 366 |
+
"predicted_fabric": "棉质",
|
| 367 |
+
"texture": "舒适",
|
| 368 |
+
"fabric_properties": "透气、舒适、日常"
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
def get_fabric_properties(fabric_type):
|
| 372 |
+
"""获取面料特性"""
|
| 373 |
+
properties = {
|
| 374 |
+
"丝绸": "光泽感强、垂坠性好、高级感、适合正装",
|
| 375 |
+
"棉质": "透气舒适、日常休闲、易打理、四季适用",
|
| 376 |
+
"混纺": "结合优点、性价比高、适应性强、现代感",
|
| 377 |
+
"牛仔": "硬挺耐用、休闲风格、经典时尚、年轻活力",
|
| 378 |
+
"毛呢": "保暖性好、正式高级、秋冬首选、商务感强"
|
| 379 |
+
}
|
| 380 |
+
return properties.get(fabric_type, "舒适实用")
|
| 381 |
+
|
| 382 |
+
def comprehensive_image_analysis(image_path, progress=gr.Progress()):
|
| 383 |
+
"""综合图像分析 - 整合所有分析维度"""
|
| 384 |
+
try:
|
| 385 |
+
design_state.reset()
|
| 386 |
+
|
| 387 |
+
if image_path is None:
|
| 388 |
+
return {}, {}, gr.Radio(choices=[]), gr.Gallery(value=[])
|
| 389 |
+
|
| 390 |
+
progress(0.05, desc="加载图片...")
|
| 391 |
+
image = Image.open(image_path).convert('RGB')
|
| 392 |
+
design_state.original_image = image
|
| 393 |
+
|
| 394 |
+
# 1. BLIP图像描述
|
| 395 |
+
progress(0.15, desc="AI图像理解中...")
|
| 396 |
+
try:
|
| 397 |
+
caption = model_manager.generate_caption(image)
|
| 398 |
+
design_state.image_caption = caption
|
| 399 |
+
logger.info(f"BLIP描述: {caption}")
|
| 400 |
+
except Exception as e:
|
| 401 |
+
logger.error(f"图像描述生成失败: {e}")
|
| 402 |
+
caption = "时尚服装设计作品"
|
| 403 |
+
design_state.image_caption = caption
|
| 404 |
+
|
| 405 |
+
# 2. CLIP风格分析
|
| 406 |
+
progress(0.3, desc="AI风格识别中...")
|
| 407 |
+
try:
|
| 408 |
+
style_scores = model_manager.analyze_style(image)
|
| 409 |
+
design_state.style_analysis = style_scores
|
| 410 |
+
logger.info(f"风格分析: {style_scores}")
|
| 411 |
+
except Exception as e:
|
| 412 |
+
logger.error(f"风格分析失败: {e}")
|
| 413 |
+
style_scores = {"时尚潮流": 0.8, "现代风格": 0.6}
|
| 414 |
+
design_state.style_analysis = style_scores
|
| 415 |
+
|
| 416 |
+
# 3. 高级颜色分析
|
| 417 |
+
progress(0.5, desc="深度颜色分析中...")
|
| 418 |
+
color_analysis = advanced_color_analysis(image)
|
| 419 |
+
design_state.color_analysis = color_analysis
|
| 420 |
+
|
| 421 |
+
# 4. 面料质地分析
|
| 422 |
+
progress(0.7, desc="面料质地分析中...")
|
| 423 |
+
fabric_analysis = analyze_fabric_texture(image)
|
| 424 |
+
design_state.fabric_analysis = fabric_analysis
|
| 425 |
+
|
| 426 |
+
# 5. 生成综合分析报告
|
| 427 |
+
progress(0.85, desc="生成分析报告...")
|
| 428 |
+
comprehensive_analysis = {
|
| 429 |
+
"基础信息": {
|
| 430 |
+
"图像描述": caption,
|
| 431 |
+
"图像尺寸": f"{image.width} x {image.height}",
|
| 432 |
+
"分析时��": time.strftime("%Y-%m-%d %H:%M:%S")
|
| 433 |
+
},
|
| 434 |
+
"风格分析": {
|
| 435 |
+
"主要风格": max(style_scores.keys(), key=style_scores.get),
|
| 436 |
+
"风格置信度": f"{max(style_scores.values()):.1%}",
|
| 437 |
+
"所有风格评分": {k: f"{v:.1%}" for k, v in sorted(style_scores.items(), key=lambda x: x[1], reverse=True)}
|
| 438 |
+
},
|
| 439 |
+
"颜色分析": {
|
| 440 |
+
"主色调": color_analysis["dominant_colors"][0] if color_analysis["dominant_colors"] else "经典色调",
|
| 441 |
+
"配色方案": color_analysis["color_harmony"],
|
| 442 |
+
"季节倾向": color_analysis["season_analysis"],
|
| 443 |
+
"颜色情感": color_analysis["color_palette"].get("颜色1", {}).get("emotion", "中性")
|
| 444 |
+
},
|
| 445 |
+
"材质分析": {
|
| 446 |
+
"预测面料": fabric_analysis["predicted_fabric"],
|
| 447 |
+
"质地特征": fabric_analysis["texture"],
|
| 448 |
+
"面料特性": fabric_analysis["fabric_properties"]
|
| 449 |
+
}
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
# 6. 基于综合分析生成设计建议
|
| 453 |
+
design_suggestions = generate_intelligent_suggestions()
|
| 454 |
+
|
| 455 |
+
progress(1.0, desc="分析完成")
|
| 456 |
+
|
| 457 |
+
choices = list(design_suggestions.keys())
|
| 458 |
+
return (
|
| 459 |
+
comprehensive_analysis,
|
| 460 |
+
design_suggestions,
|
| 461 |
+
gr.Radio(choices=choices, value=choices[0] if choices else None),
|
| 462 |
+
gr.Gallery(value=[])
|
| 463 |
+
)
|
| 464 |
+
|
| 465 |
+
except Exception as e:
|
| 466 |
+
logger.error(f"综合分析失败: {e}", exc_info=True)
|
| 467 |
+
return {"错误": f"分析失败: {str(e)}"}, {}, gr.Radio(choices=[]), gr.Gallery(value=[])
|
| 468 |
+
|
| 469 |
+
def generate_intelligent_suggestions():
|
| 470 |
+
"""基于所有分析维度生成智能设计建议"""
|
| 471 |
+
context = design_state.get_design_context()
|
| 472 |
+
|
| 473 |
+
# 获取关键信息
|
| 474 |
+
main_style = context["main_style"]
|
| 475 |
+
dominant_color = context["dominant_colors"][0] if context["dominant_colors"] else "经典色调"
|
| 476 |
+
fabric_type = context["fabric_type"]
|
| 477 |
+
color_emotion = design_state.color_analysis.get("color_palette", {}).get("颜色1", {}).get("emotion", "中性")
|
| 478 |
+
|
| 479 |
+
# 基于综合分析生成建议
|
| 480 |
+
suggestions = {}
|
| 481 |
+
|
| 482 |
+
# 1. 风格延续建议
|
| 483 |
+
suggestions[f"经典{main_style}"] = f"保持{main_style}核心特色,运用{dominant_color}主色调,体现{color_emotion}的情感表达"
|
| 484 |
+
|
| 485 |
+
# 2. 材质创新建议
|
| 486 |
+
suggestions[f"{fabric_type}质感创新"] = f"基于{fabric_type}面料特性,结合{dominant_color}配色,打造现代{main_style}风格"
|
| 487 |
+
|
| 488 |
+
# 3. 配色方案建议
|
| 489 |
+
color_harmony = design_state.color_analysis.get("color_harmony", "和谐配色")
|
| 490 |
+
suggestions[f"{color_harmony}设计"] = f"采用{color_harmony}策略,以{dominant_color}为主调,营造{color_emotion}氛围"
|
| 491 |
+
|
| 492 |
+
# 4. 季节适应建议
|
| 493 |
+
season_analysis = design_state.color_analysis.get("season_analysis", "四季通用")
|
| 494 |
+
suggestions[f"{season_analysis}款式"] = f"针对{season_analysis}特点,融合{main_style}元素,突出{fabric_type}质感"
|
| 495 |
+
|
| 496 |
+
# 5. 情感导向建议
|
| 497 |
+
suggestions[f"{color_emotion}表达"] = f"强化{color_emotion}的情感传达,通过{main_style}剪裁体现{fabric_type}的独特魅力"
|
| 498 |
+
|
| 499 |
+
# 6. 创新融合建议
|
| 500 |
+
suggestions["跨界融合创新"] = f"打破传统{main_style}界限,创新运用{dominant_color},结合现代设计理念"
|
| 501 |
+
|
| 502 |
+
return suggestions
|
| 503 |
+
|
| 504 |
+
def generate_professional_designs(selected_suggestion, progress=gr.Progress()):
|
| 505 |
+
"""生成专业服装设计图 - 三视图风格(改进版)"""
|
| 506 |
+
try:
|
| 507 |
+
if not selected_suggestion or not design_state.original_image:
|
| 508 |
+
return gr.Gallery(value=[]), gr.Radio(choices=[])
|
| 509 |
+
|
| 510 |
+
design_state.design_direction = selected_suggestion
|
| 511 |
+
|
| 512 |
+
progress(0.1, desc="准备设计生成...")
|
| 513 |
+
|
| 514 |
+
# 获取完整设计上下文
|
| 515 |
+
context = design_state.get_design_context()
|
| 516 |
+
|
| 517 |
+
# 生成三种专业设计视图
|
| 518 |
+
design_views = ["正面设计图", "背面设计图", "侧面设计图"]
|
| 519 |
+
generated_designs = []
|
| 520 |
+
design_choices = []
|
| 521 |
+
|
| 522 |
+
for i, view in enumerate(design_views):
|
| 523 |
+
try:
|
| 524 |
+
progress(0.2 + i*0.25, desc=f"生成{view}...")
|
| 525 |
+
|
| 526 |
+
# 创建专业的设计提示词
|
| 527 |
+
# 使用基于 suggestion 的 seed 保证三视图一致
|
| 528 |
+
base_seed = abs(hash(selected_suggestion)) % (2 ** 31 - 1)
|
| 529 |
+
view_seed = (base_seed + i * 9973) % (2 ** 31 - 1)
|
| 530 |
+
|
| 531 |
+
design_prompt = create_professional_design_prompt(view, context, selected_suggestion)
|
| 532 |
+
|
| 533 |
+
# 使用SD模型生成设计
|
| 534 |
+
design_image = model_manager.generate_image(
|
| 535 |
+
prompt=design_prompt,
|
| 536 |
+
negative_prompt="person, face, model, background, blurry, low quality, text, watermark, realistic photo, 3d render",
|
| 537 |
+
num_inference_steps=30,
|
| 538 |
+
width=512,
|
| 539 |
+
height=640,
|
| 540 |
+
guidance_scale=8.0,
|
| 541 |
+
seed=view_seed
|
| 542 |
+
)
|
| 543 |
+
|
| 544 |
+
generated_designs.append(design_image)
|
| 545 |
+
design_choices.append(f"{selected_suggestion} - {view}")
|
| 546 |
+
logger.info(f"成功生成{view}")
|
| 547 |
+
|
| 548 |
+
except Exception as e:
|
| 549 |
+
logger.error(f"生成{view}失败: {e}")
|
| 550 |
+
# 创建占位图像
|
| 551 |
+
placeholder = create_design_placeholder(view, 512, 640)
|
| 552 |
+
generated_designs.append(placeholder)
|
| 553 |
+
design_choices.append(f"{selected_suggestion} - {view} (占位)")
|
| 554 |
+
|
| 555 |
+
design_state.generated_designs = generated_designs
|
| 556 |
+
|
| 557 |
+
progress(1.0, desc="设计生成完成")
|
| 558 |
+
|
| 559 |
+
return (
|
| 560 |
+
gr.Gallery(value=generated_designs, columns=3),
|
| 561 |
+
gr.Radio(choices=design_choices, value=design_choices[0] if design_choices else None)
|
| 562 |
+
)
|
| 563 |
+
|
| 564 |
+
except Exception as e:
|
| 565 |
+
logger.error(f"专业设计生成失败: {e}")
|
| 566 |
+
return gr.Gallery(value=[]), gr.Radio(choices=[])
|
| 567 |
+
|
| 568 |
+
def create_professional_design_prompt(view, context, suggestion):
|
| 569 |
+
"""创建专业的服装设计提示词 - 避免token截断"""
|
| 570 |
+
|
| 571 |
+
# 关键词映射,避免中文token问题
|
| 572 |
+
style_keywords = {
|
| 573 |
+
"商务正装": "business formal suit professional",
|
| 574 |
+
"休闲风": "casual comfortable relaxed",
|
| 575 |
+
"运动风": "sportswear athletic active",
|
| 576 |
+
"时尚潮流": "fashion trendy modern stylish",
|
| 577 |
+
"复古风": "vintage retro classic",
|
| 578 |
+
"街头风": "streetwear urban hip",
|
| 579 |
+
"优雅风": "elegant sophisticated graceful"
|
| 580 |
+
}
|
| 581 |
+
|
| 582 |
+
color_keywords = {
|
| 583 |
+
"深红色": "deep red burgundy",
|
| 584 |
+
"橙红色": "orange red coral",
|
| 585 |
+
"金黄色": "golden yellow amber",
|
| 586 |
+
"草绿色": "grass green olive",
|
| 587 |
+
"翠绿色": "emerald green jade",
|
| 588 |
+
"天蓝色": "sky blue azure",
|
| 589 |
+
"宝蓝色": "royal blue navy",
|
| 590 |
+
"紫色": "purple violet",
|
| 591 |
+
"深黑色": "deep black charcoal",
|
| 592 |
+
"纯白色": "pure white ivory",
|
| 593 |
+
"深灰色": "dark gray slate"
|
| 594 |
+
}
|
| 595 |
+
|
| 596 |
+
fabric_keywords = {
|
| 597 |
+
"丝绸": "silk smooth luxurious",
|
| 598 |
+
"棉质": "cotton comfortable breathable",
|
| 599 |
+
"混纺": "blend modern synthetic",
|
| 600 |
+
"牛仔": "denim sturdy casual",
|
| 601 |
+
"毛呢": "wool warm textured"
|
| 602 |
+
}
|
| 603 |
+
|
| 604 |
+
view_keywords = {
|
| 605 |
+
"正面设计图": "front view technical drawing fashion flat",
|
| 606 |
+
"背面设计图": "back view technical drawing fashion flat",
|
| 607 |
+
"侧面设计图": "side view technical drawing fashion flat"
|
| 608 |
+
}
|
| 609 |
+
|
| 610 |
+
# 构建英文提示词
|
| 611 |
+
style_eng = style_keywords.get(context["main_style"], "modern fashion")
|
| 612 |
+
color_eng = color_keywords.get(context["dominant_colors"][0] if context["dominant_colors"] else "", "neutral colors")
|
| 613 |
+
fabric_eng = fabric_keywords.get(context["fabric_type"], "quality fabric")
|
| 614 |
+
view_eng = view_keywords.get(view, "technical fashion drawing")
|
| 615 |
+
|
| 616 |
+
# 专业服装设计提示词
|
| 617 |
+
prompt = (
|
| 618 |
+
f"{view_eng}, {style_eng} garment design, "
|
| 619 |
+
f"{color_eng} color scheme, {fabric_eng} material, "
|
| 620 |
+
f"clean fashion illustration, professional technical drawing, "
|
| 621 |
+
f"flat lay design, no model, clothing only, "
|
| 622 |
+
f"detailed stitching, precise proportions, "
|
| 623 |
+
f"fashion design sketch, minimalist background, "
|
| 624 |
+
f"high quality illustration, vector style"
|
| 625 |
+
)
|
| 626 |
+
|
| 627 |
+
logger.info(f"{view}设计提示词: {prompt}")
|
| 628 |
+
return prompt
|
| 629 |
+
|
| 630 |
+
def create_design_placeholder(view, width, height):
|
| 631 |
+
"""创建设计占位图"""
|
| 632 |
+
img = Image.new('RGB', (width, height), color=(240, 240, 240))
|
| 633 |
+
draw = ImageDraw.Draw(img)
|
| 634 |
+
|
| 635 |
+
# 绘制基本轮廓
|
| 636 |
+
if "正面" in view:
|
| 637 |
+
# 画一个基本的衣服正面轮廓
|
| 638 |
+
draw.rectangle([width//4, height//6, 3*width//4, 5*height//6], outline=(100, 100, 100), width=3)
|
| 639 |
+
elif "背面" in view:
|
| 640 |
+
# 画一个基本的衣服背面轮廓
|
| 641 |
+
draw.rectangle([width//4, height//6, 3*width//4, 5*height//6], outline=(120, 120, 120), width=3)
|
| 642 |
+
else:
|
| 643 |
+
# 侧面轮廓
|
| 644 |
+
draw.ellipse([width//3, height//6, 2*width//3, 5*height//6], outline=(140, 140, 140), width=3)
|
| 645 |
+
|
| 646 |
+
# 添加文字
|
| 647 |
+
try:
|
| 648 |
+
font = ImageFont.load_default()
|
| 649 |
+
text = view
|
| 650 |
+
draw.text((width//2-50, height//2), text, fill=(80, 80, 80), font=font)
|
| 651 |
+
except:
|
| 652 |
+
pass
|
| 653 |
+
|
| 654 |
+
return img
|
| 655 |
+
|
| 656 |
+
def generate_3d_fitting_effect(selected_design_index, progress=gr.Progress()):
|
| 657 |
+
"""生成专业3D试穿效果 - 标准模特展示"""
|
| 658 |
+
try:
|
| 659 |
+
if not design_state.generated_designs or selected_design_index is None:
|
| 660 |
+
return None
|
| 661 |
+
|
| 662 |
+
design_state.selected_design_index = selected_design_index
|
| 663 |
+
|
| 664 |
+
progress(0.1, desc="准备3D建模...")
|
| 665 |
+
|
| 666 |
+
# 获取设计上下文和选中的设计
|
| 667 |
+
context = design_state.get_design_context()
|
| 668 |
+
selected_design = design_state.generated_designs[selected_design_index]
|
| 669 |
+
|
| 670 |
+
progress(0.3, desc="构建3D试穿场景...")
|
| 671 |
+
|
| 672 |
+
# 创建专业3D试穿提示词
|
| 673 |
+
fitting_prompt = create_3d_fitting_prompt(context, selected_design_index)
|
| 674 |
+
|
| 675 |
+
progress(0.5, desc="AI 3D渲染中...")
|
| 676 |
+
|
| 677 |
+
try:
|
| 678 |
+
# 使用ControlNet生成高质量3D试穿效果
|
| 679 |
+
fitting_image = model_manager.generate_controlnet_image(
|
| 680 |
+
image=design_state.original_image,
|
| 681 |
+
prompt=fitting_prompt,
|
| 682 |
+
reference_image=selected_design,
|
| 683 |
+
negative_prompt="blurry, distorted, low quality, unrealistic, extra limbs, deformed, bad anatomy, text, watermark, multiple people",
|
| 684 |
+
num_inference_steps=40,
|
| 685 |
+
guidance_scale=8.5
|
| 686 |
+
)
|
| 687 |
+
|
| 688 |
+
progress(0.9, desc="完成3D渲染")
|
| 689 |
+
design_state.fitting_result = fitting_image
|
| 690 |
+
logger.info("使用ControlNet生成3D试穿效果")
|
| 691 |
+
return fitting_image
|
| 692 |
+
|
| 693 |
+
except Exception as e:
|
| 694 |
+
logger.warning(f"ControlNet 3D试穿失败: {e}")
|
| 695 |
+
# 回退到标准模型
|
| 696 |
+
progress(0.6, desc="使用标准模型生成...")
|
| 697 |
+
fitting_image = model_manager.generate_image(
|
| 698 |
+
prompt=fitting_prompt,
|
| 699 |
+
negative_prompt="blurry, distorted, low quality, unrealistic, extra limbs, deformed, bad anatomy, multiple people",
|
| 700 |
+
num_inference_steps=35,
|
| 701 |
+
width=512,
|
| 702 |
+
height=768,
|
| 703 |
+
guidance_scale=8.0
|
| 704 |
+
)
|
| 705 |
+
|
| 706 |
+
progress(0.9, desc="完成渲染")
|
| 707 |
+
design_state.fitting_result = fitting_image
|
| 708 |
+
return fitting_image
|
| 709 |
+
|
| 710 |
+
except Exception as e:
|
| 711 |
+
logger.error(f"3D试穿生成失败: {e}")
|
| 712 |
+
return create_fitting_placeholder()
|
| 713 |
+
|
| 714 |
+
def create_3d_fitting_prompt(context, design_index):
|
| 715 |
+
"""创建3D试穿提示词 - 英文避免token截断"""
|
| 716 |
+
|
| 717 |
+
# 风格关键词映射
|
| 718 |
+
style_keywords = {
|
| 719 |
+
"商务正装": "professional business attire formal suit",
|
| 720 |
+
"休闲风": "casual comfortable everyday wear",
|
| 721 |
+
"运动风": "athletic sportswear activewear",
|
| 722 |
+
"时尚潮流": "fashion forward trendy modern",
|
| 723 |
+
"复古风": "vintage retro classic style",
|
| 724 |
+
"街头风": "streetwear urban contemporary",
|
| 725 |
+
"优雅风": "elegant sophisticated refined"
|
| 726 |
+
}
|
| 727 |
+
|
| 728 |
+
color_keywords = {
|
| 729 |
+
"深红色": "deep red burgundy rich",
|
| 730 |
+
"橙红色": "coral orange warm",
|
| 731 |
+
"金黄色": "golden amber bright",
|
| 732 |
+
"草绿色": "olive green natural",
|
| 733 |
+
"翠绿色": "emerald jade vibrant",
|
| 734 |
+
"天蓝色": "sky blue light",
|
| 735 |
+
"宝蓝色": "royal navy deep",
|
| 736 |
+
"紫色": "purple violet",
|
| 737 |
+
"深黑色": "black charcoal dark",
|
| 738 |
+
"纯白色": "white clean pure",
|
| 739 |
+
"深灰色": "charcoal slate gray"
|
| 740 |
+
}
|
| 741 |
+
|
| 742 |
+
fabric_keywords = {
|
| 743 |
+
"丝绸": "silk luxurious smooth draping",
|
| 744 |
+
"棉质": "cotton comfortable natural texture",
|
| 745 |
+
"混纺": "modern blend synthetic comfort",
|
| 746 |
+
"牛仔": "denim sturdy casual texture",
|
| 747 |
+
"毛呢": "wool textured warm sophisticated"
|
| 748 |
+
}
|
| 749 |
+
|
| 750 |
+
# 获取英文关键词
|
| 751 |
+
style_eng = style_keywords.get(context["main_style"], "modern fashion")
|
| 752 |
+
color_eng = color_keywords.get(context["dominant_colors"][0] if context["dominant_colors"] else "", "neutral tones")
|
| 753 |
+
fabric_eng = fabric_keywords.get(context["fabric_type"], "quality fabric")
|
| 754 |
+
|
| 755 |
+
# 构建3D试穿提示词
|
| 756 |
+
prompt = (
|
| 757 |
+
f"professional 3D fashion model wearing {style_eng}, "
|
| 758 |
+
f"{color_eng} color scheme, {fabric_eng} material, "
|
| 759 |
+
f"full body pose, studio lighting, clean background, "
|
| 760 |
+
f"high quality 3D render, realistic fabric texture, "
|
| 761 |
+
f"perfect fit tailoring, fashion photography style, "
|
| 762 |
+
f"detailed clothing construction, professional modeling"
|
| 763 |
+
)
|
| 764 |
+
|
| 765 |
+
logger.info(f"3D试穿提示词: {prompt}")
|
| 766 |
+
return prompt
|
| 767 |
+
|
| 768 |
+
def create_fitting_placeholder():
|
| 769 |
+
"""创建3D试穿占位图"""
|
| 770 |
+
img = Image.new('RGB', (512, 768), color=(245, 245, 245))
|
| 771 |
+
draw = ImageDraw.Draw(img)
|
| 772 |
+
|
| 773 |
+
# 画一个基本的人体轮廓
|
| 774 |
+
# 头部
|
| 775 |
+
draw.ellipse([206, 50, 306, 150], outline=(150, 150, 150), width=2)
|
| 776 |
+
# 身体
|
| 777 |
+
draw.rectangle([226, 150, 286, 400], outline=(150, 150, 150), width=2)
|
| 778 |
+
# 手臂
|
| 779 |
+
draw.rectangle([186, 170, 226, 350], outline=(150, 150, 150), width=2)
|
| 780 |
+
draw.rectangle([286, 170, 326, 350], outline=(150, 150, 150), width=2)
|
| 781 |
+
# 腿部
|
| 782 |
+
draw.rectangle([236, 400, 266, 650], outline=(150, 150, 150), width=2)
|
| 783 |
+
draw.rectangle([266, 400, 296, 650], outline=(150, 150, 150), width=2)
|
| 784 |
+
|
| 785 |
+
# 添加文字
|
| 786 |
+
try:
|
| 787 |
+
font = ImageFont.load_default()
|
| 788 |
+
draw.text((200, 380), "3D Fitting", fill=(100, 100, 100), font=font)
|
| 789 |
+
except:
|
| 790 |
+
pass
|
| 791 |
+
|
| 792 |
+
return img
|
| 793 |
+
|
| 794 |
+
def export_design_report():
|
| 795 |
+
"""导出完整的设计报告"""
|
| 796 |
+
if not design_state.original_image:
|
| 797 |
+
return "没有设计数据可导出"
|
| 798 |
+
|
| 799 |
+
try:
|
| 800 |
+
context = design_state.get_design_context()
|
| 801 |
+
|
| 802 |
+
report = {
|
| 803 |
+
"设计项目报告": {
|
| 804 |
+
"生成时间": time.strftime("%Y-%m-%d %H:%M:%S"),
|
| 805 |
+
"项目概述": {
|
| 806 |
+
"设计描述": context["caption"],
|
| 807 |
+
"设计方向": context["design_direction"],
|
| 808 |
+
"主要风格": context["main_style"]
|
| 809 |
+
},
|
| 810 |
+
"色彩分析": {
|
| 811 |
+
"主色调": context["dominant_colors"],
|
| 812 |
+
"配色方案": design_state.color_analysis.get("color_harmony", ""),
|
| 813 |
+
"季节特征": design_state.color_analysis.get("season_analysis", ""),
|
| 814 |
+
"情感表达": design_state.color_analysis.get("color_palette", {}).get("颜色1", {}).get("emotion", "")
|
| 815 |
+
},
|
| 816 |
+
"材质分析": {
|
| 817 |
+
"面料类型": context["fabric_type"],
|
| 818 |
+
"质地特征": design_state.fabric_analysis.get("texture", ""),
|
| 819 |
+
"材质特性": design_state.fabric_analysis.get("fabric_properties", "")
|
| 820 |
+
},
|
| 821 |
+
"设计建议": {
|
| 822 |
+
"选择方向": design_state.design_direction,
|
| 823 |
+
"设计理念": f"基于{context['main_style']}风格,运用{context['dominant_colors'][0] if context['dominant_colors'] else '经典'}色调"
|
| 824 |
+
}
|
| 825 |
+
}
|
| 826 |
+
}
|
| 827 |
+
|
| 828 |
+
return json.dumps(report, ensure_ascii=False, indent=2)
|
| 829 |
+
|
| 830 |
+
except Exception as e:
|
| 831 |
+
return f"报告生成失败: {str(e)}"
|
| 832 |
+
|
| 833 |
+
def create_gradio_interface():
|
| 834 |
+
"""创建改进的Gradio界面"""
|
| 835 |
+
|
| 836 |
+
with gr.Blocks(title="AI时尚设计师 Pro", theme="soft") as demo:
|
| 837 |
+
gr.Markdown("# 🎨 AI时尚设计师 Pro")
|
| 838 |
+
gr.Markdown("**专业AI驱动的服装设计平台** - 深度分析、智能设计、3D试穿")
|
| 839 |
+
|
| 840 |
+
with gr.Row():
|
| 841 |
+
with gr.Column(scale=1):
|
| 842 |
+
image_input = gr.Image(type="filepath", label="📸 上传服装参考图", height=400)
|
| 843 |
+
analyze_btn = gr.Button("🔍 AI深度分析", variant="primary", size="lg")
|
| 844 |
+
|
| 845 |
+
# 分析结果展示
|
| 846 |
+
with gr.Accordion("📊 详细分析报告", open=False):
|
| 847 |
+
analysis_output = gr.JSON(label="综合分析结果")
|
| 848 |
+
|
| 849 |
+
with gr.Column(scale=2):
|
| 850 |
+
# 设计建议标签页
|
| 851 |
+
with gr.Tab("💡 智能设计建议"):
|
| 852 |
+
suggestions_output = gr.JSON(label="🎯 基于AI分析的个性化建议")
|
| 853 |
+
suggestion_choice = gr.Radio(label="🎨 选择设计方向", interactive=True)
|
| 854 |
+
generate_designs_btn = gr.Button("✨ 生成专业设计图", variant="primary", size="lg")
|
| 855 |
+
|
| 856 |
+
# 设计图标签页
|
| 857 |
+
with gr.Tab("👔 专业设计图"):
|
| 858 |
+
gr.Markdown("**服装设计三视图** - 正面/背面/侧面专业技术图")
|
| 859 |
+
designs_gallery = gr.Gallery(label="AI生成的专业设计图", columns=3, height=500)
|
| 860 |
+
design_choice = gr.Radio(label="🎯 选择设计方案", type="index", interactive=True)
|
| 861 |
+
generate_3d_btn = gr.Button("🎭 生成3D试穿效果", variant="primary", size="lg")
|
| 862 |
+
|
| 863 |
+
# 3D试穿标签页
|
| 864 |
+
with gr.Tab("🎭 3D虚拟试穿"):
|
| 865 |
+
gr.Markdown("**专业3D试穿展示** - 标准模特效果图")
|
| 866 |
+
fitting_result = gr.Image(label="3D虚拟试穿效果", height=600)
|
| 867 |
+
|
| 868 |
+
with gr.Row():
|
| 869 |
+
export_btn = gr.Button("📄 导出设计报告", variant="secondary")
|
| 870 |
+
reset_btn = gr.Button("🔄 重置项目", variant="secondary")
|
| 871 |
+
|
| 872 |
+
# 导出结果
|
| 873 |
+
with gr.Tab("📋 设计报告"):
|
| 874 |
+
report_output = gr.Textbox(label="完整设计报告", lines=20, max_lines=30)
|
| 875 |
+
|
| 876 |
+
# 系统控制面板
|
| 877 |
+
with gr.Accordion("🔧 系统控制面板", open=False):
|
| 878 |
+
with gr.Row():
|
| 879 |
+
cleanup_btn = gr.Button("🧹 清理显存", variant="secondary")
|
| 880 |
+
cpu_btn = gr.Button("💾 模型→CPU", variant="secondary")
|
| 881 |
+
gpu_btn = gr.Button("🚀 模型→GPU", variant="secondary")
|
| 882 |
+
reload_btn = gr.Button("🔄 重载模型", variant="primary")
|
| 883 |
+
|
| 884 |
+
gr.Markdown("""
|
| 885 |
+
**系统优化说明**:
|
| 886 |
+
- 🧹 清理显存:清理GPU缓存,不影响模型
|
| 887 |
+
- 💾 模型→CPU:释放GPU显存,推理���度会降低
|
| 888 |
+
- 🚀 模型→GPU:恢复GPU加速,提升生成速度
|
| 889 |
+
- 🔄 重载模型:强制重新加载所有AI模型
|
| 890 |
+
""")
|
| 891 |
+
|
| 892 |
+
# 事件绑定 - 完整工作流程
|
| 893 |
+
analyze_btn.click(
|
| 894 |
+
fn=comprehensive_image_analysis,
|
| 895 |
+
inputs=[image_input],
|
| 896 |
+
outputs=[analysis_output, suggestions_output, suggestion_choice, designs_gallery]
|
| 897 |
+
)
|
| 898 |
+
|
| 899 |
+
generate_designs_btn.click(
|
| 900 |
+
fn=generate_professional_designs,
|
| 901 |
+
inputs=[suggestion_choice],
|
| 902 |
+
outputs=[designs_gallery, design_choice]
|
| 903 |
+
)
|
| 904 |
+
|
| 905 |
+
generate_3d_btn.click(
|
| 906 |
+
fn=generate_3d_fitting_effect,
|
| 907 |
+
inputs=[design_choice],
|
| 908 |
+
outputs=[fitting_result]
|
| 909 |
+
)
|
| 910 |
+
|
| 911 |
+
export_btn.click(
|
| 912 |
+
fn=export_design_report,
|
| 913 |
+
inputs=[],
|
| 914 |
+
outputs=[report_output]
|
| 915 |
+
)
|
| 916 |
+
|
| 917 |
+
reset_btn.click(
|
| 918 |
+
fn=lambda: (design_state.reset(), {}, {}, gr.Radio(choices=[]), gr.Gallery(value=[]), None, ""),
|
| 919 |
+
inputs=[],
|
| 920 |
+
outputs=[analysis_output, suggestions_output, suggestion_choice, designs_gallery, fitting_result, report_output]
|
| 921 |
+
)
|
| 922 |
+
|
| 923 |
+
# 系统控制
|
| 924 |
+
cleanup_btn.click(fn=model_manager.cleanup, inputs=[], outputs=[])
|
| 925 |
+
cpu_btn.click(fn=model_manager.move_models_to_cpu, inputs=[], outputs=[])
|
| 926 |
+
gpu_btn.click(fn=model_manager.move_models_to_gpu, inputs=[], outputs=[])
|
| 927 |
+
reload_btn.click(fn=model_manager.force_reload_all_models, inputs=[], outputs=[])
|
| 928 |
+
|
| 929 |
+
# 使用指南
|
| 930 |
+
with gr.Accordion("📖 专业使用指南", open=False):
|
| 931 |
+
gr.Markdown("""
|
| 932 |
+
## 🚀 完整工作流程
|
| 933 |
+
|
| 934 |
+
### 第一步:AI深度分析
|
| 935 |
+
1. 上传高清服装参考图片
|
| 936 |
+
2. 点击"AI深度分析"进行多维度智能分析
|
| 937 |
+
3. 查看详细的风格、颜色、材质分析报告
|
| 938 |
+
|
| 939 |
+
### 第二步:选择设计方向
|
| 940 |
+
1. 在"智能设计建议"中查看个性化建议
|
| 941 |
+
2. 基于AI分析结果选择最符合需求的设计方向
|
| 942 |
+
3. 建议会整合风格、色彩、材质等所有分析维度
|
| 943 |
+
|
| 944 |
+
### 第三步:生成专业设计
|
| 945 |
+
1. 点击"生成专业设计图"获取三视图
|
| 946 |
+
2. 包含正面、背面、侧面的专业技术图
|
| 947 |
+
3. 所有设计都基于前期分析结果,确保一致性
|
| 948 |
+
|
| 949 |
+
### 第四步:3D虚拟试穿
|
| 950 |
+
1. 选择心仪的设计方案
|
| 951 |
+
2. 生成标准模特的3D试穿效果
|
| 952 |
+
3. 展示真实的着装效果和服装细节
|
| 953 |
+
|
| 954 |
+
### 第五步:导出设计报告
|
| 955 |
+
1. 获取完整的项目设计报告
|
| 956 |
+
2. 包含所有分析数据和设计决策依据
|
| 957 |
+
3. 支持进一步的设计开发和制作
|
| 958 |
+
|
| 959 |
+
## 💡 专业建议
|
| 960 |
+
- **图片质量**:使用高分辨率、光线良好的服装图片
|
| 961 |
+
- **分析准确性**:让AI完整分析后再进行设计选择
|
| 962 |
+
- **设计连贯性**:所有生成内容都基于初始分析,确保风格统一
|
| 963 |
+
- **3D效果**:基于ControlNet技术,提供专业级试穿展示
|
| 964 |
+
""")
|
| 965 |
+
|
| 966 |
+
return demo
|
| 967 |
+
|
| 968 |
+
if __name__ == "__main__":
|
| 969 |
+
logger.info(f"Python版本: {sys.version}")
|
| 970 |
+
logger.info(f"当前工作目录: {os.getcwd()}")
|
| 971 |
+
logger.info(f"模型管理器状态: {'完整版' if MODELS_AVAILABLE else '简化版'}")
|
| 972 |
+
|
| 973 |
+
demo = create_gradio_interface()
|
| 974 |
+
demo.launch(
|
| 975 |
+
server_name="0.0.0.0",
|
| 976 |
+
server_port=7860,
|
| 977 |
+
share=False,
|
| 978 |
+
show_error=True,
|
| 979 |
+
max_threads=4 # 增加线程数支持并发
|
| 980 |
+
)
|