コムセント 技術情報

  1. TOP
  2. コムセント 技術情報
  3. Geminiを利用した画像へのIPTCキーワード(タグ)の埋め込み

Geminiを利用した画像へのIPTCキーワード(タグ)の埋め込み

JPEG画像などには、Exif情報にIPTCキーワードを埋め込むことができ、画像編集ソフトや、画像ビューワーなどで、キーワードを利用した検索が可能になります。大量に画像がある場合、ファイル名だけで特定の画像を探すのは大変ですが、キーワードを付けておくことで、特定の画像を簡単に見つけることができるようになります。

しかし、画像編集ソフトなどでは、現時点では自動的に画像に写っているものを識別してキーワードを埋め込む、という機能は提供されていません。クラウドなどでは提供されているサービスも多いですが、大量の画像となるとクラウドにアップロードして、探して利用する、というのはケースとして現実的では無いケースもあります。

ローカル環境で、画像に写っているものを識別し、IPTCキーワードとして埋め込むことができれば、利便性が高まるでしょう。マルチモーダル対応の生成AIであれば、画像を解析して、キーワードを生成することができるでしょう。

今回は、Gemini2.0を利用して、画像に対しIPTCキーワードを埋め込む方法を説明します。

Gemini2.0を利用する理由

マルチモーダル対応の生成AIであれば、どれでも良いので、OpenAIのAPIを使っても、Cloude3のAPIを使ってももちろんOKなのですが、Geminiであれば、Googleに登録することで制限はありますが無償で利用できます。時間は掛かりますが、無償で利用できるのは大きなメリットです。

また、GeminiはGoogleが開発しているため、Googleの画像検索エンジンと連携しているため、画像に対するキーワードの精度が高いと考えられます(確証はありませんが)。

GeminiAPIを無償で利用する

https://aistudio.google.com/へアクセスし、Googleアカウントでログインします。

「利用規約・追加利用規約・プライバシーポリシー」を確認し、同意してからGet API Keyボタンをクリックし、「APIキーを作成」をクリックします。APIキーを作成ボタンを押すと、APIキーを作成モーダルが出てくるので、「既存のGoogleCloudプロジェクトからプロジェクトを選択します」からプロジェクトを選択し、「既存のプロジェクトでAPIキーを作成」を選択します。

APIキーが発行されるので、コピーボタンを押してコピーしておきます。

APIキーを発行すると、APIキーは以下の通りです、というところに表示がされます。ここで、プランがFreeとなっていることを確認しておきます。(しばらく時間が掛かることがあります)

IPTCキーワードの埋め込み

IPTCキーワードの生成はAPIを通じた生成AIで行ないますが、画像の取得、APIを通じて画像を渡す、結果を受け取る部分はPythonでコードを作成します。

画像の取得などはPythonの標準的なライブラリーで可能ですが、IPTCキーワードの埋め込みだけはPythonの標準ライブラリーではできないため、exiftoolを利用します。

exiftoolは、画像のメタデータを操作するためのツールで、IPTCキーワードの埋め込みも可能です。https://exiftool.org/からダウンロードできます。Windows版、mac版があるので、環境に合わせて選択し、ダウンロードしておきます。Windowsの場合、ダウンロードしたら、解凍して、exiftool(-k).exeをexiftool.exeにリネームしておきます。フォルダーごと適当な場所に配置し、パスを通しておきます。

パスを通す方法

例えば、exiftoolフォルダーをC:ドライブの直下に配置した場合、「設定」→「システム」→「バージョン情報」→「システムの詳細設定」→「詳細設定」タブ→「環境変数」を選択し、「システム環境変数」の「Path」を選択して、「編集」をクリックします。「新規」ボタンをクリックして、C:\exiftoolを追加します。これで、exiftool.exeをコマンド名だけで実行できます。

Pythonコードの作成

Pythonを実行するにはPython本体が必要なので、Pythonが入っていない環境であれば、インストールしておきます。

Pythonのインストールは、https://www.python.org/downloads/からダウンロードしてインストールします。Windows環境ではインストール時に「Add Python to PATH」にチェックを入れておくと、コマンド名だけでPythonを実行できるようになりますので、チェックを入れておきます(デフォルトでチェックが入っているはずですが、確認しておきます)。

今回はいくつかのライブラリーを利用するので、pipでインストールしておきます。

ターミナルを開いて、以下のコマンドを実行します。

pip install google.generativeai Pillow

インストールが完了したら以下のPythonコードを記入します。

import google.generativeai as genai
import subprocess
from PIL import Image
import os
import sys
import time
import configparser

# Gemini APIキーを設定
genai.configure(api_key="") # ここにコピーしたAPIキーを入力

# Geminiモデルを初期化
model = genai.GenerativeModel('gemini-2.0-flash') # 別モデルを指定することも可能

i = 0
error_count = 0

def analyze_image_and_embed_iptc_keywords(image_path,filename,folder_path,current_file_count):
    try:
        with Image.open(image_path) as img:
            response = model.generate_content([
                "この画像に写っているものを一番適切なものから順にキーワードとして抽出してください。キーワードは日本語で表記してください。キーワードのみを抽出し、余分な言葉やハイフン、・などの記号、箇条書きや箇条書きの数字は付け足さないでください。もし画像の写っているものが明確では無い場合は、画像の色と印象をキーワードとして取り上げてください。ただし、キーワードの総合計の文字数は20文字以内にしてください。",img
            ])
            keywords_str = response.text
            keywords = keywords_str.split('\n')
            cleaned_keywords = [keyword.replace('* ', '').replace('- ','').replace('・ ','').replace('・','').replace('、 ',',').replace('、',',').strip() for keyword in keywords if keyword.strip()]
        keywords_csv = ','.join(cleaned_keywords)
        print(f"{keywords_csv}")
        subprocess.run([
            'exiftool',
            '-overwrite_original_in_place',
            '-charset', 'iptc=utf8',
            f'-IPTC:Keywords={keywords_csv}',
            image_path
        ], check=True)
        print(f"IPTCキーワードが {image_path} に埋め込まれました。")
        config = configparser.ConfigParser()
        config['DEFAULT'] = {
            'current_file': str(current_file_count),
            'filename': filename,
            'folder_path': folder_path
        }
        # 設定ファイルに書き込み
        with open('config.ini', 'w', encoding='utf-8') as configfile:
            config.write(configfile)
        return True
    except subprocess.CalledProcessError as e:
        print(f"exiftool実行エラー: {e}")
        sys.exit(1)
    except Exception as e:
        error_message = str(e)
        if "429" in error_message:
            return False
        else:
            print(f"エラーが発生しました: {e}")
            sys.exit(1)

folder_path = r""#読み込みたいフォルダーパスを指定
try:
    config = configparser.ConfigParser()
    config.read('config.ini', encoding='utf-8')
    current_file_count = int(config['DEFAULT']['current_file'])
except (FileNotFoundError, KeyError):
    current_file_count = 0
    
for filename in sorted(os.listdir(folder_path)):
    if filename.lower().endswith((".jpg", ".jpeg")):
        if( i < current_file_count):
            i += 1
            continue
        current_file_count += 1
	i += 1
        image_path = os.path.join(folder_path, filename)
        while True:
            try:
                if analyze_image_and_embed_iptc_keywords(image_path,filename,folder_path,current_file_count):
                    error_count = 0
                    break
                else :
                    error_count += 1
                    if error_count >= 3:
                        print("Gemini APIのエラーが3回続いたため、処理を中断します。")
                        sys.exit(1)
                    print("Gemini APIのエラーが発生したため、1分待機します。")
                    time.sleep(60)
            except Exception as e:
                print("Gemini APIのエラーが発生したため、1分待機します。")
                time.sleep(60)

後は適当なファイル名で保存し、ターミナルなどからpython 保存したファイル名.pyを実行します。コメントで記入されているように、APIキーや読み取りたいフォルダーパスなどは、ダブルクォーテーション内に適宜記述をしてください。

実行すると、指定したフォルダー内のJPEG画像に対して、IPTCキーワードが埋め込まれます。

Gemini2.0はAPIで利用した場合、1分当たりの利用上限制限(15回まで)と1日当たりの利用上限制限(1500回まで)及びコンテクスト長制限があるため制限に抵触したときは、1分間待つようにしています。それが3回続いた場合は1日の利用上限制限に抵触した可能性があるため、処理を中断します。

処理が完了した場合は、config.iniに現在の処理ファイル数が保存されるので、次回実行時はconfig.iniを読み込み、前回の続きから処理を開始します。ただ、ファイルの数に変更があったり、処理が終わったところの前に新しいファイルが追加されたとしても、そのファイルは対象外になるため、注意が必要です。最初から全てやり直す場合は、config.iniを削除してから実行してください。

キーワードの埋め込み

Gemini2.0はある程度正しくキーワードを返してきますが、プロンプトで指定しても記号混じりだったりするため、Python側で入ってくる可能性のある記号などを除去しています。IPTCキーワードはカンマ区切りで指定可能なため、カンマ区切りで入れていますが、長さに制限があるため、20文字以内に収めるようにしています。

マレにIPTCキーワードの埋め込みに失敗することがありますが、その場合は、エラーメッセージを表示して、処理を中断します。画像が正しいJPEG画像かどうかを確認してください。

画像の入っているフォルダーやファイル名に日本語が含まれているとエラーが表示されますが、特に処理には問題ありません。

画像の処理は1枚ずつ行なわれます。環境にもよりますが、Gemini2.0-Flashで1枚当たり3~4秒程度掛かるので、処理は早くありません。中断もできますが、気長に待つ必要があります。中断したいときは、Ctrl+C(Control+C)を押すと中断できます。ちなみに、Gemini2.0-Proも利用可能ですが、制限が厳しいため(1分当たり2回まで)相当な精度が欲しいとき以外は使わない方が良いです。

2025年4月1日現在では、上記コードで動作しますが、Gemini2.0のAPIは変更される可能性があるため、今後動作しなくなる可能性があります。

その場合は、Gemini2.0のAPIのドキュメントを確認して、適宜修正してください。

まとめ

高速に動作することは現状不可能ですが、生成AIのAPIを使うことで、ローカル環境に保存している画像に対して、比較的容易に正しいタグを付与することが可能になりました。タグ付けした画像は、AdobeBridgeやEagleなどの画像管理ソフトで検索が容易にできます。上手く活用してみてください。

CTO / sekiguchi

技術系の責任者。AIの利用やAIへのデータ投入など活用するものに興味が向いている。PHPなどを用いてバックエンド開発を行うほか、サーバーの管理、運用を行う。 専門学校や大学、他社でのウェビナーによる講義もしている。

このメンバーの記事一覧へ

おすすめ記事