LoginSignup
0
2

顔認証アプリのプロトタイプ

Last updated at Posted at 2023-12-07

はじめに

顔認証による入退室管理のWebアプリケーションのプロトタイプを作ってみたので記事にしてみました。

コード

import streamlit as st
import cv2
import face_recognition
import numpy as np
import os

def load_known_faces(directory="known_faces"):
    known_faces = []
    known_names = []

    for filename in os.listdir(directory):
        path = os.path.join(directory, filename)
        image = face_recognition.load_image_file(path)
        encoding = face_recognition.face_encodings(image)[0]
        known_faces.append(encoding)
        known_names.append(os.path.splitext(filename)[0])

    return known_faces, known_names

def main():
    st.title("入室")

    # カメラを開く
    video_capture = cv2.VideoCapture(0)

    # 事前に保存された顔の情報を読み込む
    known_faces, known_names = load_known_faces()

    # Streamlit上で表示する画像と名前を格納する変数
    st_image = st.empty()
    st_name = st.empty()

    # 入室のボタン
    entry_button = st.button("入室")

    while True:
        # カメラからフレームを取得
        ret, frame = video_capture.read()

        # 顔認識の処理
        face_locations = face_recognition.face_locations(frame)
        face_encodings = face_recognition.face_encodings(frame, face_locations)

        # 画像に顔の枠を描画
        for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)

            # 保存された顔との照合を行う
            matches = face_recognition.compare_faces(known_faces, face_encoding)
            name = "Unknown"

            # 照合が成功した場合、名前を取得
            face_distances = face_recognition.face_distance(known_faces, face_encoding)
            best_match_index = np.argmin(face_distances)

            if matches[best_match_index]:
                # 近似度が一定以下の場合、"Unknown"を表示
                if face_distances[best_match_index] > 0.4:
                    name = "Unknown"
                    st_name.text(name)
                else:
                    name = known_names[best_match_index]

                    # 照合が成功したらボタンを表示
                    st_name.text(name)
                    entry_clicked = entry_button

                    if entry_clicked:
                        st.text("入室しました")
        # Streamlit上で画像を表示
        st_image.image(frame, channels="BGR", width=640)


if __name__ == "__main__":
    main()

説明

現状の処理はかなり簡単なものとなっており、

def load_known_faces(directory="known_faces"):
    known_faces = []
    known_names = []

    for filename in os.listdir(directory):
        path = os.path.join(directory, filename)
        image = face_recognition.load_image_file(path)
        encoding = face_recognition.face_encodings(image)[0]
        known_faces.append(encoding)
        known_names.append(os.path.splitext(filename)[0])

    return known_faces, known_names

で同フォルダ内にあるknown_facesから人物画像を読み込み、それぞれの人物の顔の特徴量を抽出します。

その後、

    while True:
        # カメラからフレームを取得
        ret, frame = video_capture.read()

        # 顔認識の処理
        face_locations = face_recognition.face_locations(frame)
        face_encodings = face_recognition.face_encodings(frame, face_locations)

        # 画像に顔の枠を描画
        for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)

            # 保存された顔との照合を行う
            matches = face_recognition.compare_faces(known_faces, face_encoding)
            name = "Unknown"

            # 照合が成功した場合、名前を取得
            face_distances = face_recognition.face_distance(known_faces, face_encoding)
            best_match_index = np.argmin(face_distances)

            if matches[best_match_index]:
                # 近似度が一定以下の場合、"Unknown"を表示
                if face_distances[best_match_index] > 0.4:
                    name = "Unknown"
                    st_name.text(name)
                else:
                    name = known_names[best_match_index]

                    # 照合が成功したらボタンを表示
                    st_name.text(name)
                    entry_clicked = entry_button

                    if entry_clicked:
                        st.text("入室しました")
        # Streamlit上で画像を表示
        st_image.image(frame, channels="BGR", width=640)

で、カメラから一枚ずつフレームを抽出し、face_recognitionでフレームから人物の顔を認識します。

その後、認識した顔とknown_faceに登録されている顔画像の照合を行い、一定以上の近似値であった場合は該当者の名前を表示、近似値が一定以下であった場合にはUnknownを表示する形になっています。

今後の目標

今後の目標としては、データベースを接続し、メンバーの入退室状況を管理できるようにしたいです。

0
2
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
2