穿搭选择困难症,我个人感觉人人应该都有一些。
如果你的衣服越来越多、不好管理、每天都不知道穿什么,可以看看本期这个项目,能否解决你的困扰。

在部署使用过程中碰到问题,请看文末注意事项,应该能解决大部分问题。
项目介绍
完整项目名:leoz9/AIWardrobe,可于GitHub搜索。
AIWardrobe 是一个开源的 AI 智能衣柜项目,主要功能包括衣物录入、衣物图片上传、AI 识别衣物属性、衣柜管理,以及根据天气和用户目标生成穿搭推荐。
项目特征
-
智能上传:上传衣服照片后,使用 rembg 自动去背景,并通过视觉模型识别类别、颜色和风格
-
天气穿搭:集成 Open-Meteo 免费全球天气接口,根据实时天气生成更合适的穿搭建议
-
虚拟衣柜:以结构化方式浏览、搜索和管理所有衣物
-
AI 推荐:支持 Gemini 和 OpenAI 风格接口,用于生成个性化穿搭方案
-
响应式界面:基于 Tailwind CSS,适配桌面、平板和手机
部署流程
以威联通NAS为例,通过Docker Compose的方式进行部署。
部署代码如下:
services:
aiwardrobe:
image: ghcr.io/leoz9/aiwardrobe:latest
container_name: ai_wardrobe
restart: unless-stopped
ports:
- "8000:8000" # 建议先别改
environment:
DB_FILE_PATH: /app/backend/data/wardrobe.db
# Gemini 可选。如果不用 Gemini,可以先留空。
GEMINI_API_KEY: ""
# 和风天气 API。没有的话可以先留空,但天气相关功能可能不可用。
QWEATHER_API_KEY: ""
QWEATHER_API_HOST: devapi.qweather.com
volumes:
- /share/Container/aiwardrobe/backend/uploads:/app/backend/uploads # 衣物图片目录
- /share/Container/aiwardrobe/backend/data:/app/backend/data # 数据库目录
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
打开威联通的Container Station,创建新的应用程序。

使用一览
部署完毕,浏览器输入NAS_IP:8000即可访问服务。显而易见,作者多次更新后,项目更适合通过移动端来使用。

点击右上角的设置。配置AI相关,模型名称一定要选择支持图片输入的模型。这里再次强调,普通文本模型不行,只支持文本的 OAI-compatible 接口也不行。AIWardrobe 识别衣物图片时需要发送图片内容。

下方的抠图,默认配置是第二个,但是并没有可用额度。直接选择本地离线,这个地方其实也跟上面的AI配置挂钩。

配置完毕后,便可选择服饰上传。支持多个一次性导入,如果你想细化每一件的标签,那我建议还是一张张上传!

找了部分网图。

上传后会自动抠图命名和打标签分类,效果还是挺好的。


可以查看随机穿搭。

首页这边会显示一些大概信息。

关于AI推荐推荐穿搭,输入你的目标场景,AI便会根据天气、衣服、场景、运势,分析推荐给你合适的搭配

说的头头是道,哈哈~推荐分析结果如下。


注意问题
这其实也是我自己碰到的问题,图片问题上文已顺带说明,这里再补充俩。
端口相关
端口建议直接使用 8000:8000,不要随便改成8008:8000之类。
如果实在要改,可以git clone项目文件到本地,修改这个文件:frontend/src/utils/api.js。
把:
export const API_ORIGIN = `http://${window.location.hostname}:8000`
改成:
export const API_ORIGIN = window.location.origin
改完保存后,自己构建镜像和部署。
无法生成穿搭推荐
页面可以正常打开,天气和衣柜数据也能加载,但点击「生成今日穿搭推荐」后没有结果。
查看日志后发现,后端推荐接口返回了 500 错误,核心报错是:NameError: name 'build_color_tokens' is not defined。这应该是只有调用,没有函数定义,就可以临时打一个补丁。
SSH 执行下面指令,重启容器即可:
docker exec -i ai_wardrobe python - <<'PY'
from pathlib import Path
path = Path("/app/backend/services/recommendation.py")
text = path.read_text(encoding="utf-8")
backup = Path("/app/backend/services/recommendation.py.bak")
if not backup.exists():
backup.write_text(text, encoding="utf-8")
patch = r'''
COLOR_ALIASES = {
"黑": {"黑", "黑色", "black", "dark"},
"白": {"白", "白色", "white", "ivory", "米白"},
"灰": {"灰", "灰色", "gray", "grey"},
"蓝": {"蓝", "蓝色", "blue", "navy", "藏青", "牛仔"},
"红": {"红", "红色", "red", "wine", "酒红"},
"粉": {"粉", "粉色", "pink"},
"紫": {"紫", "紫色", "purple", "violet"},
"绿": {"绿", "绿色", "green", "olive", "军绿"},
"黄": {"黄", "黄色", "yellow"},
"橙": {"橙", "橙色", "orange"},
"棕": {"棕", "棕色", "brown", "咖啡", "卡其", "khaki"},
"米": {"米", "米色", "beige", "cream"},
"金": {"金", "金色", "gold"},
"银": {"银", "银色", "silver"},
}
ACCESSORY_KEYWORDS = {
"帽", "帽子", "围巾", "手套", "腰带", "皮带", "包", "背包", "项链",
"手链", "耳环", "耳饰", "戒指", "手表", "眼镜", "墨镜", "accessory",
"hat", "scarf", "belt", "bag", "watch", "necklace", "bracelet",
"ring", "glasses", "sunglasses"
}
def build_color_tokens(lucky_color: str) -> set[str]:
raw = (lucky_color or "").strip().lower()
if not raw:
return set()
tokens = {raw}
for canonical, aliases in COLOR_ALIASES.items():
alias_set = {str(alias).strip().lower() for alias in aliases}
if raw in alias_set or canonical in raw or any(alias in raw for alias in alias_set):
tokens.update(alias_set)
tokens.add(canonical)
return {token for token in tokens if token}
'''
if "def build_color_tokens" not in text:
marker = "def score_item("
if marker not in text:
raise SystemExit("没有找到 def score_item,未修改文件")
text = text.replace(marker, patch + "\n" + marker, 1)
if "ACCESSORY_KEYWORDS" not in text:
marker = "def extract_wardrobe_accessories("
if marker in text:
text = text.replace(marker, "ACCESSORY_KEYWORDS = set()\n\n" + marker, 1)
path.write_text(text, encoding="utf-8")
print("patched")
PY
最后
AI 越来越强,希望能在社区看到越来越多的的AI开发的实用项目!
感谢观看,本文完。
评论区