bluesoyaji’s blog

定年後の趣味、大学入試問題の分析や国語の勉強方法など。みなさんのお役に立てばうれしいです。

AIと一緒に写真自動振り分けアプリを作ってみた話

AIと一緒に写真自動振り分けアプリを作ってみた話

はじめに

Macに接続した外付けSSDに溜まった写真を、カメラの種類・撮影日・ファイル形式で自動整理するアプリをAI(Claude)と一緒に作ってみました。プログラムの知識はゼロですが、なんとか形にできたので、そのプロセスを記録しておきます。

ちなみにMacも初心者で操作に不慣れです。


作ったもの

  • SSD内の写真を指定フォルダに自動振り分けするツール
  • 分類方法:カメラの機種名 → 撮影年月 → ファイル形式(JPEG/RAW/HEICなど)
  • 対応カメラ:Panasonic G8・G9・GX7MK2・GX8・GF1、PENTAX KF、Sigma DP1 Merrill、iPhoneなど

作成のプロセス

1. 要件をAIに伝える

  • 「SSDに写真を貼り付けると自動で各フォルダに振り分け、カメラの種類・撮影日・ファイルの種類で分類するアプリを作りたい」と依頼
  • Pythonがインストール済みであることを確認
  • ファイルは「移動(元フォルダから消える)」方式を選択

2. Pythonスクリプトの作成(第1弾)

cat > /tmp/organize_photos_test.py << 'EOF'
import subprocess
import os
from pathlib import Path
from collections import defaultdict

SSD = Path('/Volumes/Extreme SSD')
DEST = Path('/Volumes/Extreme SSD/整理済み')
DRY_RUN = True

CAMERA_MAP = {
    'panasonic': 'Panasonic',
    'fujifilm': 'FUJIFILM',
    'olympus': 'OLYMPUS',
    'ricoh': 'RICOH',
    'nikon': 'NIKON',
    'apple': 'iPhone',
    'sigma': 'Sigma',
    'pentax': 'PENTAX',
}

RAW_EXTS = {'.rw2', '.raf', '.orf', '.dng', '.arw', '.nef', '.x3f', '.pef'}
JPEG_EXTS = {'.jpg', '.jpeg'}

def get_exif(filepath):
    try:
        result = subprocess.run(
            ['exiftool', '-Make', '-Model', '-DateTimeOriginal', '-CreateDate', str(filepath)],
            capture_output=True, text=True, timeout=10
        )
        make, model, date = '', '', ''
        for line in result.stdout.splitlines():
            if 'Make' in line and ':' in line:
                make = line.split(':', 1)[1].strip().lower()
            elif 'Model' in line and ':' in line:
                model = line.split(':', 1)[1].strip()
            elif ('Date/Time Original' in line or 'Create Date' in line) and ':' in line and not date:
                date = line.split(':', 1)[1].strip()[:10].replace(':', '-')
        return make, model, date
    except:
        return '', '', ''

def get_camera_folder(make, model):
    for key, name in CAMERA_MAP.items():
        if key in make:
            return f"{name}_{model}" if model else name
    return 'その他'

def collect_files():
    files = []
    # ルート直下のファイル
    for f in SSD.iterdir():
        if f.is_file() and f.suffix.lower() in RAW_EXTS | JPEG_EXTS:
            files.append(f)
    # サブフォルダ(整理済みフォルダは除外)
    skip = {'整理済み', 'System Volume Information', 'Photos Library.photoslibrary'}
    for d in SSD.iterdir():
        if d.is_dir() and d.name not in skip:
            for f in d.rglob('*'):
                if f.is_file() and f.suffix.lower() in RAW_EXTS | JPEG_EXTS:
                    files.append(f)
    return files

files = collect_files()
print(f"対象ファイル数: {len(files)}")

camera_count = defaultdict(int)
date_none = 0
sample = 0

for f in files[:50]:  # テストは最初の50枚だけ
    make, model, date = get_exif(f)
    camera = get_camera_folder(make, model)
    ext = f.suffix.lower()
    file_type = 'RAW' if ext in RAW_EXTS else 'JPEG'
    if not date:
        date = '日付不明'
        date_none += 1
    dest = DEST / camera / date / file_type / '未分類' / f.name
    camera_count[camera] += 1
    if sample < 10:
        print(f"  {f.name} → {camera}/{date}/{file_type}/未分類/")
        sample += 1

print(f"\nカメラ別件数(サンプル50枚):")
for cam, count in sorted(camera_count.items()):
    print(f"  {cam}: {count}枚")
print(f"日付なし: {date_none}枚")
EOF

 

こんな謎のコマンドを何度もコピーペーストしました

きつかった!

  • AIがPythonスクリプト(photo_organizer.py)を生成
  • ターミナルから実行し、振り分け元・振り分け先フォルダを入力する方式
  • テスト実行機能付き(実際には移動せず確認できる)
  • 無事に動作! カメラ別・年月別・ファイル形式別に整理できた

3. 問題発生①:フォルダ名のズレ

  • Panasonic G9のフォルダが既存の「Panasonic DMC-G9」フォルダに入らず、「dmc g9」という別フォルダが新たに作られてしまった
  • 原因:カメラのEXIFに記録されているモデル名が機種によって異なる(例:DC-G9DMC-G9など)
  • 対処:スクリプトにカメラ名統一ルール(CAMERA_NAME_MAP)を追加

4. 問題発生②:GF1のフォルダ名

  • GF1でも同様の問題が発生。panasonic_dmc_gf1panasonic dmc_gf1の2つが作られてしまった
  • アンダーバーの有無の違い
  • 今回はそのままにして、後日手動で統合することに

5. ダブルクリックで起動するアプリ化(Automator)

ここまでで2日、8時間くらい費やしています。

もっと簡単にできないかと相談してみました

  • ターミナル操作をなくすため、Macの標準アプリ「Automator」を使って.app形式に変換
  • シェルスクリプトをAutomatorに貼り付けて「写真振り分け.app」を作成
  • 起動するとフォルダ選択ダイアログが2回表示され、あとは自動で振り分け完了

6. .commandファイルへの挑戦(Automator不要の方法)

  • Automatorの操作が難しかったため、ダブルクリックで動く.commandファイルも作成を試みた
  • ダウンロード方法やターミナルでの設定でつまずき、最終的に断念
  • 実用には最初のAutomatorアプリを採用
  • Claudeはこのようにまとめていますが、実際はうまく作動しませんでした(ここだけの話)

初心者が困った点

  • ターミナルの操作:コマンドを貼り付けるだけとはいえ、慣れないと不安
  • Automatorの使い方:どこを開いてどこに貼り付けるかわかりにくかった
  • ファイルのダウンロード:AIが作ったファイルをどこからダウンロードするのかわからなかった
  • カメラ名のズレ:同じメーカーでも機種によってEXIFの表記が違い、フォルダが分裂した
  • エラーの原因究明:何が悪いのか自分では判断できず、AIに聞きながら一つずつ解決
  • (カメラの種類が多すぎや!)

使ってみた感想

プログラムの知識がなくても、AIに要件を伝えるだけでスクリプトを作ってもらえるのは本当にすごいと感じました。一方で、初心者にとってはターミナルやAutomatorの操作など、ハードルが高い場面も多くありました。

「ダブルクリックだけで全部終わる」という理想にはまだ届かない部分もありましたが、実用的なツールが完成し、実際に写真の整理ができました。

AIの進化とともに、もっと誰でも簡単に使えるようになることを期待しています。


今後の課題

  • Googleフォトへの自動同期設定
  • 草花・鳥・風景などテーマ別のAI自動分類
  • G9・GF1フォルダの手動統合

作成日:2026年5月20日 使用ツール:Claude(Anthropic)、Python、Automator(Mac標準)