FaceRecognizerSFによる顔の認識の実践
スマホの写真のサイズを1/4にすることで
generate_aligned_faces.py
による顔の切り出しが成功した
取り出した顔画像は
Face00x.jpg
となっているので、個人ごとの名前ファイルに改名する
次に
顔画像から特徴を抽出、特徴辞書として保存する
python generate_feature_dictionary.py snowpool.jpg
これで
snowpool.npy
が作成される
同様に家族分も実行する
python resize_save.py PXL_20240218_063620749.jpg
で画像ファイルを1/4にして
python generate_aligned_faces.py PXL_20240218_063620749_quarter.jpg
で写真から顔を抽出
mv face001.jpg child.jpg python generate_feature_dictionary.py child.jpg
これでそれぞれのnpyファイルができる
次に識別
モデルが変更になっているので
weights = os.path.join(directory, "yunet.onnx")
を
weights = os.path.join(directory, "face_detection_yunet_2023mar.onnx")
というように
指定するモデルを
変更する
編集するファイルは
face_recognizer.py
これで
python face_recognizer.py PXL_20240218_063620749.jpg
を実行したら
OpenCV: Couldn't read video stream from file "/Users/snowpool/aw10s/face_recog/image.jpg"
となる
https://sites.google.com/iot-com.net/home/ホーム/実験室/jetson-nano/jetson-nanoのopen-cvで顔認証
によれば
# return True, (user_id, cos_score) ←オリジナルのtypo
return True, (user_id, score)
とあるので
# return True, (user_id, cos_score)
return True, (user_id, score)
というように修正
そして
そのままだとファイル名が指定されているので
コマンドラインからファイル名を指定して実行できるように
ソースを変更する
Mainの部分を
# main関数の引数を追加 def main(image_path): # captureの初期化を変更 capture = cv2.VideoCapture(image_path) # コマンドラインから指定された画像ファイル
として
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Face Recognition")
parser.add_argument('image', help="Path to the image file")
args = parser.parse_args()
main(args.image)
と書き換える
これで再度実行してみる
Traceback (most recent call last):
File "/Users/snowpool/aw10s/face_recog/face_recognizer.py", line 108, in <module>
main(args.image)
File "/Users/snowpool/aw10s/face_recog/face_recognizer.py", line 37, in main
files = glob.glob(os.path.join(directory, "*.npy"))
NameError: name 'directory' is not defined
となった
原因は
directory = os.path.dirname(__file__)
を削除したことでディレクトリの指定ができなくなっていた
import os
import sys
import glob
import numpy as np
import cv2
import argparse
COSINE_THRESHOLD = 0.363
NORML2_THRESHOLD = 1.128
# 特徴を辞書と比較してマッチしたユーザーとスコアを返す関数
def match(recognizer, feature1, dictionary):
for element in dictionary:
user_id, feature2 = element
score = recognizer.match(feature1, feature2, cv2.FaceRecognizerSF_FR_COSINE)
if score > COSINE_THRESHOLD:
# return True, (user_id, cos_score)
return True, (user_id, score)
return False, ("", 0.0)
# def main():
# # キャプチャを開く
# directory = os.path.dirname(__file__)
# capture = cv2.VideoCapture(os.path.join(directory, "image.jpg")) # 画像ファイル
# main関数の引数を追加
def main(image_path):
# captureの初期化を変更
directory = os.path.dirname(__file__)
capture = cv2.VideoCapture(image_path) # コマンドラインから指定された画像ファイル
#capture = cv2.VideoCapture(0) # カメラ
if not capture.isOpened():
exit()
# 特徴を読み込む
dictionary = []
files = glob.glob(os.path.join(directory, "*.npy"))
for file in files:
feature = np.load(file)
user_id = os.path.splitext(os.path.basename(file))[0]
dictionary.append((user_id, feature))
# モデルを読み込む
# weights = os.path.join(directory, "yunet.onnx")
weights = os.path.join(directory, "face_detection_yunet_2023mar.onnx")
face_detector = cv2.FaceDetectorYN_create(weights, "", (0, 0))
weights = os.path.join(directory, "face_recognizer_fast.onnx")
face_recognizer = cv2.FaceRecognizerSF_create(weights, "")
while True:
# フレームをキャプチャして画像を読み込む
result, image = capture.read()
if result is False:
cv2.waitKey(0)
break
# 画像が3チャンネル以外の場合は3チャンネルに変換する
channels = 1 if len(image.shape) == 2 else image.shape[2]
if channels == 1:
image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
if channels == 4:
image = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)
# 入力サイズを指定する
height, width, _ = image.shape
face_detector.setInputSize((width, height))
# 顔を検出する
result, faces = face_detector.detect(image)
faces = faces if faces is not None else []
for face in faces:
# 顔を切り抜き特徴を抽出する
aligned_face = face_recognizer.alignCrop(image, face)
feature = face_recognizer.feature(aligned_face)
# 辞書とマッチングする
result, user = match(face_recognizer, feature, dictionary)
# 顔のバウンディングボックスを描画する
box = list(map(int, face[:4]))
color = (0, 255, 0) if result else (0, 0, 255)
thickness = 2
cv2.rectangle(image, box, color, thickness, cv2.LINE_AA)
# 認識の結果を描画する
id, score = user if result else ("unknown", 0.0)
text = "{0} ({1:.2f})".format(id, score)
position = (box[0], box[1] - 10)
font = cv2.FONT_HERSHEY_SIMPLEX
scale = 0.6
cv2.putText(image, text, position, font, scale, color, thickness, cv2.LINE_AA)
# 画像を表示する
cv2.imshow("face recognition", image)
key = cv2.waitKey(1)
if key == ord('q'):
break
cv2.destroyAllWindows()
# if __name__ == '__main__':
# main()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Face Recognition")
parser.add_argument('image', help="Path to the image file")
args = parser.parse_args()
main(args.image)
で
再度
python face_recognizer.py PXL_20240218_063620749.jpg
を
実行したら顔の認識ができた