Python – 顔認識ライブラリ Face Recognition で顔認証を行う方法

概要
dlib を使った Python の顔認識ライブラリ Face Recognition を使って、顔認証を行う方法について紹介します。 顔認証は、予め保存されている個人の顔のデータと認証中の顔の画像とを照合し、その人物が誰であるかを識別する技術です。 スマートフォンのロック解除や入退室管理など、セキュリティが求められる分野で広く使われています。
環境
コード全体は pystyle/perform-face-recognition-with-python にあります。
このコードは、以下の環境で実行しました。
Ubuntu 18.04
- ライブラリ
- Face Recognition: 1.2.3
- GPU の実行環境
- GPU: GeForce GTX 1080
- CUDA: 9.0
- CuDNN: 7
- CPU の実行環境
- CPU: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
- メモリ: 16G
Windows 10
- ライブラリ
- Face Recognition: 1.2.3
- CPU の実行環境
- CPU: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
- メモリ: 16G
インストール
Ubuntu 18.04 の場合
インストール時に Face Recognition が利用している dlib のビルドが必要になります。
インストール前に apt
で GCC 及び CMake をインストールし、C++ のビルド環境を整えます。
apt install -y build-essential cmake
準備ができたら、pip で Face Recognition をインストールします。
pip install face_recognition
Windows 10 の場合
インストール前に Visual Studio 2019 Community と CMake をインストールし、C++ のビルド環境を整えます。
準備ができたら、pip で Face Recognition をインストールします。
pip install face_recognition
顔認証の手順
以下の3人が予め保存されている人物の顔の画像とします。
以下を認証する人物の顔の画像とします。
顔画像を読み込む
load_image_file() で顔の画像を読み込みます。
import face_recognition
import matplotlib.pyplot as plt
# 保存されている人物の顔の画像を読み込む。
known_face_imgs = []
for path in ["known-face_01.jpg", "known-face_02.jpg", "known-face_03.jpg"]:
img = face_recognition.load_image_file(path)
known_face_imgs.append(img)
# 認証する人物の顔の画像を読み込む。
face_img_to_check = face_recognition.load_image_file("face_to_check.jpg")
顔の領域を検出する
face_locations() で読み込んだ顔の画像から、顔の領域を検出します。 返り値は顔の領域を表す (top, right, bottom, left) の tuple の list になっています。
model
は検出に使用するモデルを指定します。
“hog” (デフォルト) を指定した場合、HOG 特徴量 ベースのモデルになります。
“cnn” を指定した場合、CNN ベースのモデルになります。
HOG | CNN | |
---|---|---|
計算量 | 少ない | 多い |
精度 | 中 | 高 |
CNN のほうが高精度ですが、計算量が多く、CPU で実行した場合は時間がかかってしまいます。GPU が使える PC ではこちらを選択するとよいでしょう。
# 顔の画像から顔の領域を検出する。
known_face_locs = []
for img in known_face_imgs:
loc = face_recognition.face_locations(img, model="cnn")
assert len(loc) == 1, "画像から顔の検出に失敗したか、2人以上の顔が検出されました"
known_face_locs.append(loc)
face_loc_to_check = face_recognition.face_locations(face_img_to_check, model="cnn")
assert len(face_loc_to_check) == 1, "画像から顔の検出に失敗したか、2人以上の顔が検出されました"
結果を確認するために、matplotlib で顔の領域を画像上に描画します。
def draw_face_locations(img, locations):
fig, ax = plt.subplots()
ax.imshow(img)
ax.set_axis_off()
for i, (top, right, bottom, left) in enumerate(locations):
# 長方形を描画する。
w, h = right - left, bottom - top
ax.add_patch(plt.Rectangle((left, top), w, h, ec="r", lw=2, fill=None))
plt.show()
for img, loc in zip(known_face_imgs, known_face_locs):
draw_face_locations(img, loc)
draw_face_locations(face_img_to_check, face_loc_to_check)




画像から顔の領域が正しく検出できていることがわかりました。
顔の領域から特徴量を抽出する
face_encodings で顔の画像から識別に有用な特徴量を抽出します。
face_encodings(face_image, known_face_locations=None)
- 引数
- face_image: 画像
- known_face_locations: face_locations() の返り値 locations を渡します。
返り値は、顔の特徴量を表す1次元の numpy 配列の list となっています。
# 顔の領域から特徴量を抽出する。
known_face_encodings = []
for img, loc in zip(known_face_imgs, known_face_locs):
(encoding,) = face_recognition.face_encodings(img, loc)
known_face_encodings.append(encoding)
(face_encoding_to_check,) = face_recognition.face_encodings(
face_img_to_check, face_loc_to_check
)
マッチする人物がいるかどうかを調べる
登録されている人物の顔の特徴量 known_face_encodings
と認証する人物の顔の特徴量 face_encoding_to_check
を compare_faces に渡すことで、登録されている人物の中にマッチする人物がいるかどうかを調べられます。
tolerance
はマッチするかどうかを判定する閾値で、この値を低くするほど判定が厳しくなり、高くするほど判定が緩くなります。
matches = face_recognition.compare_faces(known_face_encodings, face_encoding_to_check)
print(matches) # [True, False, False]
[True, False, False]
認証する人物は登録されている1人目の人物とマッチしていると判定されました。 登録されている1人目の人物はオバマ大統領なので、正解しています。
特徴量同士の距離を計算する
内部的には、似ているかどうかの判定は特徴量同士の距離で判定しています。 距離が近いほど似ていて、遠いほど似ていないといえます。 この距離は face_distance で計算できます。
dists = face_recognition.face_distance(known_face_encodings, face_encoding_to_check)
print(dists)
[0.32466209 0.8858496 0.88910518]
認証する人物は一人目のオバマ大統領との距離が最も近い結果となりました。
-
前の記事
Python から XML-RPC を介して WordPress を操作する方法 2020.02.18
-
次の記事
Python – 顔認識ライブラリ Face Recognition で顔検出を行う方法 2020.02.27