はじめに
11月にリリースされ、その驚異的な性能が話題になっているGemini 3 Pro Preview (aka Nano Banana Pro)ですが、Google Gen AI SDKからも呼び出してプログラマブルに利用することができます。
公式ドキュメントでクックブックとして提供されているGoogle Colabノートブックを和訳、加筆したので、ユースケースをかいつまんで紹介したいと思います。
↓ノートブックの全文は以下。
実際に動作させるには従量課金が発生するのでご注意ください。
※ノートブックを見れば動作結果は確認できます。
セットアップ
SDKのインストール
pip install -U -q "google-genai>=1.40.0" # アスペクト比に対応するために必要な最低バージョン
クライアントの初期化
Google AI StudioのAPIを使う場合
from google import genai
from google.genai import types
# https://aistudio.google.com/api-keys
client = genai.Client(api_key=GOOGLE_API_KEY)
Vertex AIを利用する場合
from google.colab import auth
# Google アカウントで認証
auth.authenticate_user()
from google import genai
from google.genai import types
PROJECT_ID = 'your-project' # @param {type:'string'}
LOCATION = 'global' # @param {type:'string'}
client = genai.Client(
vertexai=True, project=PROJECT_ID, location=LOCATION
)
モデルの定義
MODEL_ID = "gemini-2.5-flash-image"
PRO_MODEL_ID = "gemini-3-pro-image-preview"
ユーティリティ関数の定義
from IPython.display import display, Markdown
import pathlib
# すべてのパーツをループし、テキストまたは画像として表示する
def display_response(response):
for part in response.parts:
if part.thought: # 思考内容(thought)は表示しない
continue
if part.text:
display(Markdown(part.text))
elif image := part.as_image():
image.show()
# 画像を保存する
# 複数画像がある場合は、最後の画像のみが保存される
def save_image(response, path):
for part in response.parts:
if image := part.as_image():
image.save(path)
Nano Banana Proのユースケース
思考(thoughts)を確認する
Nano Banana Proは思考モデルのため思考オプションが利用できます。
prompt = "バズりそうな、少し風変わりだけれどリアルな画像を作成してください" # @param {type:"string"}
aspect_ratio = "16:9" # @param ["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"]
response = client.models.generate_content(
model=PRO_MODEL_ID,
contents=prompt,
config=types.GenerateContentConfig(
response_modalities=['Text', 'Image'],
image_config=types.ImageConfig(
aspect_ratio=aspect_ratio,
),
thinking_config=types.ThinkingConfig(
include_thoughts=True # 思考(thoughts)を確認したい場合は必ず指定する
)
)
)
display_response(response)
save_image(response, 'viral.png')
for part in response.parts:
if part.thought: # 思考(thought)のパートをチェック
if part.text:
display(Markdown(part.text)) # 思考テキストを表示
elif image := part.as_image():
# image.show() # 多くの場合、出力と同じ画像なので表示は省略
print("IMAGE")
確認した思考(日本語に翻訳済み)。
超現実的なコンセプトの探求
私は現在、シュールな要素と日常の風景をブレンドして、興味深いビジュアルを作成することに重点を置いています。私は東京の満員電車、特に山手線に乗っている年配の日本人男性を想像しています。重要な珍しい要素は、列車の天井に届きそうなほど巨大な色鮮やかなキノコで、彼はそれをバックパックのように背負っています。このシーンには乗客のさまざまな反応が記録され、キノコから発せられる胞子や男性の奇妙な服装などの詳細が組み込まれます。
奇妙な概念の探求
現在は日常風景とシュールな要素の融合に注力しています。私は日本の通勤電車のようなありふれた環境と、光るキノコを持った老人のような風変わりな人物を並べて実験してきました。非日常と現実のバランスを目指し、周囲の人々の微妙な反応を画像に捉えようとしています。
Google検索によるグラウンディング
prompt = "東京の今後5日間の天気予報を、シンプルでモダンな天気チャートとして日本語で可視化してください。さらに、各日に私が何を着るべきかの視覚的な提案も追加してください。" # @param {type:"string"}
aspect_ratio = "16:9" # @param ["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"]
response = client.models.generate_content(
model=PRO_MODEL_ID,
contents=prompt,
config=types.GenerateContentConfig(
response_modalities=['Text', 'Image'], # 現時点では grounding と画像のみの組み合わせは動作しない
image_config=types.ImageConfig(
aspect_ratio=aspect_ratio,
),
tools=[{"google_search": {}}]
)
)
display_response(response)
save_image(response, 'weather.png')
4K画像の生成
prompt = "四季のすべてを体験しているオークの木の写真を作成してください" # @param {type:"string"}
aspect_ratio = "1:1" # @param ["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"]
resolution = "4K" # @param ["1K", "2K", "4K"]
response = client.models.generate_content(
model=PRO_MODEL_ID,
contents=prompt,
config=types.GenerateContentConfig(
response_modalities=['Text', 'Image'],
image_config=types.ImageConfig(
aspect_ratio=aspect_ratio,
image_size=resolution
)
)
)
display_response(response)
※サイズが大きすぎてQiitaにアップロードできず
多言語で画像の生成・翻訳
chat = client.chats.create(
model=PRO_MODEL_ID,
config=types.GenerateContentConfig(
response_modalities=['Text', 'Image'],
tools=[{"google_search": {}}]
)
)
message = "アインシュタインの一般相対性理論を、中学1年生向けにスペイン語でわかりやすく説明するインフォグラフィックを作成してください" # @param {type:"string"}
aspect_ratio = "16:9" # @param ["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"]
response = chat.send_message(
message,
config=types.GenerateContentConfig(
image_config=types.ImageConfig(
aspect_ratio=aspect_ratio,
)
)
)
display_response(response)
save_image(response, "relativity_ES.png")
message = "このインフォグラフィックを日本語に翻訳し、その他の要素はすべて同じままにしてください" # @param {type:"string"}
resolution = "2K" # @param ["1K", "2K", "4K"]
response = chat.send_message(
message,
config=types.GenerateContentConfig(
image_config=types.ImageConfig(
image_size=resolution
)
)
)
display_response(response)
save_image(response, "relativity_JP.png")
最大14枚の画像を合成
!wget "https://storage.googleapis.com/generativeai-downloads/images/sweets.png" -O "sweets.png" -q
!wget "https://storage.googleapis.com/generativeai-downloads/images/car.png" -O "car.png" -q
!wget "https://storage.googleapis.com/generativeai-downloads/images/rabbit.png" -O "rabbit.png" -q
!wget "https://storage.googleapis.com/generativeai-downloads/images/spartan.png" -O "spartan.png" -q
!wget "https://storage.googleapis.com/generativeai-downloads/images/cactus.png" -O "cactus.png" -q
!wget "https://storage.googleapis.com/generativeai-downloads/images/cards.png" -O "cards.png" -q
prompt = "娘の寝室にあるこれらのアイテムを使って、マーケティング用の写真撮影風画像を作成してください。背景は無視し、アイテムそのものにフォーカスしてください。" # @param {type:"string"}
aspect_ratio = "5:4" # @param ["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"]
resolution = "1K" # @param ["1K", "2K", "4K"]
response = client.models.generate_content(
model=PRO_MODEL_ID,
contents=[
prompt,
PIL.Image.open('sweets.png'),
PIL.Image.open('car.png'),
PIL.Image.open('rabbit.png'),
PIL.Image.open('spartan.png'),
PIL.Image.open('cactus.png'),
PIL.Image.open('cards.png'),
],
config=types.GenerateContentConfig(
response_modalities=['Text', 'Image'],
image_config=types.ImageConfig(
aspect_ratio=aspect_ratio,
image_size=resolution
),
)
)
display_response(response)
スプライトシート
text_prompt = "ドローンに乗って踊る女性のスプライトシート。3x3グリッド、シーケンス、フレームアニメーション、正方形のアスペクト比。添付の参考画像の構造に厳密に従ってください。" # @param ["ジャンプ動作のイラストによるスプライトシートを作成してください。3x3 グリッドで、白背景、連続したフレーム、フレームごとのアニメーション、正方形アスペクト比です。添付した参考画像とまったく同じ構造に従ってください。","ドローンに乗って踊る女性のスプライトシート。3x3グリッド、シーケンス、フレームアニメーション、正方形のアスペクト比。添付の参考画像の構造に厳密に従ってください。","3x3グリッド、白背景、シーケンス、フレームアニメーション、正方形アスペクト比の「Oh No」のスプライトシート。添付の参考画像の構造に忠実に従ってください。"] {"allow-input":true}
!wget "https://storage.googleapis.com/generativeai-downloads/images/grid_3x3_1024.png" -O "grid_3x3_1024.png" -q
response = client.models.generate_content(
model=PRO_MODEL_ID,
contents=[
text_prompt,
PIL.Image.open("grid_3x3_1024.png")
],
config=types.GenerateContentConfig(
image_config=types.ImageConfig(
aspect_ratio="1:1",
),
)
)
display_response(response)
save_image(response, 'sprites.png')
GIFに変換
# @title
import PIL
from IPython.display import display, Image
image = PIL.Image.open('sprites.png')
total_width, total_height = image.size
# 有効なスプライト全体の幅・高さ(外枠 1px を除いた値)
effective_width = total_width - 2
effective_height = total_height - 2
# 3x3 グリッドに基づく各フレームの幅・高さ
frame_width = effective_width // 3
frame_height = effective_height // 3
frames = []
for row in range(3):
for col in range(3):
# フレームの切り出し位置(左上と右下)を計算
left = col * (frame_width + 1)
upper = row * (frame_height + 1)
right = left + frame_width
lower = upper + frame_height
cropped_frame = image.crop((left, upper, right, lower))
frames.append(cropped_frame)
# GIF として保存
frames[0].save(
'sprite.gif',
save_all=True,
append_images=frames[1:],
duration=200, # 各フレームの表示時間(ミリ秒)
loop=0 # 無限ループ
)
# 推奨されている方式で GIF をバイトとして読み込み表示
display(Image(data=open('sprite.gif','rb').read()))
おわりに
Nano Banana Proの登場で、これまで難しかった元画像を忠実に合成したり、日本語での文字入れまで高精度でできるようになりました。
また、思考モデルであるため曖昧な指示から推論して最善のアウトプットを引き出す能力も上がっていて、想像したことは何でも画像にできるAIまで一気に成長しました。
今後のさらなる進化や動画モデルへの適用も楽しみです。
おまけ
GitHubのAwesome-Nano-Banana-imagesリポジトリでもたくさんのユースケースが紹介されています。






