LoginSignup
0
0

python venvの仮想環境で構築する顔認証(face_recognition)windows環境

Posted at

■ 概要

・Windows11。
・pythonの仮想環境venvで構築。
・モジュールは、opencv-python、face_recognition、configを使用。
・外部カメラ使用(USB WEBカメラ)
・物体検知で、ディレクトリ(image_jp)内にある画像と一致したら、パスワードを入力する。

■ 完成画面

スクリーンショット (762).png

■ ディレクトリ構成

スクリーンショット (756).png
./app/以下
スクリーンショット (757).png

■仮想環境の作成と、モジュールのインストール

・仮想環境 作成
$ python -m venv venv
・仮想環境を起動して、入る。
$ /venv/SCripts\activate.bat

・モジュールのインストール
$ pip install opencv-python
$ pip install face_recognition
$ pip install config

■ ソースコード

・main_001.py

python main_001.py
import os
import sys
from tabnanny import check
import face_recognition
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
import glob
import config

# === config.py へ thresholdの値記述
threshold = config.threshold
tmp_info= config.pass_info
mode= config.mode  # 1 : on , 2 : OFF


face_locations = []
face_encodings = []

# === ディレクトリ下の画像を取得 
# image_paths = glob.glob('image/*')
image_paths = glob.glob('image_jp/*') # このディレクトリの中へ判定する画像を入れておく。
for img_val in image_paths:
    print("登録 画像ファイル名 :::" + img_val)


image_paths.sort()
known_face_encodings = []
known_face_names = []

checkd_face = []

# delimiter = "\\" # Windows用 (\記号を2つ書く)
# delimiter = "/"  # Mac/Linux用

for image_path in image_paths:
    # im_name = image_path.split(delimiter)[-1].split('.')[0]
    im_name = os.path.basename(image_path).split('.')[0]    # os.path.basename ファイル名の取得
    image = face_recognition.load_image_file(image_path)
    face_encoding = face_recognition.face_encodings(image)[0]
    known_face_encodings.append(face_encoding)
    known_face_names.append(im_name)


video_capture = cv2.VideoCapture(0)

#================== パスワードチェック
def check_password(name):
    if name in checkd_face:
        return
    
    emp_pw = input(name + "さんのパスワードを入力してください。")
    
    if tmp_info[name] == emp_pw:
        print("ログイン OK")
        checkd_face.append(name)
    else:
        print("パスワードが間違っています。")


#================== 認識率の計算
def calculate_recognition_rate(matches):
    num_matches = sum(matches)
    total_faces = len(matches)
    recognition_rate = num_matches / total_faces
    return recognition_rate


#================== main 処理
def main(): 
    
	print("=== main 処理 開始 ===")
 
	while True:
     
  
	    # ビデオの単一フレームを取得
		_, frame = video_capture.read()

		# ビデオの現在のフレーム内のすべての顔に対してその位置情報を検索
		face_locations = face_recognition.face_locations(frame)
		# 顔の位置情報からエンコードを生成
		face_encodings = face_recognition.face_encodings(frame, face_locations)

		for face_encoding in face_encodings:
			# 顔が登録済みの顔と一致するか確認
			matches = face_recognition.compare_faces(known_face_encodings, face_encoding, threshold)
			name = "Unknown"

			# カメラ画像と最も近い登録画像を見つける
			face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
			best_match_index = np.argmin(face_distances)
			if matches[best_match_index]:
				name = known_face_names[best_match_index]
    
			# 認識率を計算
			recognition_rate = calculate_recognition_rate(matches)
			recognition_rate_str = f"Recognition Rate: {recognition_rate:.2%}"

		# 位置情報の表示
		for (top, right, bottom, left) in face_locations:
      
        	# 顔領域に枠を描画  色:緑
			cv2.rectangle(frame, (left, top), (right, bottom), (0, 128, 0), 2)

			# 枠の下に名前を表示 色:緑
			cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 128, 0), cv2.FILLED)
			#font = cv2.FONT_HERSHEY_DUPLEX
			#cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
   
			# === 日本語表示 ===
			fontpath = 'meiryo.ttc'
			font = ImageFont.truetype(fontpath, 32)
			img_pil = Image.fromarray(frame)
			draw = ImageDraw.Draw(img_pil)
			position = (left + 6, bottom - 40)
			# drawにテキストを記載
			draw.text(position, name, font=font, fill=(255,255,255,0))
			frame = np.array(img_pil)
   
   
			# カメラ画像上に認識率を表示 色:赤
			cv2.putText(frame, recognition_rate_str, (10, 30), cv2.FONT_HERSHEY_DUPLEX, 1.0, (0, 0, 255), 1)
   
			# === 本人認証 ===
			if mode == 1 and name != "Unknown":
				check_password(name)
   
		
		# 結果をビデオに表示
		cv2.imshow('Tossy_View', frame)

		# t キーで終了
		if cv2.waitKey(1) & 0xFF == ord('t'):
			
			print("=== main 処理 終了 ===")
			# ウェブカメラへの操作を開放
			video_capture.release()
			cv2.destroyAllWindows()
			break


if __name__ == "__main__":
    main()


# ウェブカメラへの操作を開放
video_capture.release()
cv2.destroyAllWindows()

・config.py

python config.py
pass_info = {}
pass_info["夏目智徹_01"] = "1234"
pass_info["夏目_02"] = "0000"

mode = 1

threshold = 0.6
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0