0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

unerryAdvent Calendar 2024

Day 3

「この人誰だっけ」をAIで解決する試み

Last updated at Posted at 2024-12-02

はじめに

2024年5月31日(Fri)20:00 ~ 2024年6月7日(Fri)22:00
#生成AI オンラインハッカソン4 by #protopedia
https://protopedia.net/event/102

このイベントで作った作品の解説をします。
ネタ作品ですが、Embeddingとベクター検索は生成AI関連でもよく使う技術となりますので、何かの役にたつと幸いです。

概要

  • 以前どこかで会って名刺交換したのだが、名前を思い出せないという時に使用
  • Raspberry Pi4 カメラで撮影した画像をベクター検索して、可能性の高い人を教えてくれるシステム

仕様

image.png

使い方

  1. パーティなどで名刺交換したあと、写真を撮影。

  2. 家に帰ったら忘れないうちにEmbeddingし、MacのローカルベクターDBに登録しておく。

  3. 人と会う機会にこのデバイスを持っていき、うっかり名前を思い出せない時に、「ちょっと失礼します!」と勢いよく鞄から人形を取り出し、目をあわせてもらう

  4. MacからRaspberry Piに有線などで接続

  5. Raspberry Pi カメラで撮影

  6. ベクター化 → 類似検索

  7. 可能性のある人物が提示される

コード

以下は 「2. 家に帰ったら忘れないうちにEmbeddingし、MacのローカルのベクターDBに登録しておく」の部分のコードとなります。
tensorflowのライブラリに含まれるResNet50を使っています。

# 画像からembeddingを抽出するモデルの設定
model = ResNet50(weights='imagenet', include_top=False, pooling='avg')

def get_image_embedding(img_path):
    """
    指定されたパスの画像からembeddingを取得します。
    """
    # 画像の読み込みと前処理
    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)

    # 画像からembeddingを取得
    embedding = model.predict(img_array)
    return embedding

def load_images_and_embeddings(directory):
    """
    指定されたディレクトリ内の全ての画像を読み込み、それぞれのembeddingを取得します。
    """
    image_paths = [os.path.join(directory, f) for f in os.listdir(directory) if f.endswith(('.jpg', '.jpeg', '.png'))]
    embeddings = []
    for img_path in image_paths:
        embedding = get_image_embedding(img_path)
        embeddings.append(embedding)
    return image_paths, np.vstack(embeddings)

def create_faiss_index(embeddings):
    """
    embeddingをFAISSインデックスに追加します。
    """
    dimension = embeddings.shape[1]
    index = faiss.IndexFlatL2(dimension)
    index.add(embeddings)
    return index

Raspberry Piのカメラを叩いて撮影し、ローカル上の/content/target-image/target.jpegに保存するコードは割愛します。

次は、「6. ベクター化 → 類似検索」の部分のコードです。

  # クエリ画像のパス
    query_image_path = '/content/target-image/target.jpeg'

    # 類似画像を検索
    similar_images = search_similar_images(query_image_path, image_paths, index, top_k=5)

    # 結果を表示
    print("Query image:", query_image_path)
    print("Similar images:")
    for img_path in similar_images:
        print(img_path)

結果

自分の顔と芸能人3人の方の写真を、1人3枚づつ集めてこのシステムで判定したところ、残念ながら正確には判定できませんでした。

image.png

1位 ロバート秋山さん
2位 自分
3位 ファーストサマーウイカさん
4位 ロバート秋山さん
5位 自分

選外
ビートたけしさん
うる星やつらの「ラムちゃん」さん

(著作権の都合上、顔写真を出す事は控えます)

結果その2

結果が納得いかないので、他のモデルを試そうと思い、ResNet50 -> VGG16に変えて試したところ、信頼性が落ちてしまいました。

image.png

1位 ファーストサマーウイカさん
2位 自分
3位 ロバート秋山さん
4位 自分
5位 うる星やつらの「ラムちゃん」さん

選外
ビートたけしさん

Tips

VGG16はResNet50より古く、ベクターの次元数も少ないので、多少重かったとしてもResNet50を使った方が良さそうです。

名前 特徴 ベクトルの次元数
VGG16 深さが 16 層の畳み込みニューラル ネットワーク 512次元
ResNet50 深さが 50 層の畳み込みニューラル ネットワーク 2048次元

振り返り

様々なハードルがあり、実用には適しておりませんでした。
とくに「勢いよく人形を取り出し、目をあわせてもらう」運用は無理でした。残念。
ですが将来的に「Ray-Ban Meta」のような民間のwearable デバイスがネット越しにAIと繋がり、このような機能を持つ事は容易に想像できます。
その時を楽しみに待ちたいと思います。

以上となります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?