Gemini Nano Banana Proで背景透過した画像を出力したい
初めに
この記事はCommune Developers Advent Calendar 2025の2日目の記事です
Gemini Nano Banana Pro
画像を生成できるAI
Gemini Nano Banana Proは画像を生成できるAIモデルです。
前回発表されたGemini Nano Banana(gemini-2.5-flash-image)を驚異的に上回る品質レベルで画像を出力することができ、各業界への適用が期待されています。
今回は、Gemini Nano Banana Proで背景透過した画像を出力する手法を紹介していきます。
前提
Gemini Nano Banana Proに対して「透明な背景で画像を生成して(Transparent background)」とプロンプトで指示した時、アルファチャンネル付きのPNG画像が出力されることを期待します。
しかし、実際に出力されるのは白と黒の市松模様の背景が出力されるだけで実際に背景透過処理はされていません。

対してOpenAI(ChatGPT)では背景透過画像の生成が可能です。

なぜ透過画像が生成できないのか
個人の完全な推測になります。
Gemini Nano Banana Proの場合は、ピクセルのRGB値(赤・緑・青)を予測するように訓練されており、アルファチャンネル(透明度)は訓練データに含まれていないか、モデルアーキテクチャがRGBA出力に対応していないのは、と考えています。
そもそも「透明」というのをAIに学習させることが難しいのではないかと考えています。
「透明 = 何も描かない」→ 白や灰色で埋める
「透明 = チェッカーパターン」→ 市松模様を描画
「透明 = 背景なし」→ 被写体だけを描くが背景色は残る
よって、Gemini Nano Banana Pro は学習した内容を忠実に再現しOpenAIは別の学習方法を用いている or 出力した画像に対して内蔵のセグメンテーションモデルで被写体を分離、アルファチャンネル(透明度)を後付けしているのではと推測しています。
グリーンバック出力戦略
クロマキー合成
映画やテレビの制作現場では、緑色(または青色)の背景の前で撮影し、後から背景を差し替える「クロマキー合成」という技術が使われています。この技術をGemini Nano Banana Proに応用します。

Gemini Nano Banana Proに対して、以下のようなプロンプトを使用します:
「[被写体の説明]を生成してください。
重要な指示:
- 背景は完全に均一な明るい緑色(#00FF00、クロマキーグリーン)で塗りつぶしてください
- 被写体には緑色を一切使用しないでください
- 被写体と背景の境界は明確にしてください
- 背景にグラデーションや影を入れないでください

出力された画像に対してクロマキー処理をして出力します。
実際にはGemini APIを使用して画像を生成/取得した後にクロマキー処理を行います。
画像処理手順
1. 画像を読み込む
2. BGR → HSV色空間に変換
3. 緑色の範囲を定義してマスクを作成
4. マスクを反転(被写体部分を取得)
5. アルファチャンネルを設定
6. 透過PNGとして保存
画像処理にはpythonを使用します。
必要なライブラリを事前にインストールします。
pip install opencv-python numpy pillow
"""
入力画像(グリーンバックの画像)を "input_greenback.png" として準備
"""
import cv2
import numpy as np
from PIL import Image
def remove_green_background(input_path: str, output_path: str) -> None:
# 画像を読み込み(BGR形式)
img = cv2.imread(input_path)
if img is None:
raise FileNotFoundError(f"画像が見つかりません: {input_path}")
# BGR → HSV変換
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 緑色の範囲を定義(HSV)
lower_green = np.array([40, 150, 100])
upper_green = np.array([80, 255, 255])
# 緑色部分のマスクを作成
green_mask = cv2.inRange(hsv, lower_green, upper_green)
# マスクを反転
subject_mask = cv2.bitwise_not(green_mask)
# BGR → BGRA に変換
img_bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# アルファチャンネルにマスクを適用
img_bgra[:, :, 3] = subject_mask
# 保存
cv2.imwrite(output_path, img_bgra)
print(f"透過画像を保存しました: {output_path}")
# 使用例
if __name__ == "__main__":
remove_green_background("input_greenback.png", "output_transparent.png")
出力結果がこちらになります。

透明処理ができるようになりましたが、生成物と透明部分の境目に緑が残っているので更に形態学処理・フェザリング・デスピル処理を追加していきましょう。
import cv2
import numpy as np
from PIL import Image
def remove_green_background(input_path: str, output_path: str) -> None:
# 画像を読み込み(BGR形式)
img = cv2.imread(input_path)
if img is None:
raise FileNotFoundError(f"画像が見つかりません: {input_path}")
# BGR → HSV変換
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# === 背景の緑色を検出 ===
lower_green = np.array([40, 150, 100])
upper_green = np.array([80, 255, 255])
green_mask = cv2.inRange(hsv, lower_green, upper_green)
# === 【追加】エッジ部分の検出(緩めの条件) ===
lower_edge = np.array([35, 80, 80])
upper_edge = np.array([85, 255, 255])
edge_mask = cv2.inRange(hsv, lower_edge, upper_edge)
# エッジ領域 = 緩い条件 - 厳しい条件
edge_only_mask = cv2.bitwise_and(edge_mask, cv2.bitwise_not(green_mask))
# マスクを反転(被写体部分)
subject_mask = cv2.bitwise_not(edge_mask)
# === 【追加】形態学処理(エッジを綺麗に) ===
kernel = np.ones((3, 3), np.uint8)
subject_mask = cv2.erode(subject_mask, kernel, iterations=1)
subject_mask = cv2.dilate(subject_mask, kernel, iterations=2)
# === 【追加】フェザリング(境界をなめらかに) ===
subject_mask = cv2.GaussianBlur(subject_mask, (5, 5), 0)
# BGR → BGRA に変換
img_bgra = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# === 【追加】エッジ部分のデスピル処理(緑かぶり除去) ===
b = img_bgra[:, :, 0].astype(np.float32)
g = img_bgra[:, :, 1].astype(np.float32)
r = img_bgra[:, :, 2].astype(np.float32)
# エッジ部分で緑が過剰な場合のみデスピル
edge_pixels = edge_only_mask > 0
max_rb = np.maximum(r, b)
green_excess = g - max_rb
despill_mask = edge_pixels & (green_excess > 20)
despill_amount = green_excess * 0.7
g[despill_mask] = g[despill_mask] - despill_amount[despill_mask]
img_bgra[:, :, 1] = np.clip(g, 0, 255).astype(np.uint8)
# アルファチャンネルにマスクを適用
img_bgra[:, :, 3] = subject_mask
# 保存
cv2.imwrite(output_path, img_bgra)
print(f"透過画像を保存しました: {output_path}")
# 使用例
if __name__ == "__main__":
remove_green_background("input_greenback.png", "output_transparent.png")

追加した処理の説明
| 処理 | 効果 |
|---|---|
| エッジ検出 | 境界付近の緑がかったピクセルを特定 |
| 形態学処理 | 緑フリンジを削り、被写体を復元 |
| フェザリング | 境界を滑らかにして自然な仕上がりに |
| デスピルエッジ | 部分の緑かぶりを除去 |
成果物
GradioでGemini Nano Banana Proを使用してそのまま透過させるツールを作りました。
下のリポジトリをクローンいただければそのまま使用できます。
機能1: グリーンバック除去機能

機能2 Gemini Nano Banana Proで生成した画像から自動的に背景を除去する機能
(Gemini API Keyが必要です https://zenn.dev/ma_ro/articles/49b67565462299)

機能3 既存の画像を背景除去して出力機能
元画像

元画像を入力してGemini Nano Bananaにグリーンバック処理→背景透過処理

環境構築についてはREADMEに、使用方法についてはGradioを開いた後のフロント部分に記載があります。
終わり
それでは次回のCommune Developers Advent Calendar 2025もお楽しみに
Discussion