見出し画像

NASに眠る85,000枚の写真をDiscordから自然言語で検索できるようにした

以前、Openclawで同じようなものを作ったのですが、Claude Codeからも使えるようにしました。


仕組みの概要

システムの核心はCLIP(Contrastive Language-Image Pre-Training)というAIモデルです。OpenAIが公開したこのモデルは、4億枚の画像とテキストのペアで学習されており、画像とテキストを同じベクトル空間に変換することができます。

具体的には、写真をCLIPに通して得られる512次元のベクトルをデータベースに保存しておき、検索時にはクエリテキストも同じモデルでベクトルに変換して、コサイン類似度が高い写真を返す仕組みです。

事前にすべての写真をインデックスしておく必要がありますが、一度作ってしまえばあとは検索するだけです。85,000枚のインデックスは1日かかりましたが、それ以降は追加分だけを差分処理しています。


精度を上げるための工夫

CLIPは英語テキストとの相性が良く、日本語クエリでは精度が落ちることがわかりました。「花火」より「fireworks festival night sky」の方が適切な結果が返ってきます。
そこでGemini CLIを経由して、日本語クエリを英語キーワードに翻訳してからCLIPにかけるようにしました。例えば「沼津の花火」は「Numazu fireworks festival」に変換されます。

美観スコアも組み込んでいます。LAIONが公開しているViT-B/32用の美観予測モデルを使うと、ピントが合っていて構図の整った写真を優先できます。既存のCLIPベクトルをそのまま通せるので、再インデックスが不要でした。スコアは±25%程度の重みで最終スコアに影響します。

もう一つ工夫したのが場所ブーストです。一眼レフで撮った写真にはGPSデータがなく、場所での絞り込みができません。そこで、iPhoneのGPS付き写真から「この日付にこの場所にいた」という記録を取り出し、同日に撮られた一眼レフの写真にも同じ場所情報を推定して適用するようにしました。「沼津の花火」で検索すると、GPSのない一眼レフで撮った花火写真が正しく上位に来るようになりました。


実際の使い勝手

Discordのチャンネルにテキストを送るだけで上位5枚の写真が返ってきます。

「赤い橋」のように色と被写体を組み合わせた検索も有効です。「滝」「橋」といった単純なキーワードでも、写真ライブラリから対応する写真を見つけてきます。

場所名との組み合わせも機能します。「沼津の花火」で2017年と2018年の花火大会写真が上位に来たときは、実際に使えるシステムになったと感じました。


返ってくる情報

画像ファイルと合わせて、撮影日とGPS住所(あれば)も表示されるようにしています。「2019-11-16 / 高千穂峡」のような形です。GPS情報がない一眼レフ写真は「GPS なし」と表示されます。

現時点ではキーワードによってはノイズが混じることもありますが、明らかに外れた写真が上位に来るようなケースはだいぶ減っています。


まとめ

CLIPによる意味検索、Geminiによる日本語→英語変換、LAION美観スコア、GPS推定による場所ブーストを組み合わせることで、実用的な写真検索システムができました。美観スコアは今回新たに導入したものですが、うまく機能していると思います。

既存のフォト管理アプリ(Google フォト、iCloud フォト等)でも自動タグ付けや自然言語検索は実装されていますが、外部サービスに写真データを送りたくない場合や、自宅NASに写真を集約して管理したい場合には、こういったローカルで動くシステムが選択肢になります。

再インデックス不要で既存データをそのまま活用できる点は、運用コストを抑える上で重要でした。インデックスさえ作ってしまえば、新しい写真が追加されるたびに差分だけ処理すればよいからです。

写真が増えるほど検索の価値も上がります。長年のライブラリを持っている方には、試してみる価値があると思います。

いいなと思ったら応援しよう!