本文へスキップ

背景除去APIで透過商品PNGを納品する

商品写真をAPI 1回で透過PNGに切り抜き、納品前にアルファチャンネルとエッジを確認する手順を紹介します。

執筆
Lydia
公開
読了時間
約 22 分
更新
コバルト色のジャンプスーツを着た女性が、市松模様の人物シルエットを配したアクリルパネルの横に立っている

グレーのテーブルや窓辺で撮った商品写真が数百枚あり、ショップやマーケットプレイス、デザイナーがそれぞれを透過PNGで求めているとします。SpicyAPI Background Remover なら1回の呼び出しで済みます。写真のURLを送ると、元の幅と高さのまま、主役の被写体を透過PNGで返します。その後の作業は利用者側の仕事です。ファイルに本当にアルファがあるか確認し、実際に置く背景の上でエッジを確かめ、納品先ごとに必要なフラットなコピーを書き出します。

まずPlaygroundで試す

background-remover-v1 のPlaygroundを開きます。Input image に商品写真をドロップし、料金を確認して Run model を押します。同じ写真をコードで使う前に、透過結果を明るい背景と暗い背景の上で確認してください。

エンドポイントが受け取るものと返すもの

Background Remover (spicyapi/background-remover-v1/edit)
入力image_url の1フィールドのみ。JPEG、PNG、WebPの写真。プロンプト、マスク、被写体の指定はありません
被写体の選択自動です。フレームに候補が複数あるときは先にトリミングしてください。必要以上に残ることがあります
出力アルファチャンネル付きのPNG 1枚。幅と高さは入力と同じです
料金出力画像1枚あたり $0.0048。送る写真のサイズでは変わりません
制限時間1,800秒以内に終わらないタスクは期限切れとなり、課金されません
結果のリンクoutput.assets[0].url に入る署名付きURLで、有効期間は約20分です(新しいURLが必要ならタスクを再度照会します)。ファイル自体の保管は最長で約14日です

出力は元のキャンバスサイズを保つので、拡大縮小せずに切り抜きを差し替え用の背景へ重ねられます。切り抜きの境界には返されたアルファチャンネルを使ってください。キャンバスが同じでも、前景のすべてのエッジや色が変わらないとは限りません。詳細はBackground Remover のモデルページにあります。

まず実際の結果を見る

モデルページ自身の例は、グレーのスタジオ背景に置いたすりガラスのスポイト瓶で、1024 × 1536ピクセルです。同ページの変換前と変換後のファイルで、「変換後」はここではページの背景の上に表示しています。

グレーのスタジオ背景に置かれた、ラベルが白紙のすりガラス製スポイト瓶の元写真(1024 × 1536ピクセル)
Background Remover の入力: グレーの背景のすりガラス製スポイト瓶
同じスポイト瓶を透明な背景で切り抜いた画像(同じ1024 × 1536のサイズ)
Background Remover の出力: 透明な背景の瓶

次の章以降の確認スクリプトをこのペアに実行すると、良い結果の数値が得られます。出力にはアルファチャンネルがあり、サイズは元と一致し、ピクセルの約78%が完全に透明、約22%が不透明で、半透明のエッジピクセルは約0.35%だけです。被写体のボックスは335 × 1,234ピクセルです。濃紺の背景に合成しても、スポイトの先端、ブラシ仕上げのカラー、すりガラスの肩に明るい縁取りは出ません。

呼び出す

python -m pip install spicyapi pillow で spicyapi と pillow をインストールします。SPICY_API_KEY と、元画像の直接URLを入れた IMAGE_URL を設定してから、この例を実行してください。料金の確認を求め、タスクを作成して完了を待ち、切り抜きを保存し、明るい背景と暗い背景のプレビューを書き出します。

python
import os
import urllib.request
import uuid
from io import BytesIO
from pathlib import Path

from PIL import Image
from spicyapi import SpicyClient, output_assets

client = SpicyClient()
model = "spicyapi/background-remover-v1/edit"
inputs = {"image_url": os.environ.get("IMAGE_URL", "https://cdn.spicyapi.ai/models/examples/inputs/e82b71db9e3d0e5f.png")}

quote = client.quote_task(model=model, input_data=inputs)
if input(f"Maximum ${quote['maxCharge']}. Create? [y/N] ") != "y":
    raise SystemExit("Stopped without creating a task.")

task = client.create_task(model=model, input_data=inputs, idempotency_key=str(uuid.uuid4()),
                          quote_id=quote["quoteId"], expected_cost=quote["estimatedCost"])
print("Task:", task["taskId"])  # keep this ID: a timeout does not cancel the task
task = client.wait_for_terminal(task["taskId"])
if task["state"] != "succeeded":
    raise RuntimeError(str(task.get("errorMessage", task["state"])))

asset = output_assets(task)[0]
request = urllib.request.Request(asset["url"], headers={"User-Agent": "SpicyAPI-Blog-Example/1.0"})
with urllib.request.urlopen(request, timeout=120) as response:
    data = response.read()
Path("cutout.png").write_bytes(data)

with Image.open(BytesIO(data)) as image:
    if image.format != "PNG":
        raise RuntimeError("Expected a PNG cutout.")
    rgba = image.convert("RGBA")
alpha = rgba.getchannel("A")
values = list(alpha.getdata())
print({"size": rgba.size, "alpha_min_max": alpha.getextrema(),
       "clear_fraction": sum(v <= 8 for v in values) / len(values),
       "solid_fraction": sum(v >= 247 for v in values) / len(values),
       "soft_fraction": sum(8 < v < 247 for v in values) / len(values),
       "subject_box": alpha.getbbox()})
for name, colour in [("light", "#f5f2e8"), ("dark", "#162235")]:
    Image.alpha_composite(Image.new("RGBA", rgba.size, colour), rgba).convert("RGB").save(name + ".jpg")

応答が失われたあとで同じリクエストを再試行するときは、新しいキーを作らずに、そのリクエストの冪等性キーを再利用します(冪等性のリファレンス)。ローカルファイルのアップロードについては、Python SDKとメディアのドキュメントを参照してください。

ファイルをデコードして透過を確認する

白いプレビューは何の証明にもなりません。白いページ上の本物の切り抜きかもしれませんし、白い背景付きの不透明な画像かもしれず、市松模様がピクセルに直接描かれている可能性もあります。ファイルをデコードして、アルファチャンネルを読みます。アルファの格納方法はPNG仕様で定められています。実務で知るべきなのは、デコード後に透明になりうるピクセルがあるかどうかで、ファイル名がどうなっているかではありません。

この例はアルファの分布を報告し、Pillowでクリーム色と濃紺の合成画像を書き出して確認できるようにします。報告されたサイズを元画像と比べてください。

しきい値には注意が必要です。アルファ255だけを不透明と数えると誤解を招きます。スポイト瓶の出力では、約14%のピクセルがアルファ1〜254にありますが、そのほとんどは254で、見た目には不透明です。アルファ8以下を透明、247以上を不透明として扱えば、「ソフト」の割合に、本当に気にしたいもの、つまりアンチエイリアスのかかったエッジ、髪、本当に半透明な素材だけが残ります。

レポートの読み方:

  • アルファチャンネルがない、または alpha_min_max が(255, 255)なら、透明な部分がありません。エッジを確認する前にパイプラインを調べてください。
  • 背景のあった写真で clear_fraction がほぼ0、または solid_fraction がほぼ0なら、被写体が失われたか、結果がもやのようになっています。
  • サイズが合わない場合は、EXIFで回転された元画像か、自分のコードでのリサイズが原因のことが多いです。エンドポイントは寸法を保つためです。
  • soft_fraction が大きいのは、ガラス、布、髪では普通で、マットなマグカップなら警告のサインです。しきい値は1つの全体値ではなく、パイロットセットを見たうえで商品カテゴリごとに決めてください。
  • ゆったりトリミングした写真で被写体のボックスがキャンバスの端に接している場合は、2つ目の物体が残っている可能性があります。
図: アルファ0は透明、128は部分的な被覆、255は不透明。同じ青い円盤が明るい背景と暗い背景で違って見える
アルファはエッジのなじみ方を決めます。実際のエッジを明るい背景と暗い背景の両方で確認してください。

商品を変えずに写真を準備する

撮影やトリミングの前に、何を商品とみなすかを決めてください。リボン、パッケージ、接地の影は、含めるか外すかのどちらかで、書かれていない指示をツールが推測することはできません。欠けたふちを描き直したり、ないロゴを作り足したりしないでください。出品ページで見せるべき欠点は、写真に残します。

  • 競合する物体を除くためにトリミングしますが、持ち手やストラップがAPIに見える前に切れないよう、すべての端の周りに余白を残します。
  • 重なった物体はトリミングでは直せません。隠れた境界を推測する必要があるからです。撮り直し、重なり、透明なディスプレイスタンド、見切れた被写体は例外レーンに回して、通常のバッチを詰まらせないようにします。
  • いちばんきれいなファイルを送ります。JPEGで何度も書き出すと、エッジにディテールが必要なまさにその場所にブロックノイズが出ます。劣化のない作業用コピーを保管してください。カラープロファイルの変換は意図して行ってください。雑な変換は、誰かが切り抜きを確認する前に商品の色を変えてしまいます。

画像を使う場所でエッジを確認する

切り抜きは、確認に使っているページだけでなく、実際の納品先の背景の上に置いてください。クリーム色の上できれいに見える切り抜きでも、濃紺の上では淡い縁が出ることがあります。この縁は、元の背景の色が半透明のピクセルに残ったものです。欠点が問題になるか見るには納品サイズで、形を見るには100%で確認します。スクリプトの2つの合成画像はクリーム色と濃紺を使っているので、ブランドカラーに差し替えてください。

すべてのピクセルを同じように見るのではなく、この種の商品が見分けられる部分を見ます。マグカップの持ち手の内側、ふちと底、靴ひもと靴底、ブラシの毛、スポイトの先端などです。元画像、アルファ、合成画像を同じ縮尺・同じ切り出しで比べます。ファイルを却下するときは、失われた特徴と納品先を書いてください(「暗い合成で持ち手の穴が埋まっている」)。次の人が、トリミング、レタッチ、撮り直しのどれかを判断できます。

黄色い輪郭を付けた4つの商品写真: マグカップ、ガラスのデカンタ、鉢植え、フリンジ付きの黒いスカーフ。確認が必要なシルエット、開口部、細いエッジを示している
確認すべきシルエット、開口部、細いエッジ: マグカップの持ち手、ガラス、葉、フリンジ(編集用イラストで、APIの出力ではありません)。

再試行ではなく判断が必要な状況が3つあります。

  • シルエットの内側の穴。 持ち手の穴や椅子の背の桟の間は背景に属します。輪郭だけを確認すると、穴が埋まっていても正しく見えることがあります。暗い合成画像で確認してください。
  • 影。 接地の影は商品を地面になじませますが、長く伸びた影は背景のテクスチャを切り抜きに引き込みます。マスターに影を残すか、レイアウト側で自前の影を描くかを決めてください。自前の影を加える場合は、元画像にある影を弱めるか消して、2つの影がぶつからないようにします。
  • ガラスと半透明の素材。 瓶の色には背景から透過した光が含まれるので、どんな新しい背景でも物理的に正しい瓶になる切り抜きはありません。白では自然に見える淡いスタジオの映り込みも、暗い背景では不自然に見えることがあります。半透明のプラスチックや布は、アルファを0か255にしきい値で丸めず、部分的なアルファのまま残してください。縁取りを消すためにマスク全体を収縮させるのもやめましょう。商品が細くなり、細かい特徴が失われます。コピーに対して局所的にレタッチします。
3つのクローズアップ: 斑点のあるマグカップの持ち手の穴、石の上で長い影を落とすオイルの小瓶、葉を背にしたグラスのふち。判断が異なる持ち手、影、ガラスを示している
持ち手の穴は抜けるべきで、影は指示書に従い、ガラスは背景に依存する色を保ちます(編集用イラストで、APIの出力ではありません)。

失敗は原因になった段階で直す

再実行する前に分類してください。同じ呼び出しを繰り返すとお金がかかり、これらの多くでは何も変わりません。

見えるもの原因対処
タスクが invalid_request または取得エラーで失敗するURLが画像ファイルへの直接リンクではないURLを直すかファイルをアップロードする。同じ入力で再試行しない
ファイルがデコードできない、またはアルファがない転送か、自分側の変換結果をダウンロードし直す。JPEGへの変換が入っていないか確認する
ギフトボックスや2つ目の商品が残る被写体の候補が複数ある商品にトリミングし、新しい元画像のリビジョンとして送る
持ち手の先やストラップが切れる送信前のトリミングがきつすぎたすべての端に余白を取って再トリミングする
髪、フリンジ、細いブラシの毛がギザギザになる自動の切り抜きでは硬いエッジになりやすい無地に近い背景で撮り直すか、その1枚を手作業でマスクする
暗い背景で淡い縁が出るエッジのピクセルに元の色が残っている、または後段のシャープ化やリサイズマスターと元画像を比べて段階を特定し、書き出し工程を直す
商品の周りに塗りつぶしの箱が出るJPEG書き出しが透明部分を埋めた意図してフラット化する(次の章)。PNGはマスターとして保管する

ツールを誘導するプロンプトはないので、調整できるのは入力写真と、呼び出し後の作業です。あるカテゴリが失敗し続けるなら、リクエストを繰り返すのではなく、撮り方を変えてください。

無地の背景が必要な納品先向けにフラット化する

マーケットプレイスは白背景のJPEGを求めることがよくあります。JPEGにはアルファがないため、マスターをJPEGに書き出すと、透明部分が誰も承認していない既定の色で埋まります。選んだ色の上でフラット化し、PNGはマスターとして保管し、拡大縮小は均一に行います(幅と高さを別々に引き伸ばさないこと)。スクリプトが書き出す light.jpg は、まさにこの工程をクリーム色で行ったものです。白にするにはループ内の色を変えるか、画像エディターで別にフラット化したJPEGを書き出してください。マスターだけでなく、フラットなファイルも確認します。リサンプリング、色変換、圧縮はそれぞれ独自の不具合を足します。ショップやCMSにアップロードしたあとにだけ縁取りが出る場合は、マスター、自分の書き出し、プラットフォームのサムネイルのデコード後のピクセルを比べてください。原因は切り抜きではなく、プラットフォーム側のリサイズや再圧縮であることがよくあります。

別のルートが適切な場合

単純な切り抜きなら、Background Remover はこの表でもっとも低価格のルートで、元のキャンバスサイズも保ちます。意図的に提供していないことが必要なときは、別のルートを使ってください。

必要なことルート料金(ライブ見積もり)備考
単純な商品の切り抜き、新しい内容なしBackground Remover1画像あたり $0.00481フィールド。元のサイズのまま
切り抜きとプロンプト駆動の編集を1回の呼び出しでGPT Image 2.5 Sunburst または Flare、background: transparent、output_format: png を指定した edit タスク低品質で $0.0149、中品質で $0.0208(1k、入力画像1枚)生成型です。商品が描き直されることがあるので、商品とアルファを確認してください。Flare と Sunburst の比較ガイドを参照
GPT Image 2(2.5ではない)利用不可background は auto か opaque のみ受け付け、透明の指定は拒否されます
完成したデザインから人物や商品を取り出し、さらにテキストやシーンのレイヤーも得るSeedream 5.0 Flash のレイヤー分解出力画像1枚あたり $0.026ベース画像1枚と最大16枚の透過レイヤーで、出力ごとに課金されます。デフォルトのリクエストは17出力、$0.442と見積もられるため、単純な切り抜き1回とは別の作業・別のコストです。レイヤー分割ガイドを参照

生成モデルがPNGを返しても、透明になるとは限りません。PNGは不透明な白い背景を持てます。すべての結果を同じスクリプトでデコードしてください。商品の正確なピクセルが重要な場面(ラベル、ロゴ、パッケージの文字)では、生成型の描き直しよりも抽出ルートを選びます。

確認担当を溺れさせずにバッチを回す

モデルの呼び出しは安くて速く、ボトルネックは確認作業です。カタログを代表する、権利処理済みの写真を12枚ほど選んでパイロットから始めてください。きれいな単純形状が1つ、持ち手や開口部のあるもの、光沢のあるもの、細いエッジのあるもの、競合する物体があるものを1つずつ入れます。パイロットの結果で、軽い確認で済ませるカテゴリと、常に人が見るカテゴリを決めます。

  • 同時実行数に上限を設けて送信し、ダウンロード用のキューは別に持ちます。遅いダウンロードが再抽出を引き起こさないようにするためです。ダウンロードに失敗したら、リンクが有効なうちは既存の結果に対して再試行します。キューの設計はバックプレッシャーのガイドで扱っています。
  • 元画像のリビジョンごとに、自社のアセットID、元画像のチェックサム、タスクID、出力先、確認の判断を保存します。SKUだけでは足りません。1つの商品には複数の角度と撮り直しがあります。
  • 「succeeded」は「確認可能」を意味するだけで、「公開してよい」ではありません。スクリプトを自動で実行し、人には警告が付いたファイルとサンプルだけを回します。パイロットを通過したカテゴリ(中立的な背景の単純な物体)は、ドリフトを拾う定期サンプリングを付けた軽いレーンへ移せます。反射する物、透明な物、判断が分かれる物は引き続き全数確認です。キャンペーンのメイン画像は、完了順ではなくサブの角度より先に確認します。
  • 完了通知については、非同期タスクのポーリングとWebhookの比較ガイドを参照してください。どちらの方法でも、結果は同じ確認ステップに入ります。
  • 失敗の原因が共通しているときは止めます。持ち手の穴が10件失われたなら、それは元の素材についての情報であって、10回再試行する理由ではありません。

承認された画像1枚あたりのコスト

切り抜き100枚は$0.48、1,000枚は$4.80です。重要なのは、承認されたマスター1枚あたりの支出です。計画の例として、最初の切り抜き100枚に再トリミングした10枚を加えたバッチは 110 × $0.0048 = $0.528で、95枚が確認を通れば、承認された画像1枚あたり約$0.0056になります。

コストの計算例: 110枚の切り抜きが$0.0048で$0.528。承認された95枚のマスターで割ると1枚あたり約$0.00556。確認の人件費は別の項目
コストの計算例: 110枚の切り抜きが$0.0048で$0.528。承認された画像1枚あたり約$0.00556で、確認の人件費は含みません。

通常、確認にかかる時間のほうがAPIより高くつきます。有効な手立ては上流にあります。確認時間の大半がガラス瓶に取られているなら、その撮影環境の照明を改善するほうが、どんな価格差よりも多くを節約できます。完了した切り抜きを却下しても、完了して課金された出力であることに変わりはありません。失敗したタスクや期限切れのタスクは、ホールドが解放されます。

元画像、マスター、書き出しを分けて保管する

元の写真、透過PNGのマスター、フラット化した納品用コピーを別々のファイルとして保管し、内容がわかる名前を付けます(例: <asset>-source、<asset>-cutout-master、<asset>-catalogue-cream)。レタッチした版は手を加えていないAPIの出力と分けて保管し、あとで縁取りが出たときに、切り抜きと書き出しのどちらが原因かたどれるようにします。承認された納品サイズも各マスターと一緒に保存しておくと、カードサイズでの承認がメインビジュアルサイズでの承認と取り違えられません。

却下は、「被写体の間違い」「特徴の欠落」「縁取り」「背景の断片の残り」「書き出しの不具合」のうち1つの分類で記録します。件数が意味を持つのは、何かを変えるときだけです。トリミングのルール、ガラス用の手動レーン、修正した書き出しプリセットなどです。カメラマンには「AIが処理しやすいように」ではなく、具体的な撮影ルールを渡してください(「持ち手全体を写すこと。開口部の後ろにギフトボックスを置かない」「淡い色の商品には暗めの背景を使う」)。

香水瓶を、「元画像」「マスター」「確認用コピー(明・暗)」「最終書き出し」とラベルを付けた4枚の印刷物風カードで示した図。ファイルを分けておく理由を表している
元画像、マスター、明暗の確認用コピー、納品先への書き出しは別々に保管します(編集用イラストで、実際の納品フォルダではありません)。

よくある質問

無料の背景除去APIはありますか?

このエンドポイントにはありません。完了した出力1枚ごとに$0.0048かかるので、写真100枚のパイロットは$0.48です。無料が必須条件なら、rembgのようなオープンソースの除去ツールを自前でホストすれば画像ごとの料金は避けられますが、運用と調整は自分で行うことになります。ホスト型のルートで得られるのは、安定したエンドポイントと予測しやすいコストです。

結果をPNGで保存すれば背景は透明になりますか?

いいえ。PNGはアルファを持てますが、不透明な白い背景を含むこともあります。ファイルをデコードしてアルファチャンネルを読み、明るい背景と暗い背景の合成画像を確認してください。JPEGの拡張子を.pngに変えても何も加わりません。

持ち手や髪、影を残すよう指示できますか?

このタスクではできません。入力は画像URLだけです。元画像をトリミングする、撮り直す、またはローカルでレタッチしてください。プロンプトで結果を操作したい場合は、上の表にある画像編集のルートを使い、あとから商品とアルファを確認します。

どう始めればよいですか?

代表的な商品を1つと、納品先を1つ選びます。写真を送ってPNGをデコードし、2つの背景でエッジを確認し、承認した派生ファイルをフラット化して、デザイナーに実際のレイアウトで開いてもらいます。そのあとパイロットセットのより難しいものを実行し、カタログ全体をスケジュールする前に、撮り直しや手動レーンが必要なものを書き留めてください。

呼び出しをAgentに任せる

入力の準備と結果の返却をAgentにさせ、料金とクリエイティブな判断は自分で承認したいときに使います。

  • CLI: 同じ入力オブジェクトを input.json として保存し、npx @spicyapi/cli tasks create --model spicyapi/background-remover-v1/edit --input-file input.json --wait を実行します。CLIは料金の確認を求めます。復旧用に、返されたタスクIDを控えておいてください。
  • MCP: アシスタントに、spicyapi/background-remover-v1/edit に対して spicyapi_task_create を、続けて spicyapi_task_wait を使うよう頼みます。MCPサーバーは、作成の前に料金の確認を求めます。
  • Skill: npx skills add spicyapi-ai/spicy-skill でインストールし、$spicyapi に同じワークフローを実行して承認待ちで止まるよう頼みます。Skillは設定済みのCLIまたはMCP接続を使います。

他の言語 English · 한국어 · Deutsch · Français · Español · Português (Brasil) · Русский · Italiano · Polski

実際に試してみる

支払いは実行した分だけ。プランもサブスクリプションもありません。

使用モデル:MiniMax H3 · ByteDance Seedance 2.0 Fast