PAYATHON 2026

Android 学生项目有哪些可用的免费 virtual try-on API?

技术老齐

学生项目可以免费完成演示,但会受到配额和排队限制

建议先通过 gradio_client 调用 Hugging Face 上的虚拟试衣 Space,再用 FastAPI 为 Android 应用提供自己的 REST 接口。

这样不用训练模型,手机也不需要运行模型。公共 Space 的可用性取决于维护者和平台资源,无法保证每次都立即返回结果。Hugging Face 的 ZeroGPU Space 可以免费使用,但有配额和队列限制。ZeroGPU 官方说明

如果学校能提供 GPU,自己部署预训练模型更方便控制演示环境。模型代码和权重可以免费获取,计算资源仍需自行解决。

有哪些实际可用的选择?

方案免费的前提适合的情况主要限制
调用现有 ZeroGPU SpaceSpace 开放访问,且剩余配额足够先做出能运行的项目演示排队、配额耗尽、上游接口变化
在自己的 ZeroGPU Space 部署账号满足托管条件,应用兼容 ZeroGPU希望控制代码和参数仍受共享 GPU 和配额限制
学校或个人 GPU 部署预训练模型已有可使用的 GPU答辩时需要控制运行环境需要配置依赖、下载权重和维护服务

使用现有 ZeroGPU Space 和自己托管 Space 的条件不同。能否免费托管,要看账号设置和官方要求。复制 Space 时也要检查硬件选项,普通 GPU 实例可能产生费用。Gradio 客户端说明

Hugging Face 上有模型仓库,也不代表该模型有免费的托管推理 API。Spaces、Inference Providers 和 Inference Endpoints 是不同的服务。当前 Inference Providers 定价页列出的免费账号月度赠送额度为 None,做项目预算时不能直接沿用过去介绍的免费额度。Inference Providers 定价

Hugging Face Space 能转成 API 吗?

如果 Space 使用 Gradio,并且开放了可调用的端点,通常就能通过 API 使用。打开应用底部的 Use via API 或 View API,可以查看平台生成的调用示例。通过 API 接入后,公共演示服务的排队和资源限制依然存在。

也可以安装 Python 客户端:

pip install gradio_client

以 IDM-VTON Space 为例,先检查接口:

import os
from gradio_client import Client

client = Client(
    "yisol/IDM-VTON",
    token=os.getenv("HF_TOKEN"),
)
client.view_api()

view_api() 会显示端点名称、输入参数和输出类型;文件输入通常通过 handle_file() 上传。Gradio Python 客户端指南

接入时需要注意:

  • 按目标 Space 的 API 文档填写参数。人物图可能是 ImageEditor 对象,需要 background、layers 等字段,不能只传一个图片路径。
  • 优先使用 /tryon 这样的命名端点。fn_index 容易随界面修改而变化,尽量避免依赖它。
  • 不要假定所有 Space 都有统一的 /predict HTTP 接口。上传、排队和获取结果可能涉及多个请求,交给客户端处理更省事。
  • 如果 Space 没有开放端点,或不允许这种使用方式,就需要换一个 Space,或者在许可证允许的范围内部署自己的副本。

如何通过 FastAPI 接入 Android?

建议让 Android 只访问自己的后端:

Android (Java)
    → FastAPI:接收人物图和服装图
    → Gradio Space 或自己部署的模型
    → FastAPI:返回生成图片
    → Android:显示结果

这样可以把 Hugging Face token 留在服务器上,以后更换模型也方便。

下面的同步演示接口按 IDM-VTON Space 源码中的 /tryon 端点传入参数,启用自动生成 mask,并取第一个输出作为试衣结果。这里的自动 mask 针对上衣区域,适合先验证上衣试穿流程。IDM-VTON Space 源码

公共 Space 更新后,参数可能变化,运行前应重新执行 view_api() 核对。这段代码仅用于演示接入方式,公共服务能否随时使用尚未经过验证。

安装依赖:

pip install fastapi uvicorn python-multipart gradio_client pillow

app.py:

import os
from io import BytesIO
from pathlib import Path
from tempfile import TemporaryDirectory

from fastapi import FastAPI, File, Form, HTTPException
from fastapi.responses import Response
from gradio_client import Client, handle_file
from PIL import Image, ImageOps, UnidentifiedImageError

app = FastAPI()
MAX_BYTES = 5 * 1024 * 1024  # 示例自行设置的单图限制


def save_image(data: bytes, target: Path):
    if not data or len(data) > MAX_BYTES:
        raise HTTPException(400, "图片不能为空,且不得超过 5 MiB")

    try:
        with Image.open(BytesIO(data)) as image:
            image = ImageOps.exif_transpose(image).convert("RGB")
            image.save(target, format="PNG")
    except (UnidentifiedImageError, OSError, ValueError) as exc:
        raise HTTPException(400, "无法读取图片") from exc


@app.post("/try-on")
def try_on(
    person: bytes = File(...),
    garment: bytes = File(...),
    description: str = Form("a shirt"),
):
    with TemporaryDirectory() as directory:
        root = Path(directory)
        person_path = root / "person.png"
        garment_path = root / "garment.png"

        save_image(person, person_path)
        save_image(garment, garment_path)

        try:
            client = Client(
                "yisol/IDM-VTON",
                token=os.getenv("HF_TOKEN"),
                download_files=str(root / "outputs"),
            )
            result = client.predict(
                dict={
                    "background": handle_file(str(person_path)),
                    "layers": [],
                    "composite": None,
                },
                garm_img=handle_file(str(garment_path)),
                garment_des=description,
                is_checked=True,
                is_checked_crop=False,
                denoise_steps=30,
                seed=42,
                api_name="/tryon",
            )

            output = BytesIO()
            with Image.open(result[0]) as image:
                image.convert("RGB").save(output, format="PNG")
        except Exception as exc:
            # 实际项目应在服务器记录错误,并细分配额、网络等问题。
            raise HTTPException(502, "试衣服务暂时无法完成请求") from exc

        return Response(output.getvalue(), media_type="image/png")

FastAPI 接收文件上传需要 python-multipart。文件和 description 会通过 multipart/form-data 一起提交。FastAPI 文件上传文档

启动:

uvicorn app:app --host 0.0.0.0 --port 8000

测试后端:

curl -X POST http://127.0.0.1:8000/try-on \
  -F "person=@person.jpg" \
  -F "garment=@shirt.jpg" \
  -F "description=a blue shirt" \
  --output result.png

Android 端可以用现有的 OkHttp 或 Retrofit,以相同字段名上传两张图片,再将成功响应作为图片读取。调用应放在后台线程,同时显示等待状态。

示例中的 token、download_files 和阻塞式 predict() 都来自当前客户端接口。如果使用旧版依赖,应核对对应版本的文档。Client 参数说明

自己部署时,优先考虑哪些模型?

CatVTON:有 GPU 时可以优先评估

CatVTON 官方仓库提供预训练权重和 Gradio 应用,无需从头训练。仓库说明,在指定的 bf16 配置下,生成 1024×768 图片约需 8 GB 显存。

这一显存需求有配置前提,并不保证任意 8 GB 显卡都能运行完整服务。部署时还要考虑预处理和并发请求的资源占用,以及 CUDA 依赖。

可以按以下顺序部署:

  1. 按仓库要求建立独立环境,先跑通官方 Gradio 应用。
  2. 用自己的图片确认 mask、服装类别和输出效果。
  3. 让 FastAPI 调用本地 Gradio 服务,或者提取推理函数供后端调用。
  4. 在单张 GPU 上先串行处理请求,验证后再考虑并发。

IDM-VTON:可复用演示流程,但预处理依赖较多

IDM-VTON 官方仓库提供预训练模型和本地 Gradio 演示。部署需要准备 human parsing、OpenPose、DensePose 等组件或检查点。接入用户上传的图片时,应沿用演示应用的预处理流程,避免直接把面向数据集的批量推理脚本当作上传接口。

这两个项目都声明采用 CC BY-NC-SA 4.0,有非商业使用等条件。学校项目也应按要求保留署名;后续若转成商业应用,需要重新检查授权及相关依赖的许可证。CatVTON 许可说明、IDM-VTON 许可说明

做课程演示时,需要处理哪些问题?

先把范围收窄到一种服装,例如上衣。人物照片尽量选择正面、身体区域完整且遮挡较少的,服装图则选择背景干净的,再逐步确认模型能处理哪些输入。生成图只能展示外观效果,不能用来判断实际尺码是否合适。

后端还需要补上以下处理:

  • 排队时间较长时,提交任务后先返回 job_id,由 Android 查询状态,避免一直占用一个 HTTP 请求。
  • 分别提示配额耗尽、网络失败和图片不合要求等问题,避免无限重试。
  • 限制上传体积、图片像素和请求并发。示例中的字节检查发生在请求解析之后,部署时还应在入口处设置上传限制。
  • 告知用户照片会发送给哪些服务,并清理自己服务中的临时文件。公共 Space 如何保留数据,需要单独确认。

没有 GPU 时,可以先用现有 Space 跑通端到端流程,再准备几组明确标注为预生成的演示结果,应对答辩现场的排队或网络故障。如果学校能提供 GPU,再迁移到自己部署的 CatVTON 或 IDM-VTON,保留 Android 到 FastAPI 的接口即可。

备注:内容仅供参考。