首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >服装图人像抹除:解决虚拟试衣中模特冲突的实用方案

服装图人像抹除:解决虚拟试衣中模特冲突的实用方案

原创
作者头像
高老师
发布2026-06-03 12:16:13
发布2026-06-03 12:16:13
920
举报

服装图人像抹除:解决虚拟试衣中模特冲突的实用方案

背景

我们团队在做一个虚拟试衣产品,用户上传一张模特图和一张服装图,AI 生成模特穿上该服装的效果图。看起来很美好,但上线后遇到一个高频问题:

很多用户上传的"服装图"里面本身就包含模特。

这会导致什么问题?生图模型虽然提示词里写了"必须使用第一张图片的模特",但 AI 仍然会偶尔产生幻觉——把服装图里的模特当成目标模特,生成出完全错误的人脸。

用户反馈:为什么试衣结果的脸不是我?为什么换了个模特?

一开始我们的应对方式是让用户重试几次,但体验很差。根本原因是服装图里的人像信息在干扰生图模型。

思路

既然问题出在服装图里的人像干扰,那最直接的方案就是:检测服装图是否包含人,如果包含就把脸部、脖子、头发等区域抹除掉,只保留服装本身的信息再传给试衣模型。

抹除后,生图模型只能从模特图获取人脸信息,幻觉问题基本消除。

技术方案选型

我调研了几种主流方案:

方案

CPU 速度

精度

模型大小

说明

SegFormer B0 人体解析

~2-3s/张

~50MB

像素级语义分割,直接有 Face/Neck/Hair 标签

YOLO + MediaPipe

~50ms

~30MB

脖子边界靠关键点估算,不精准

SAM2

~10-30s

极高

~2GB

太慢太重,CPU 不现实

RemBG + 人体解析

~5-6s

~220MB

两模型串联,延迟翻倍

最终选择 SegFormer B0 + ATR 数据集,理由:

  1. 一个模型同时完成检测和分割,不需要串联多模型
  2. ATR 数据集的标签体系天然包含 Face(11)、Neck(17)、Hair(2)、Hat(1),直接可用
  3. B0 是最小变体,CPU 上 2-3 秒可接受
  4. HuggingFace 上有现成预训练模型,开箱即用

抹除方式对比:

方式

效果

速度

推荐度

cv2 inpainting (Telea)

边界自然,修复效果好

~10ms

⭐⭐⭐ 推荐

马赛克

像素化打码

~5ms

⭐⭐ 看场景

纯色填充

有明显色块

~1ms

⭐ 不推荐

实现过程

1. 人体解析模型

使用 mattmdjaga/segformer_b0_clothes 模型,通过 HuggingFace transformers 加载:

代码语言:python
复制
from transformers import SegformerForSemanticSegmentation, SegformerImageProcessor

model = SegformerForSemanticSegmentation.from_pretrained("mattmdjaga/segformer_b0_clothes")
processor = SegformerImageProcessor.from_pretrained("mattmdjaga/segformer_b0_clothes")

模型输出 18 个类别的像素级分割图,其中我们需要抹除的类别:

代码语言:python
复制
ERASE_LABELS = {"Hat", "Hair", "Sunglasses", "Face", "Neck"}

2. Mask 生成与膨胀

拿到分割图后,将需要抹除的类别合并为二值 mask,再做形态学膨胀确保边缘完整覆盖:

代码语言:python
复制
mask = np.isin(seg_map, list(ERASE_IDS)).astype(np.uint8) * 255
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (31, 31))
mask = cv2.dilate(mask, kernel, iterations=1)

膨胀很重要——分割边界通常会比实际区域小几个像素,不膨胀的话抹除边缘会残留头发丝或脸部轮廓。

3. 抹除

三种方式实现都很简单:

代码语言:python
复制
# Inpaint 修复(推荐)
result = cv2.inpaint(image, mask, inpaint_radius=10, cv2.INPAINT_TELEA)

# 马赛克
# 逐块计算 mask 区域内平均颜色,用平均色填充

# 纯色填充
result[mask == 255] = (128, 128, 128)

4. API 服务封装

用 FastAPI 封装成服务,接口设计为 base64 进 base64 出,方便虚拟试衣系统直接调用:

代码语言:txt
复制
POST /api/erase
输入: image(base64) + method + 可选参数
输出: JSON { has_person, detected_parts, image(base64), format, elapsed_seconds }

关键设计决策:

  • 未检测到人像时原样返回:不做任何重编码,直接回传原始 base64,零体积变化
  • 默认输出 JPG 格式:PNG 对照片类图片体积会膨胀 3-4 倍
  • 支持 data:image/jpeg;base64, 前缀:前端传来的 base64 常带这个前缀,自动处理

5. 前端演示页面

顺手做了一个单页应用,支持拖拽上传、三种抹除方式切换、参数调整、原图与结果左右对比、下载结果。方便给同事演示效果。

最终效果

  • 服装图包含模特 → 自动检测并抹除脸部/脖子/头发 → 试衣模型不再受干扰
  • 服装图不含模特 → 原样返回,零开销
  • CPU 环境下 2-3 秒/张,作为 API 服务完全够用
  • 抹除后试衣结果的模特一致性显著提升

项目结构

代码语言:txt
复制
vtt-mask/
├── app/
│   ├── main.py          # FastAPI 服务,路由定义
│   ├── parser.py        # SegFormer B0 人体解析模型
│   ├── eraser.py        # 抹除逻辑 (inpaint / mosaic / fill)
│   └── static/
│       └── index.html   # 前端演示页面
├── requirements.txt
├── API_DOC.md           # API 接口文档
└── README.md

调用方式

代码语言:python
复制
import requests, base64

with open("clothing.jpg", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()

resp = requests.post("http://localhost:8787/api/erase", data={
    "image": b64,
    "method": "inpaint",
    "output_format": "jpg",
})
result = resp.json()

if result["has_person"]:
    print("检测到人像,已抹除:", result["detected_parts"])
else:
    print("纯服装图,无需抹除")

# result["image"] 为抹除后图片 base64

遇到的坑

  1. NumPy 版本兼容:onnxruntime 编译时绑定了 NumPy 1.x,如果环境装了 NumPy 2.x 会直接 crash。解决:pip install "numpy<2"
  2. ONNX 导出失败:SegFormer 模型有动态 shape,torch.onnx.export 导出时报错。最终放弃 ONNX 加速,直接用 PyTorch CPU 推理,2-3 秒也能接受
  3. PNG 体积膨胀:第一版默认输出 PNG,结果图片体积比原图大 3-4 倍。原因是 PNG 无损压缩对照片效果差。改为默认输出 JPG 后体积与原图同量级
  4. 未检测到人像时的重编码问题:早期版本即使不抹除也会 decode → encode 一遍,导致 JPEG→PNG 格式变化和体积膨胀。改为直接回传原始字节流后解决

总结

这个方案的核心思路很简单:与其让 AI 不犯错,不如从输入端消除犯错的可能。把服装图中的人像信息抹除掉,试衣模型就只剩一个选择——用模特图的人脸。

SegFormer B0 模型轻量精准,CPU 即可运行,部署成本低。整个方案从调研到上线一天搞定,效果立竿见影。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 服装图人像抹除:解决虚拟试衣中模特冲突的实用方案
    • 背景
    • 思路
    • 技术方案选型
    • 实现过程
      • 1. 人体解析模型
      • 2. Mask 生成与膨胀
      • 3. 抹除
      • 4. API 服务封装
      • 5. 前端演示页面
    • 最终效果
    • 项目结构
    • 调用方式
    • 遇到的坑
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档