DeepFace(GitHub)という顔認識ライブラリを使ってみよう。
pip install deepface
でインストールできる(はずである)。
使い方の基本は、
from deepface import DeepFace r = DeepFace.represent(img_path=画像ファイルのパスまたはBGR形式の画像, model_name=モデル, enforoce_detection=False, detector_backend=顔検出器)
とすれば顔情報のリストが返る。画像ファイルのパスを渡すのが簡単だが、日本語ファイル名だとうまくいかないので、以下では自前で読み込んでから渡す。モデルは "VGG-Face"
がデフォルトだが、"Facenet512"
のほうが性能が良さそうである。enforce_detection=False
を付けないと、顔が検出されないときエラーになる。顔検出器は "opencv"
がデフォルトだがあまり賢くないので以下では "mtcnn"
を使う。
まずはフォルダにいろいろ写真を入れてやってみよう。
import pathlib path = pathlib.Path("/path/to/dir") names = [p for p in path.iterdir() if p.match("*.jp*g")] # .jpg .jpeg # あるいは import glob で name = glob.glob("/path/to/dir/*.jp*g")
でファイルパス一覧を読み出す。ここで日本語ファイル名があると後で失敗する。
まず、それぞれのファイルについて、埋め込みベクトルを計算する:
from deepface import DeepFace import cv2 import matplotlib.pyplot as plt import os embeddings = [] basenames = [] for name in names: basename = os.path.splitext(os.path.basename(name))[0] img = cv2.imread(name) rs = DeepFace.represent(img_path=img, model_name="Facenet512", enforce_detection=False, detector_backend="mtcnn") color = [0, 255, 0] for r in rs: print(r['face_confidence'], end=" ") if r['face_confidence'] > 0.9: embeddings.append(r['embedding']) basenames.append(basename) f = r['facial_area'] cv2.rectangle(img, (f['x'], f['y']), (f['x']+f['w'], f['y']+f['h']), color, 2) color = color[1:] + color[:1] print(basename) # cv2.imshow("Image", img) または plt.figure() plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.axis("off") plt.show()
距離行列を表示する:
import numpy as np def distance(a, b): # コサイン距離 return max(1 - np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)), 0) # 距離行列(0.6より大きければ * を付ける) for e1 in embeddings: for e2 in embeddings: d = distance(e1, e2) if d > 0.6: print(f" {d:4.2f}*", end="") else: print(f" {d:4.2f} ", end="") print()
クラスタリングのためのデンドログラムを描く:
from scipy.cluster.hierarchy import dendrogram, linkage n = len(embeddings) condensed_dist_mat = np.array([distance(embeddings[i], embeddings[j]) for i in range(n) for j in range(i+1, n)]) linked = linkage(condensed_dist_mat) plt.figure(figsize=(8, 4)) dendrogram(linked, labels=basenames, orientation="left") plt.show()
linkage()
は method="single|complete|average"
などのオプションを与えることができる(デフォルトは single
)。