Commit 04489fd1 authored by Kyle Anderson's avatar Kyle Anderson

Working register + authenticate user

The registering and authentication of users now works together nicely. Will continue with making it more efficient and integration with the react side.
parent 9505915c
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
Methods for authenticating a user. Methods for authenticating a user.
""" """
from imutils.video import VideoStream
import face_recognition
import imutils
import time import time
import cv2 import cv2
import face_recognition
import imutils
import common import common
from data_handler import load_database from data_handler import load_database
...@@ -24,23 +24,20 @@ def load_encodings(file_location: str): ...@@ -24,23 +24,20 @@ def load_encodings(file_location: str):
def determine_identity(face_encoding, known_faces): def determine_identity(face_encoding, known_faces):
"""Determines the most likely identity of a single face. Returns the user id.""" """
matches = face_recognition.compare_faces( "Determines the most likely identity of a single face. Returns the user id.
known_faces["encodings"], face_encoding) :param face_encoding: The encoding which needs identification.
matched_user = '' :param known_faces: The database of known faces to use for searching.
matched_user_id_count = {} :return: The string user_id of the recognized user.
"""
# If there is at least one match to a face in the database, figure out which one it is. recognized_users = {}
if True in matches: for (user_id, user_encodings) in known_faces.items():
matched_users = [user_index for ( matches = face_recognition.compare_faces(user_encodings, face_encoding)
user_index, is_match) in enumerate(matches) if is_match] # Count the number of occurrences of true.
recognized_users[user_id] = matches.count(True)
for i in matched_users:
user_id: str = known_faces[USER_IDS_KEY][i] matched_user: str = max(recognized_users,
matched_user_id_count[user_id] = matched_user_id_count.get(user_id, 0) + 1 key=recognized_users.get)
matched_user: str = max(matched_user_id_count,
key=matched_user_id_count.get)
return matched_user return matched_user
...@@ -54,10 +51,10 @@ def check_recognized_users(recognized_user_counts): ...@@ -54,10 +51,10 @@ def check_recognized_users(recognized_user_counts):
return recognized_users return recognized_users
def draw_rectanges_and_user_ids(image_frame, conversion: float, boxes, user_ids: list): def draw_rectanges_and_user_ids(image_frame, conversion: float, box_user_id_map: dict):
"""Draws the rectangles and user_ids onto the video stream so anyone viewing the stream could see them.""" """Draws the rectangles and user_ids onto the video stream so anyone viewing the stream could see them."""
if boxes and user_ids and len(user_ids) > 0: if box_user_id_map and len(box_user_id_map) > 0:
for ((top, right, bottom, left), user_id) in zip(boxes, user_ids): for ((top, right, bottom, left), user_id) in box_user_id_map.items():
top = round(top * conversion) top = round(top * conversion)
right = round(right * conversion) right = round(right * conversion)
bottom = round(bottom * conversion) bottom = round(bottom * conversion)
...@@ -98,25 +95,27 @@ def recognize_user(known_faces: dict, encoding_model: str = "hog", image_flip: i ...@@ -98,25 +95,27 @@ def recognize_user(known_faces: dict, encoding_model: str = "hog", image_flip: i
# Detect the location of each face and determine the boxes in which they lie # Detect the location of each face and determine the boxes in which they lie
boxes = face_recognition.face_locations( boxes = face_recognition.face_locations(
rgb_image, model=encoding_model) rgb_image, model=encoding_model)
# Computer the facial embeddings (the encoding) at # Compute the facial embeddings (the encoding) at
# each of the locations found in the previous line. # each of the locations found in the previous line.
encodings = face_recognition.face_encodings(rgb_image, boxes) encodings = face_recognition.face_encodings(rgb_image, boxes)
for encoding in encodings: box_user_id_mapping = {}
for (i, encoding) in enumerate(encodings):
user_id: str = determine_identity(encoding, known_faces) user_id: str = determine_identity(encoding, known_faces)
if user_id: if user_id:
if user_id not in recognized_users_count: if user_id not in recognized_users_count:
recognized_users_count[user_id] = 0 recognized_users_count[user_id] = 0
recognized_users_count[user_id] += 1 recognized_users_count[user_id] += 1
box_user_id_mapping[boxes[i]] = user_id
if draw_rectangles: if draw_rectangles:
draw_rectanges_and_user_ids(image_frame, r, boxes, list(known_faces[USER_IDS_KEY])) draw_rectanges_and_user_ids(image_frame, r, box_user_id_mapping)
# Now check if we have already positively identified a user enough times # Now check if we have already positively identified a user enough times
recognized_users = check_recognized_users(recognized_users_count) recognized_users = check_recognized_users(recognized_users_count)
if len(recognized_users) > 0: if len(recognized_users) > 0:
break break
cv2.waitKey(1) # Required or else video stream doesn't really render. cv2.waitKey(20) # Required or else video stream doesn't really render.
if recognized_users_count: if recognized_users_count:
recognized_user = max(recognized_users_count, recognized_user = max(recognized_users_count,
......
...@@ -3,7 +3,6 @@ import time ...@@ -3,7 +3,6 @@ import time
import cv2 import cv2
from imutils.video import VideoStream from imutils.video import VideoStream
USER_IDS_KEY = "user_ids"
DATABASE_LOC = "./dataset/faces.pickle" DATABASE_LOC = "./dataset/faces.pickle"
......
""" """
Creates a facial recognition profile for a new user. Creates a facial recognition profile for a new user.
""" """
import os
import cv2
import face_recognition
import common import common
import data_handler import data_handler
from common import USER_IDS_KEY, start_video_stream
import face_recognition
import cv2
import os
def process_image(image, encoding_model: str = "hog"): def process_image(image, encoding_model: str = "hog"):
...@@ -21,7 +22,8 @@ def process_image(image, encoding_model: str = "hog"): ...@@ -21,7 +22,8 @@ def process_image(image, encoding_model: str = "hog"):
# Detect the coordinates of the boxes corresponding to faces in the input image # Detect the coordinates of the boxes corresponding to faces in the input image
boxes = face_recognition.face_locations(image_rgb, model=encoding_model) boxes = face_recognition.face_locations(image_rgb, model=encoding_model)
# Actually make the encodings for the face. # Actually make the encodings for the face.
return face_recognition.face_encodings(image_rgb, boxes) # Only want the first recognized face
return face_recognition.face_encodings(image_rgb, [boxes[0]]) if boxes and len(boxes) > 0 else []
def register_user(user_id: str, dataset_dir: str, encoding_model="hog", database_loc: str = common.DATABASE_LOC, def register_user(user_id: str, dataset_dir: str, encoding_model="hog", database_loc: str = common.DATABASE_LOC,
...@@ -41,11 +43,11 @@ def register_user(user_id: str, dataset_dir: str, encoding_model="hog", database ...@@ -41,11 +43,11 @@ def register_user(user_id: str, dataset_dir: str, encoding_model="hog", database
# Might want to check file validity here at some point, but won't for now. # Might want to check file validity here at some point, but won't for now.
image = cv2.imread(full_path) image = cv2.imread(full_path)
if image is not None: if image is not None:
processed = process_image(image, encoding_model=encoding_model)
if show_output: if show_output:
print(f"Processing image {i + 1}") print(f"Processing image {i + 1}")
processed = process_image(image, encoding_model=encoding_model)
if processed: if processed:
processed_images.append(processed) processed_images.extend(processed)
if len(processed_images) > 0: # Only do things if we actually have stuff to add. if len(processed_images) > 0: # Only do things if we actually have stuff to add.
user_info = data_handler.load_database(database_loc) user_info = data_handler.load_database(database_loc)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment