FAISSを使った画像類似検索の実装:女性のプロマイド画像を例に詳細解説
📌 目的:
本記事では、FAISS(Facebook AI Similarity Search) を用いて、画像の類似検索 を実装する方法を、女性のプロマイド画像を例に詳細に解説します。
📌 1. FAISSとは?
FAISS(Facebook AI Similarity Search) は、Facebook AI Research(FAIR)が開発した、大規模な特徴量ベクトルの類似検索を高速に行うライブラリ です。
🔹 FAISSのメリット
✅ 超高速検索:数百万件のデータからでも、ミリ秒単位で類似検索が可能
✅ 大規模データ対応:数GB~TB規模の特徴量ベクトルを効率的に検索可能
✅ 柔軟なインデックス:L2距離・コサイン類似度・HNSW(近似最近傍検索)など多彩な検索手法をサポート
✅ GPUサポート:GPUを活用してさらに高速化可能
📌 2. FAISSのユースケース
FAISSは以下のような場面で活用されています。
ユースケース | 説明 |
---|---|
画像類似検索 | 似た画像を検索(例: ファッションEC、アイドルフォト類似検索) |
顔認識 | ユーザーの顔特徴から同じ人物を検索(例: 顔認証システム) |
動画推薦 | 動画の特徴ベクトルをもとに、関連動画を推薦(例: YouTube、TikTok) |
音楽推薦 | 曲の特徴を分析し、類似した楽曲を検索(例: Spotify) |
テキスト検索 | 単語の埋め込みベクトルを用いた類似文章検索(例: 検索エンジン) |
💡 今回は、女性のプロマイド画像を使った類似検索を実装します!
📌 3. FAISSを使った画像類似検索の流れ
FAISSを使って、以下の流れで類似画像を検索します。
- 画像の特徴量を抽出(ResNetを使用)
- FAISSのインデックスに特徴量を登録
- クエリ画像を入力し、類似画像を検索
- 検索結果を表示し、分析
📌 4. 画像の特徴量を抽出
まずは、ResNet50 を使って画像の特徴量(ベクトル)を取得します。
🔹 ライブラリのインストール
pip install faiss-cpu tensorflow numpy opencv-python
🔹 画像の特徴量抽出(ResNet50)
import numpy as np
import tensorflow as tf
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet50 import preprocess_input
import os
from glob import glob
# ResNet50のロード(最後の全結合層を削除)
model = ResNet50(weights='imagenet', include_top=False, pooling='avg')
def extract_features(img_path):
"""画像から特徴量を抽出する"""
img = image.load_img(img_path, target_size=(224, 224))
img_array = image.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
img_array = preprocess_input(img_array)
features = model.predict(img_array)
return features.flatten() # 2048次元の特徴ベクトルを返す
# データセットの画像パスを取得
image_paths = glob("dataset/*.jpg") # datasetフォルダに画像を配置
feature_vectors = np.array([extract_features(img) for img in image_paths])
# 特徴量と画像パスを保存
np.save("image_features.npy", feature_vectors)
np.save("image_paths.npy", np.array(image_paths))
🔍 結果:
feature_vectors
に、全画像の特徴ベクトル(2048次元)が保存されます。
📌 5. FAISSのインデックス作成
次に、FAISSを使って高速検索のための**インデックス(検索用データ構造)**を作成します。
import faiss
# 特徴量をロード
feature_vectors = np.load("image_features.npy")
image_paths = np.load("image_paths.npy")
# FAISSのインデックス作成(L2距離を使用)
index = faiss.IndexFlatL2(feature_vectors.shape[1]) # 2048次元のL2距離ベースの検索
index.add(feature_vectors) # 画像特徴量をインデックスに追加
# インデックスを保存
faiss.write_index(index, "faiss_index.bin")
🔍 結果:
FAISSのインデックスが作成され、faiss_index.bin
に保存されます。
📌 6. クエリ画像の類似検索
ユーザーがアップロードした画像と似た画像を検索します。
# FAISSのインデックスをロード
index = faiss.read_index("faiss_index.bin")
def search_similar_images(query_img, top_k=5):
"""クエリ画像と類似する画像を検索"""
query_vector = extract_features(query_img).reshape(1, -1)
distances, indices = index.search(query_vector, top_k)
return [image_paths[i] for i in indices[0]] # 類似画像のパスを返す
# 検索テスト(例: "test.jpg" の類似画像を取得)
query_image = "test.jpg"
similar_images = search_similar_images(query_image)
print("🔍 類似画像のパス:", similar_images)
🔍 結果:
入力画像 "test.jpg"
に最も似た5枚の画像のパスが返されます。
📌 7. 検索結果の可視化
検索結果を画像で表示します。
import cv2
import matplotlib.pyplot as plt
def show_images(query_img, similar_images):
"""クエリ画像と類似画像を可視化"""
fig, axes = plt.subplots(1, len(similar_images) + 1, figsize=(15, 5))
# クエリ画像
img = cv2.imread(query_img)[..., ::-1] # BGR → RGB変換
axes[0].imshow(img)
axes[0].set_title("Query Image")
axes[0].axis("off")
# 類似画像
for i, img_path in enumerate(similar_images):
img = cv2.imread(img_path)[..., ::-1]
axes[i + 1].imshow(img)
axes[i + 1].set_title(f"Rank {i+1}")
axes[i + 1].axis("off")
plt.show()
# 類似画像を可視化
show_images(query_image, similar_images)
✅ 検索結果が視覚的に確認できるようになります!
📌 8. まとめ
🎯 FAISSの活用ポイント
- ResNet50で画像特徴を抽出し、FAISSで高速類似検索を実装
- L2距離を用いたベクトル検索で、精度の高い結果を取得
- 大規模データにも対応し、数百万枚の画像もミリ秒単位で検索可能
- 画像検索の他、顔認識・動画推薦・音楽検索にも応用可能
🚀 次のステップ
- コサイン類似度を用いる(L2距離と比較)
- HNSWを使った近似最近傍検索(より高速化)
- 顔認識モデル(FaceNet)と組み合わせる
これで、プロマイド画像の類似検索システムを構築できます! 🎉
Discussion