HiAPI
博客

教程

使用 API 去除图像背景:基于提示词的编辑

如何在 hiapi 上使用图生图模型替换或去除图像背景——最少的代码、批量模式,以及能让产品照片构图精准无误的 schema 细节。

2026年11月3日
使用 API 去除图像背景:基于提示词的编辑

传统的背景去除工具只提供一种操作:把主体抠出来,留下透明区域(或纯色填充)。而使用图生图模型进行基于提示词的背景去除,可以在一次调用中同时得到抠图结果和替换后的背景——无缝的白色影棚背景、生活场景、纯品牌色——因为模型是在保留的主体周围逐像素重新生成背景,而不是仅仅计算一个 alpha 蒙版。

本指南将准确展示如何在 hiapi 上做到这一点:哪些图生图模型真正擅长处理背景去除、你需要据此编码的请求/响应结构,以及能让批量任务避免悄悄污染你产品目录的生产模式(回调、重试、错误处理)。

前置条件:

  • 从你的仪表盘获取 hiapi API 密钥
  • Python 3.9+ 并安装 requests(pip install requests)
  • 你的源图像托管在公开 URL 上——hiapi 的任务 API 按 URL 获取图像,而不是通过文件上传,因此本地文件路径不可用。任何对象存储或 CDN 都可以。

背景去除作为图生图任务如何运作

hiapi 上的每一次生成——图像、视频或音频——都经过相同的异步任务生命周期:你提交一个任务,得到 taskId,然后要么轮询结果,要么通过回调 URL 接收结果。完整契约见异步任务 API 参考;对背景去除而言,重要的部分是:

  1. 带 model + input(你的提示词、源图像 URL 和输出形状)的 POST /v1/tasks 返回 {"code":200,"data":{"taskId":"tk-hiapi-..."}}。此时还没有 status 字段。
  2. GET /v1/tasks/{taskId} 返回 data.status,取值为 queued、handling、archiving、success、fail 之一。只有 success 和 fail 是终态。
  3. 当状态为 success 时,data.output 是一个 {"url","type","expireAt"} 数组。url 是带签名的短时效链接(expireAt 是 Unix 时间戳)——请立即下载,不要存储该热链。

至于模型,请使用图生图端点,并让提示词描述替换后的背景,而不是孤立地说“去除背景”——这些模型对具体目标的响应远好于对否定式指令的响应:

Remove the background completely and replace it with a seamless, pure white
studio background. Keep the subject's shape, edges, lighting, and colors
exactly unchanged. Do not add shadows, reflections, or any other objects
that were not in the original image.

最小示例:输入一张图像,替换背景

seedream-5.0-lite/image-to-image 是此用途最便宜且够用的选项——它接受 prompt、image_urls、aspect_ratio 和 resolution(仅支持 2K 或 4K;该端点没有 1K 档,并且像 n 或 seed 这样的未知字段会被直接以 400 拒绝)。

import os
import time
import requests

API = "https://api.hiapi.ai/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
    "Content-Type": "application/json",
}

BACKGROUND_PROMPT = (
    "Remove the background completely and replace it with a seamless, pure "
    "white studio background. Keep the subject's shape, edges, lighting, and "
    "colors exactly unchanged. Do not add shadows, reflections, or any other "
    "objects that were not in the original image."
)

def create_task(model: str, task_input: dict) -> str:
    resp = requests.post(f"{API}/tasks", headers=HEADERS,
                          json={"model": model, "input": task_input}, timeout=60)
    resp.raise_for_status()
    return resp.json()["data"]["taskId"]

def wait_task(task_id: str, timeout_s: int = 180, poll_s: int = 3) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        resp = requests.get(f"{API}/tasks/{task_id}", headers=HEADERS, timeout=30)
        resp.raise_for_status()
        task = resp.json()["data"]
        if task["status"] == "success":
            return task
        if task["status"] == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task {task_id} failed: {err.get('code')} {err.get('message')}")
        time.sleep(poll_s)
    raise TimeoutError(f"task {task_id} still {task['status']} after {timeout_s}s")

task_id = create_task("seedream-5.0-lite/image-to-image", {
    "prompt": BACKGROUND_PROMPT,
    "image_urls": ["https://your-cdn.example.com/product-photo.jpg"],
    "aspect_ratio": "1:1",
    "resolution": "2K",
})
task = wait_task(task_id)
image_bytes = requests.get(task["output"][0]["url"], timeout=60).content

with open("product-no-bg.png", "wb") as f:
    f.write(image_bytes)

这就是整个循环:提交、轮询、下载。在将其接入流水线之前,若想快速进行无代码验证,AI 产品照片实验室可在浏览器中运行同类型的背景替换。

批量处理产品目录

真实的产品目录有几十或几百张图像,而任务 API 没有原生批量端点——你需要自行展开单个任务提交,并并发轮询它们:

from concurrent.futures import ThreadPoolExecutor, as_completed

def remove_background(image_url: str, aspect_ratio: str = "1:1") -> str:
    task_id = create_task("seedream-5.0-lite/image-to-image", {
        "prompt": BACKGROUND_PROMPT,
        "image_urls": [image_url],
        "aspect_ratio": aspect_ratio,
        "resolution": "2K",
    })
    task = wait_task(task_id)
    return task["output"][0]["url"]

source_urls = [
    "https://your-cdn.example.com/sku-1001.jpg",
    "https://your-cdn.example.com/sku-1002.jpg",
    # ...
]

results = {}
with ThreadPoolExecutor(max_workers=5) as pool:
    futures = {pool.submit(remove_background, url): url for url in source_urls}
    for future in as_completed(futures):
        url = futures[future]
        try:
            results[url] = future.result()
        except Exception as exc:
            results[url] = None
            print(f"failed: {url}: {exc}")

保持 max_workers 适度——在许多并发任务上过于频繁地轮询只会消耗请求配额,并不会加速生成,因为每个任务的墙钟时间主要由模型推理决定,而不是你的轮询频率。

生产环境加固:精确构图、回调、幂等性、错误

保留精确的产品构图。对于目录工作,你通常无法容忍模型重新构图或轻微裁切主体——输入中居中的鞋子需要保持在输出中居中。seedream-5.0-pro/image-to-image 支持 lite 档不支持的 aspect_ratio 值:match_input_image,它将输出画布锁定为输入图像自身的尺寸,而不是强制为固定比例。它每次调用还接受最多 10 个 image_urls,并将 resolution 限制为 1K/2K(与 lite 不同的分辨率集——不要假设各 seedream 端点的 schema 一致,每个端点都有自己的枚举)。对于构图必须精确匹配的纯背景去除与替换工作,这是应当选择的档位,每张图像成本更高——当前费率见定价。

如果你需要一次引用多个源角度(例如同一产品的前视图和侧视图),而不是每次调用处理一张图像,nano-banana-2 是一个合理的替代方案——它通过 image_input(而非 image_urls)接受参考图像,另有 resolution 可取 1K/2K/4K。

用回调代替轮询。对于任何真实规模的批量任务,webhook 都优于轮询:添加一个 callback 对象作为 input 的同级——不要嵌套在它内部,POST /v1/tasks 会拒绝那种结构:

task_input = {
    "prompt": BACKGROUND_PROMPT,
    "image_urls": [image_url],
    "aspect_ratio": "1:1",
    "resolution": "2K",
}
resp = requests.post(f"{API}/tasks", headers=HEADERS, json={
    "model": "seedream-5.0-lite/image-to-image",
    "input": task_input,
    "callback": {"url": "https://your-service.example.com/hooks/hiapi", "when": "final"},
}, timeout=60)

任务达到终态后,hiapi 会向你的回调 URL POST 与 GET /v1/tasks/{taskId} 会返回的相同 data 对象。如果你想在服务端验证回调的真实性,可参阅异步任务参考中可选的 X-HiAPI-Signature HMAC 头。

幂等性。POST /v1/tasks 上没有文档化的 idempotency_key 字段——请在应用层构建幂等性。用一个小的存储(数据库行、Redis 键,甚至一次性脚本的本地文件),按 (image_url, prompt, model) 的哈希作为键,在提交新任务之前,检查该键是否已有存储的 taskId 或输出 URL。如果你的批量任务中途崩溃并重跑,你就能跳过已处理图像的重复计费,而不是悄悄增加成本。

错误处理——三种不同形态,不要同样对待:

  • 请求校验(创建时的错误输入)——HTTP 400,扁平结构:{"code":400,"error_code":"INVALID_REQUEST","message":"...","data":null}。这意味着你的 input 字典与模型 schema 不匹配——检查是否有拼错的字段名或错误的枚举值。
  • 认证失败——HTTP 401,嵌套方式不同:{"error":{"code":"permission_denied","message":"...","request_id":"...","type":"hiapi_error"}}。API 密钥缺失/过期,而不是请求错误——不要重试,修复密钥。
  • 任务级失败(请求有效,但生成本身失败)——在你轮询时显现:data.status == "fail",data.error 描述出错原因。这是可重试的;暂时的上游错误重新提交后可能会成功。
if task["status"] == "fail":
    err = task.get("error") or {}
    # log err["code"] / err["message"], then decide: retry, skip, or alert

不要将三者都归入一个 except Exception——401 在循环中重试只会消耗你的速率限制且永远不会成功,而任务级 fail 确实可能在第二次尝试时成功。

下一步

常见问题

这真的去除背景,还是只是覆盖它?功能上两者都是——模型在保留的主体周围重新生成整个画布,因此不会像边缘检测抠图工具那样留下残余蒙版或毛边。代价是必须在提示词中明确说明“保持其他一切不变”,否则模型会乐于连主体一起重新风格化。

我能得到透明 PNG 而不是纯色背景吗?在提示词中直接要求(例如“将背景替换为透明”或“在透明背景上隔离主体”),并在模型支持 output_format 字段的地方请求 PNG 输出——支持情况因模型而异,因此假设可用之前请检查特定模型的页面。

为什么我的图像返回时被重新构图,而不是与原始图像匹配?你很可能使用的档位其 aspect_ratio 枚举不包含 match_input_image——在 lite/4.5 档中,你选择的是固定比例,相对于源图可能会裁切或加黑边。切换到 seedream-5.0-pro/image-to-image 并将 aspect_ratio 设为 match_input_image。

每张图像的成本是多少?定价因模型和分辨率档位而异,并会随时间变化——请查看定价,而不是在你自己的代码或文档中硬编码数字。

如果我的图像 URL 还不是公开的怎么办?任务 API 在服务端按 URL 获取图像,因此它必须无需认证即可访问。请先上传到任何公开桶或 CDN 路径——带签名/私有 URL 或 localhost 路径会在任务创建时失败,或(更糟)在处理过程中静默失败。

立即开始构建持久 AI 产物

获取 API 密钥,通过一个基于任务(task)的 API 调用图像、视频和音频模型。

阅读 API 文档