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)。