広告枠を募集中 ご相談ください

EC開発者がCutout.proのREST APIを商品画像パイプラインに統合し、一括背景透過と画像標準化を実現する方法

365Finds Editorial
Wiki 記事 11,430 本収録

あなたの AI で 365 Wiki を使う

下のプロンプトをコピーして、普段使っている AI に貼り付け、そのまま質問してください。

完全版 Skill をダウンロード

まずはプロンプトでお試しください。よく使う場合は完全版 365Wiki Skill をインストールすると、毎回貼り付ける必要がありません。普段使う AI がなければ、Gemini や Microsoft Copilot のウェブ版でも使えます。

大規模なECモールや複数プラットフォームを横断する出品チームにおいて、商品登録時の画像処理は深刻な運用ボトルネックになりがちです。各サプライヤーから納品される元画像は、解像度、アスペクト比、背景の雑音、照明条件がバラバラです。デスクトップ向けの一括レタッチツールは手作業が介在するため社内ERP、PIM(商品情報管理)、CMSとの自動連携が難しく、デザイナーによる手動切り抜き作業は24〜72時間の出品遅延とSKUあたりの人件費高騰を招きます。

Cutout.proが提供する開発者向けREST APIを活用すれば、商品画像の背景透過(切り抜き)、トリミング、白抜き背景生成を自動化できます。このAPIをバックエンドの非同期画像処理パイプラインに組み込むことで、入荷した生データを数秒でAmazonやShopifyの出品基準に適合した純白背景(#FFFFFF)、統一マージン、自然な接地シャドウ(コンタクトシャドウ)付きの標準画像へと一括変換できます。


1. Cutout.pro APIの仕様と認証フロー

Cutout.proの機能はHTTPSエンドポイント経由で提供されます。認証はシンプルで、すべてのリクエストのHTTPヘッダーに発行されたAPIキーを付与します。

APIKEY: your_cutout_pro_api_key_here

パイプライン実行前のクレジット残高確認

セール期やシーズン切り替え時の商品一括登録では、数万枚の画像が一括処理されます。処理途中でクレジットが枯渇するとエラーコード 4001(残高不足)が発生し、後続タスクが停止してしまいます。そのため、バッチ処理開始前にアカウント残高を事前確認する設計が不可欠です。

Cutout.proには残高確認専用のエンドポイントが用意されています。

レスポンス例:

{
  "code": 0,
  "data": {
    "monthBalance": 1250,
    "imageBalance": 5000,
    "videoBalance": 0,
    "monthStartDate": "2026-10-01 00:00:00",
    "monthExpireDate": "2026-11-01 00:00:00"
  },
  "msg": null,
  "time": 1728729600000
}

タスクオーケストレーターに事前チェックを組み込むことで、残高不足時にジョブを安全に一時停止し、運用チームへアラートを通知できます。


2. エンドポイントの選定と必須パラメータ

EC商品の切り抜き処理には、汎用オブジェクト向けモデルである mattingType=6 または mattingType=1 を指定します。画像の保存場所やアーキテクチャに応じて3つの呼び出しモードが選択可能です。

モードエンドポイントメソッド & Content-Typeレスポンス形式推奨ユースケース
モード1: バイナリ直接取得https://www.cutout.pro/api/v1/mattingPOST / multipart/form-data生画像バイナリ(image/png)ローカルディスク書き込みやインメモリ処理
モード2: Base64 JSONhttps://www.cutout.pro/api/v1/matting2POST / multipart/form-datadata.imageBase64 含むJSONJSON-RPCベースのマイクロサービス間連携
モード3: URL指定https://www.cutout.pro/api/v1/mattingByUrlGET / クエリパラメータdata.imageBase64 含むJSONS3、Cloudflare R2、CDN上に元画像がある場合

EC標準化に重要なリクエストパラメータ


3. 大量バッチ処理とレートリミット対策(非同期キュー設計)

Cutout.proのAPIは同期型HTTP通信であり、1枚ごとのリクエストに対して即時推論が行われます。しかし、標準プランでは 秒間最大5リクエスト(5 QPS) という同時実行制限が存在します。

無制限なマルチスレッドで並行送信を行うと、エラーコード 5005(Too many requests in the queue, please wait)が頻発します。数万SKUを安定処理するためには、非同期メッセージキューによる流量制御が必要です。

本番環境向けアーキテクチャ

[ERP / PIM 一括商品登録]
        │ (SKUバッチ投入)
        ▼
[メッセージブローカー: Redis / RabbitMQ]
        │
        ▼
[Workerクラスタ (Celery / BullMQ)]
   ├── トークンバケット流量制御 (クラスタ全体で <= 4.5 QPS に制御)
   ├── Cutout.pro API呼び出し (POST /api/v1/matting?mattingType=6)
   │     └── 5005エラー時の指数バックオフ+ジッター
   ├── 画像標準化エンジン (Pillow / Sharp)
   │     ├── 正方形キャンバスへの配置 (2000x2000px)
   │     ├── 85%比率でのセンタリングリサイズ
   │     └── 自然な接地シャドウ (Contact Shadow) の合成
   ├── クラウドストレージ保存 (AWS S3 / Cloudflare R2)
   └── ERPへのWebhook通知 (処理完了・画像URL更新)

リトライとエラー処理方針

  1. トークンバケットによる流量制御: ワーカープール全体からの外部送信レートを秒間4.5回以下に制限し、Cutout.proの5 QPS制限超過を防ぎます。
  2. エラーコードごとの分岐:
    • 5005(キュー超過・頻度制限): 指数バックオフ(待機時間: 1.5秒、3秒、6秒+ランダムジッター)で再試行。
    • 1002(15MB超過)/ 5008(不正画像): デッドレターキュー(DLQ)に転送し、ERPダッシュボードで手動確認フラグを付与。
    • 4001(残高不足): ワーカーの消費を全停止し、即座にSlackやメールで運用担当者へ高優先度アラートを通知。

4. 画像標準化パイプラインの実装(サイズ、マージン、接地シャドウ)

APIの bgcolor=FFFFFF オプションで単純な白背景化は可能ですが、主要ECプラットフォームの出品基準を満たすには以下の調整が必要です。

推奨される構成は、Cutout.proから透過PNG(crop=true、bgcolor なし)を取得し、ワーカー内の画像ライブラリ(Python PillowやNode.js Sharp)でキャンバス調整と影の合成を行う方式です。

本番用実装コード(Python + Pillow)

import io
import time
import requests
from PIL import Image, ImageFilter

CUTOUT_API_KEY = "YOUR_API_KEY_HERE"
API_URL = "https://www.cutout.pro/api/v1/matting?mattingType=6&crop=true"

def remove_background(image_bytes: bytes, max_retries: int = 3) -> bytes:
    """Cutout.pro APIを呼び出し、5005制限時の指数バックオフを備えた切り抜き処理"""
    headers = {"APIKEY": CUTOUT_API_KEY}
    files = {"file": ("product.jpg", image_bytes, "image/jpeg")}
    
    for attempt in range(max_retries):
        response = requests.post(API_URL, headers=headers, files=files, timeout=30)
        
        if response.status_code == 200 and response.headers.get("Content-Type", "").startswith("image/"):
            return response.content
        
        try:
            err = response.json()
            code = err.get("code")
            msg = err.get("msg")
            
            if code == 5005:  # キュー制限
                time.sleep((2 ** attempt) + 0.5)
                continue
            elif code == 4001:
                raise RuntimeError("Cutout.proのAPIクレジットが不足しています。")
            else:
                raise ValueError(f"Cutout.pro処理失敗: {code} - {msg}")
        except requests.exceptions.JSONDecodeError:
            response.raise_for_status()

    raise TimeoutError("Cutout.proへのリトライ上限に達しました。")

def standardize_product_image(
    transparent_png_bytes: bytes,
    target_canvas_size: int = 2000,
    fill_ratio: float = 0.85
) -> Image.Image:
    """
    正方形純白キャンバスへリサイズ・配置し、占有率85%と自然な接地シャドウを合成。
    """
    # 1. 切り抜かれた透過PNGを読み込み
    product = Image.open(io.BytesIO(transparent_png_bytes)).convert("RGBA")
    prod_w, prod_h = product.size

    # 2. 占有率に合わせたアスペクト比保持スケーリング
    max_dim = int(target_canvas_size * fill_ratio)
    scale = min(max_dim / prod_w, max_dim / prod_h)
    new_w, new_h = int(prod_w * scale), int(prod_h * scale)
    product_resized = product.resize((new_w, new_h), Image.Resampling.LANCZOS)

    # 3. 正方形純白キャンバスを作成
    canvas = Image.new("RGBA", (target_canvas_size, target_canvas_size), (255, 255, 255, 255))

    # 4. 接地シャドウ(コンタクトシャドウ)の生成
    alpha = product_resized.split()[3]
    shadow_height = max(10, int(new_h * 0.08))
    
    # アルファチャンネルを縦方向に縮小して接地マスクを作成
    shadow_mask = alpha.resize((new_w, shadow_height), Image.Resampling.BILINEAR)
    shadow_mask = shadow_mask.filter(ImageFilter.GaussianBlur(radius=15))
    
    # 濃いグレーの半透明レイヤーを作成(不透明度最大35%)
    shadow_layer = Image.new("RGBA", (new_w, shadow_height), (40, 40, 40, 0))
    shadow_layer.putalpha(shadow_mask.point(lambda p: int(p * 0.35)))

    # 5. 各レイヤーをキャンバスに合成
    pos_x = (target_canvas_size - new_w) // 2
    pos_y = (target_canvas_size - new_h) // 2

    # 影を商品の最下部付近に配置
    shadow_y = pos_y + new_h - int(shadow_height * 0.6)
    canvas.paste(shadow_layer, (pos_x, shadow_y), shadow_layer)

    # 商品本体を合成
    canvas.paste(product_resized, (pos_x, pos_y), product_resized)

    # 出力用RGB画像へ変換
    return canvas.convert("RGB")

def run_pipeline(input_path: str, output_path: str):
    with open(input_path, "rb") as f:
        raw_bytes = f.read()

    # ステップ1: クラウドAPIによる透過切り抜き
    cutout_bytes = remove_background(raw_bytes)

    # ステップ2: ローカルでの画像標準化と接地シャドウ合成
    final_img = standardize_product_image(cutout_bytes)

    # ステップ3: 最適化JPEGとして保存
    final_img.save(output_path, "JPEG", quality=90, optimize=True)

5. 運用上のベストプラクティスとコスト削減策

  1. mattingByUrl による転送帯域とI/Oの削減: 登録元画像がすでにS3などのオブジェクトストレージにある場合、mattingByUrl モードを活用して公開URLを渡します。サーバーからの画像再アップロード処理が不要となり、ネットワーク負荷とレイテンシを大幅に削減できます。
  2. 2段階の画像審査ワークフロー: 出品ドラフト作成時は preview=true(0.25クレジット)で処理し、出品承認・本番公開時にフル解像度(1クレジット)で本番処理を実行する設計にすることで、無駄なクレジット消費を防止できます。
  3. 透過PNGマスクの長期保存: APIから取得した透過PNGはアーカイブ用ストレージに保管しておくことを推奨します。将来的に背景色をライトグレーに変更したり、余白比率の規定が変わった場合でも、有料APIを再実行することなくローカル合成スクリプトのみで全商品を再生成できます。

参考文献