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
を
実行したら顔の認識ができた