👗

バーチャル試着、FASHN AI + nano banana pro が最強説

に公開
7

はじめに

どうも!
株式会社エクスプラザのhyodoです!

弊社アドベントカレンダー22日目の投稿となります!

AIバーチャル試着、どれも微妙じゃないです?

ECサイトで見つけた服、「自分が着たらどんな感じだろう」と思って、AIを利用して着せ替えを試したことがある人は多いと思います。

例えば、下記のように試着させようとして、画像生成AIに実行させると、、、

だいたいこうなります。

  • 切り貼りしたみたいに合成感が出る
  • 対象以外の服が着せられてる
  • 顔が別人
  • 服の質感が元画像と違う
    などなど…

これを、FASHN AInano banana proを組み合わせる方法で解消できたので、紹介させていただければと思います。

ざっくり手順をお伝えすると、

Step 1: FASHN AI → シームレスに服を着せる
Step 2: Gemini  → 元の服の質感を転写する

です。

この手順で先ほどの人物と服を合成させると、

このように自然に試着したようになります。

1つのAIだけだと難しい

一般的な画像生成AI

人物画像と服の画像を渡して「この人にこの服を着せて」と指示すると、全然違う人が全然違う服を着ている画像が出てきます。顔が変わる、体型が変わる、服のデザインが勝手にアレンジされる。といった事象が発生します。

Virtual Try-On専用のAI

FASHN AIのようなVirtual Try-On専用AIは、合成感がなくて自然に仕上がります。顔も体型もちゃんと保持されます。

ただ、元の服の「生地感」が少し失われます。光沢やシワの細かさが物足りません。写真としては綺麗ですが、元の服を見比べると「なんか違う」という感じがします。

2段階アプローチ

そこで考えたのが2段階アプローチです。

  1. まずFASHNで合成感のない着せ替えをする
  2. その結果に対して、Geminiで元の服の質感を転写する

これで自然な合成とリアルな質感の両方が手に入ります。

実装

必要なもの

  • FASHN AI APIキー(fashn.aiで取得)
  • Gemini APIキー(Google AI Studioで取得、無料枠あり)
  • Python 3.9以上
pip install pillow requests google-generativeai

Step 1: FASHN AIで着せ替え

import base64
import time
from io import BytesIO
from PIL import Image
import requests


class FashnTryOn:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://api.fashn.ai/v1"

    def try_on(self, person_image: Image.Image, garment_image: Image.Image) -> Image.Image:
        person_b64 = self._to_base64(person_image)
        garment_b64 = self._to_base64(garment_image)

        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}",
        }

        payload = {
            "model_name": "tryon-v1.6",
            "inputs": {
                "model_image": person_b64,
                "garment_image": garment_b64,
                "category": "auto",
                "mode": "quality",
                "segmentation_free": True,
                "num_samples": 1,
                "output_format": "png",
            },
        }

        resp = requests.post(f"{self.base_url}/run", json=payload, headers=headers)
        job_id = resp.json()["id"]

        while True:
            status = requests.get(
                f"{self.base_url}/status/{job_id}",
                headers={"Authorization": f"Bearer {self.api_key}"}
            ).json()

            if status["status"] == "completed":
                img_url = status["output"][0]
                img_data = requests.get(img_url).content
                return Image.open(BytesIO(img_data))

            if status["status"] == "failed":
                raise Exception("FASHN処理失敗")

            time.sleep(3)

    def _to_base64(self, image: Image.Image) -> str:
        if image.mode == 'RGBA':
            bg = Image.new('RGB', image.size, (255, 255, 255))
            bg.paste(image, mask=image.split()[3])
            image = bg

        buffer = BytesIO()
        image.save(buffer, format='PNG')
        b64 = base64.b64encode(buffer.getvalue()).decode()
        return f"data:image/png;base64,{b64}"

FASHNのポイントはmode: "quality"です。これで最高品質のモードになります(処理時間は約19秒)。顔と体型が完全に保持されて、合成感もほとんどありません。

Step 2: Geminiで質感強化

FASHNの結果に対して、元の服の質感を転写します。

import google.generativeai as genai
from io import BytesIO
from PIL import Image


class TextureEnhancer:
    def __init__(self, api_key: str):
        genai.configure(api_key=api_key)

    def enhance(self, tryon_result: Image.Image, original_garment: Image.Image) -> Image.Image:
        model = genai.GenerativeModel("gemini-3-pro-image-preview")

        tryon_result = self._resize(tryon_result, 1024)
        original_garment = self._resize(original_garment, 1024)

        prompt = """
IMAGE 1: 試着済みの画像(人物が服を着ている状態)
IMAGE 2: 元の服の画像

IMAGE 1の服の質感を、IMAGE 2に合わせて強化してください。

変えてはいけないもの:
- 人物の顔、体型、ポーズ
- 背景
- 服のシルエット

強化するもの:
- 生地のテクスチャ(織り目、糸の質感)
- 光沢感またはマット感
- シワや陰影のリアルさ
"""

        response = model.generate_content([
            tryon_result.convert('RGB'),
            original_garment.convert('RGB'),
            prompt
        ])

        for candidate in response.candidates:
            for part in candidate.content.parts:
                if hasattr(part, 'inline_data') and part.inline_data:
                    return Image.open(BytesIO(part.inline_data.data))

        return tryon_result

    def _resize(self, image: Image.Image, max_size: int) -> Image.Image:
        if max(image.size) > max_size:
            ratio = max_size / max(image.size)
            new_size = tuple(int(d * ratio) for d in image.size)
            return image.resize(new_size, Image.Resampling.LANCZOS)
        return image

ここで大事なのは、元の服の画像を「参照」として一緒に渡すことです。Geminiはマルチモーダルなので、2つの画像を見比べて質感を転写してくれます。

プロンプトで「変えてはいけないもの」を明示しておくと、人物や背景を変えずに質感だけを強化してくれます。

2つを組み合わせる

def perfect_tryon(person_path: str, garment_path: str) -> Image.Image:
    person = Image.open(person_path)
    garment = Image.open(garment_path)

    print("Step 1: FASHN AI で着せ替え中...")
    fashn = FashnTryOn(api_key="YOUR_FASHN_API_KEY")
    tryon_result = fashn.try_on(person, garment)

    print("Step 2: Gemini で質感強化中...")
    enhancer = TextureEnhancer(api_key="YOUR_GEMINI_API_KEY")
    final_result = enhancer.enhance(tryon_result, garment)

    return final_result


result = perfect_tryon("person.jpg", "shirt.png")
result.save("result.png")

なぜこの組み合わせがうまくいくのか

FASHNは合成の自然さに特化しています。服を人物に「溶け込ませる」技術が優れていて、切り貼り感が出ません。ただし、その過程で元の服の細かいテクスチャが少し失われます。

一方、Geminiは画像理解と画像生成の両方ができます。2つの画像を渡して「こっちの質感をこっちに適用して」と指示すれば、それをやってくれます。ただし、Gemini単体で着せ替えをさせると合成感が出たり、人物が変わったりします。

つまり、それぞれ得意分野が違います。

  • FASHN:合成の自然さ、ID保持
  • Gemini:質感の再現、細部の強化

2つを組み合わせることで、弱点を補い合えます。

入力画像のコツ

人物画像は全身が写っていて、正面向きのものが良いです。腕を広げすぎていたり、複雑なポーズだと精度が落ちます。

服の画像は平置き(テーブルに置いた状態)がベストです。白背景でシワがない状態だと認識精度が上がります。モデルが着用している写真でも動きますが、平置きの方が安定します。

処理時間とコスト

処理時間はFASHNのqualityモードで約20秒、Geminiの質感強化で約5〜10秒です。合計で約30秒弱かかります。

FASHNは従量課金、Geminiは無料枠があります。個人で試す分にはGeminiの無料枠で十分足ります。

まとめ

  • FASHNで合成感のない着せ替えをする
  • Geminiで元の服の質感を転写する
  • 2段階でやることで、自然さと質感の両方を実現できる

「AIっぽい」着せ替え結果に不満があった方は、ぜひこの方法を試してみてください。


参考リンク

7
株式会社エクスプラザ

Discussion

ログインするとコメントできます
7