1. はじめに:なぜこのアプリを作ったのか
近年、大規模言語モデル (LLM) や画像セグメンテーションモデルの進化は目覚ましいものがあります。
本稿では、Google の生成AI Gemini と 私の前回の記事で使用できる環境を構築したMeta の SAM-3 (Segment Anything Model 3) を連携させ、「ユーザーが関心を持った絵画の特定の領域」に対してAIが専門的な詳細解説を提供する簡易的な Streamlit アプリケーションを作ってみたのでご紹介します。
個人的なポイントは、ユーザーがキーワードで指定した部分を SAM-3 が正確にセグメンテーション(マスキング)し、そのマスク画像を含めて Gemini が解説する、というインタラクティブな深掘り解析を実現した点です。
利用技術スタック
- フロントエンド: Streamlit
- データソース: MET Museum Collection API
- AI (LLM/Vision): Gemini 2.5 Flash (API)
- プロンプトによる画像セグメンテーション: SAM-3
2. アプリの機能概要とデモ
アプリは、ユーザーが選んだパブリックドメインの絵画に対し、以下の4つのステップでインタラクティブな解析を提供します。
構成は以下の通りです。
- app.py:画面表示や各種処理への指示
- ai_service.py:主にAI(GeminiとSAM-3)を使用する機能
- data_service.py:主に絵画データなどを取得する機能
- sam3フォルダ:sam3利用のための各種ファイルが保管
Step 1. 絵画の選択と全体解析
data_service.py が MET API から取得した絵画のギャラリーが表示されます。
作品を選択すると、すぐに get_overall_analysis 関数により Gemini が作品を分析し、ユーザーに提案するマスキングプロンプトの候補を提示します。
Step 2. マスキングキーワード入力と候補の確認
ユーザーがキーワードを入力し、「SAM-3 マスキングプレビュー」ボタンを押すと、ai_service.py の get_sam3_masks 関数が動作します。SAM-3は複数のセグメンテーション候補を生成し、ユーザーは最も適切に領域を特定しているマスクを選びます。
Step 3. 選択領域に対する詳細解説の実行
ユーザーが選択したマスクに対し、「選択したマスクで解説を実行」ボタンを押すと、get_detail_analysis 関数が実行されます。このとき、マスクが適用された画像とプロンプトがGeminiに渡され、AIがその領域に特化した詳細な解説を生成します。
本稿執筆がギリギリになってしまったため、GeminiのAPI制限で肝心の最後の結果の部分が出力できなかったため、イメージだけで恐縮ですが以下のような解説を見ることができます。
エル・グレコがイタリア滞在中に制作した《盲目を治すキリストの奇跡》における建物の描写は、彼の画業における重要な転換期を象徴しており、その技法と時代背景に深い意味が込められています。
1. 技法:複雑な遠近法と建築描写の習熟
この作品の背景に描かれている建物群は、エル・グレコがヴェネツィアとローマで学んだ高度なイタリア美術の技法を駆使して描かれています。
① 線遠近法(リニア・パースペクティブ)の活用
- イタリア・ルネサンスで確立された線遠近法が積極的に用いられ、画面に深い奥行きと構造的な秩序を与えています。
- 群衆のドラマが展開される舞台として、建物が明確な幾何学的空間を作り出しています。
② 建築的要素の混在と複雑な構成
- 古典的な古代ローマ建築の柱やアーチ、そして彼が滞在した16世紀当時のルネサンス様式の建物が混在して描かれています。
- 特にパルマ国立美術館に所蔵されているバージョンでは、線遠近法の消失点に古代ローマのディオクレティアヌス帝の浴場跡などの遺跡が描かれていると指摘されており、これは画家がローマで実際に遺跡を研究し、それを構図に取り入れたことを示しています。
- この複雑な建築描写は、画家がイタリアで培った技術の高さと、空間構成における実験的な試みであったと考えられます。
2. 時代背景と意味合い
建物の描写は、単なる背景ではなく、当時の芸術的・精神的な文脈を反映しています。
① イタリア美術の吸収と「習作」
- クレタ島出身のエル・グレコは、イタリアでヴェネツィア派(ティツィアーノ、ティントレットなど)の鮮やかな色彩や光の技法と、ローマの古典的なデッサンや構図法を学びました。
- この作品は、多くの人物を屋外に配置し、遠近法を用いて複雑な都市空間を描くという点で、彼がイタリアの巨匠たちの手法を吸収し、自らのものとするための**「習作」あるいは「実験」**の場でした。
② マニエリスムへの移行
- 彼は後のトレド時代のような、極端に引き伸ばされた人物像や幻想的な色彩を特徴とするマニエリスム的な画風に移行する過渡期にありました。
- この時期の建築描写は、ルネサンスの調和的な遠近法を踏襲しつつも、後のマニエリスム特有の「人工的」「不均衡」な空間構成の兆候がすでに現れていると見ることもできます。
③ 聖書の奇跡の「舞台」設定
- 建物は、キリストの奇跡が起こる場所が歴史的・現実的な都市空間であることを示しつつ、その威厳を高める「舞台装置」の役割を果たしています。
- 当時の対抗宗教改革の文脈では、「盲目」を「不信仰」と捉え、「治癒」を「真の信仰への導き」と解釈したため、この奇跡の場面を説得力のある、公的な場で展開する必要がありました。堂々とした建築物は、そのドラマにふさわしい荘厳な背景を与えています。
3. コード解説:SAM-3 と Gemini Vision の統合
一部とはなりますがアプリケーションの中核である ai_service.py における、AIモデルの連携ロジックを解説します。
3.1. 全体解析:プロンプト候補の生成 (get_overall_analysis)
Gemini Vision に画像全体を分析させ、ユーザーが何に興味を持つかを事前に予測し、専門的な視点からマスキングに適したキーワードを抽出します。
# ai_service.py より抜粋
def get_overall_analysis(image: Image.Image, painting_title: str, painting_artist: str) -> list[str]:
# ... 中略 ...
prompt = f"""
あなたは美術史の専門家です。以下の絵画の主要な構成要素を抽出し、箇条書きでリスト化してください。
絵画のタイトル: {painting_title}, 作家: {painting_artist}
各リスト項目は、SAM-3(セグメンテーションモデル)が領域を特定しやすい具体的な物体名や描写表現にしてください。
回答は、純粋な箇条書きのリスト形式のみを英語で出力してください。
"""
response = gemini_client.models.generate_content(
model='gemini-2.5-flash',
contents=[prompt, image] # 画像とテキストを同時に入力
)
# ...
return cleaned_list
3.2. 詳細解説:マスク画像による焦点の誘導 (get_detail_analysis)
**マスク適用後の画像 (masked_image)**をマルチモーダル入力としてGeminiに渡すことで、AIの焦点を強制的にユーザーの関心領域に絞り込み、より具体的で正確な解説を引き出します。
# ai_service.py より抜粋
def get_detail_analysis(image: Image.Image, painting_title: str, painting_artist: str, detail_prompt: str, masked_image: Image.Image) -> str:
# ...
prompt = f"""
あなたは美術史の専門家です。目の前の画像は、元の絵画「{painting_title}」by「{painting_artist}」から、ユーザーが興味を持った要素「{detail_prompt}」を特定して切り出したり、ハイライトしたりした領域です。
この特定された領域について、専門的な詳細解説を日本語で記述してください。
解説には以下の点を含めてください。
1. **表現技法**: その領域がどのような筆致、色彩、明暗で描かれているか。
2. **歴史的・象徴的意味**: その要素が当時の美術史や文化、またはこの絵画全体の物語においてどのような意味を持つか。
3. **作品全体との関係**
"""
# マスク画像とプロンプトを渡すことで、AIの焦点を誘導
response = gemini_client.models.generate_content(
model='gemini-2.5-flash',
contents=[prompt, masked_image]
)
return response.text
3.3. SAM-3 によるマスキングの実装 (get_sam3_masks)
今回のアプリの中でSAM-3は、テキストプロンプトを基にセグメンテーション(物体領域の特定)を行う役割を担います。
# ai_service.py より抜粋 (SAM-3 の推論部分)
def get_sam3_masks(image: Image.Image, prompts: str) -> list[tuple[Image.Image, str]]:
# ... モデル初期化 ...
processor = Sam3Processor(model, confidence_threshold=0.1)
inference_state = processor.set_image(image)
# プロンプトに基づいて推論を実行し、マスク結果を可視化
inference_state = processor.set_text_prompt(state=inference_state, prompt=prompt)
img_result = get_mask(image, inference_state) # マスク適用後の画像を生成
masked_results.append((img_result, prompt))
return masked_results
4. データと著作権への配慮 (data_service.py)
このアプリでは、データソースとして MET Museum Collection API を利用し、著作権に最大限配慮しています。
パブリックドメイン限定: 検索APIのパラメータに "isPublicDomain": "true" を指定することで、著作権が失効した作品のみを検索対象としています。
これにより、作品画像の利用における法的リスクを排除しています。
5. まとめ
本稿で紹介したアプリケーションは、Gemini Vision と SAM-3 という最新の技術を組み合わせ、従来の静的な情報提供を超えたユーザー中心の動的な美術体験を簡単に構築できることが確認できました。
ご意見・改善点などあればぜひコメントください!