Commit 92ff71a8 authored by Kyle Anderson's avatar Kyle Anderson

Fixup authenticate user

Just fixing up some of the basic errors that were in the authenticate
user file. Still untested, no idea if it will work.
parent 7dac19f8
...@@ -4,7 +4,6 @@ Methods for authenticating a user. ...@@ -4,7 +4,6 @@ Methods for authenticating a user.
from imutils.video import VideoStream from imutils.video import VideoStream
import face_recognition import face_recognition
import argparse
import imutils import imutils
import pickle import pickle
import time import time
...@@ -16,85 +15,122 @@ TIMEOUT: float = 30.0 ...@@ -16,85 +15,122 @@ TIMEOUT: float = 30.0
ENCODING_MODEL: str = "hog" ENCODING_MODEL: str = "hog"
# Minimum number of frames in which a user must be recognized in order to be authenticated. # Minimum number of frames in which a user must be recognized in order to be authenticated.
MIN_USER_RECOGNITION_COUNT = 10 MIN_USER_RECOGNITION_COUNT = 10
draw_rectangles: bool = False
image_writer = None
def load_encodings(file_location: str): def load_encodings(file_location: str):
"""Loads the encodings for faces from the given file location."""
with open(file_location, "rb") as encodings_file: with open(file_location, "rb") as encodings_file:
encodings = pickle.loads(encodings_file.read()) encodings = pickle.loads(encodings_file.read())
return encodings return encodings
def start_video_stream(camera: int): def start_video_stream(camera: int):
"""Starts the video stream and returns the created stream. Also waits for the video stream to open before returning it.""" """Starts the video stream and returns the created stream.
Also waits for the video stream to open before returning it."""
video_stream = VideoStream(src=camera) video_stream = VideoStream(src=camera)
time.sleep(2.0) time.sleep(2.0)
return video_stream return video_stream
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""" """Determines the most likely identity of a single face. Returns the user id."""
matches = face_recognition.compare_faces(known_faces["encodings"], face_encoding) matches = face_recognition.compare_faces(
known_faces["encodings"], face_encoding)
matched_user = None matched_user = None
# If there is at least one match to a face in the database, figure out which one it is. # If there is at least one match to a face in the database, figure out which one it is.
if True in matches: if True in matches:
matched_user_id_count = {} matched_user_id_count = {}
matched_users = [user_index for (user_index, is_match) in enumerate(matches) if is_match] matched_users = [user_index for (
user_index, is_match) in enumerate(matches) if is_match]
for i in matched_users:
user_id: str = known_faces["user_ids"][i] for i in matched_users:
matched_user_id_count[user_id] = matched_user_id_count.get(user_id, 0) + 1 user_id: str = known_faces["user_ids"][i]
matched_user_id_count[user_id] = matched_user_id_count.get(
matched_user: str = max(matched_user_id_count, keys=matched_user_id_count.get()) user_id, 0) + 1
matched_user: str = max(matched_user_id_count,
keys=matched_user_id_count.get())
return matched_user return matched_user
def check_recognized_users(recognized_user_counts): def check_recognized_users(recognized_user_counts):
"""Determines if there are recognized users in the dictionary, and if so returns the list of their IDs""" """Determines if there are recognized users in the dictionary,
and if so returns the list of their IDs"""
recognized_users = [] recognized_users = []
for ((user_id, count) in recognized_user_counts): for user_id, count in recognized_user_counts.items():
if count >= MIN_USER_RECOGNITION_COUNT: if count >= MIN_USER_RECOGNITION_COUNT:
recognized_users.append(user_id) recognized_users.append(user_id)
return recognized_users return recognized_users
def draw_rectanges_and_user_ids(image_frame, conversion: float, boxes, user_ids: list):
"""Draws the rectangles and user_ids onto the video stream so anyone viewing the stream could see them."""
for ((top, right, bottom, left), user_id) in zip(boxes, user_ids):
top = round(top * conversion)
right = round(right * conversion)
bottom = round(bottom * conversion)
left = round(left * conversion)
# Draw the rectangle onto the face we've identified
cv2.rectangle(image_frame, (left, top), (right, bottom), (0, 255, 0), 2)
# Find the top so we can put the text there.
y = top - 15 if top - 15 > 15 else top + 15
cv2.putText(image_frame, user_id, (left, y), cv2.FONT_HERSHEY_PLAIN, 0.75, (0, 255, 0), 2)
display_frame(image_frame)
def display_frame(frame):
"""Displays the frame to the user."""
cv2.imshow("Frame", frame)
def recognize_user(): def recognize_user():
"""Attempts to recognize a user. """Attempts to recognize a user.
Returns the ID of the user if identified, or None if no users are identified.""" Returns the ID of the user if identified, or None if no users are identified.
# Dictionary of the form { "user_id": #frames_recognized } to keep track of how many times each user was recognized. Dictionary of the form { "user_id": #frames_recognized } to keep
track of how many times each user was recognized."""
recognized_users_count = {} recognized_users_count = {}
recognized_user = None recognized_user = None
video_stream = start_video_stream(0) video_stream = start_video_stream(0)
known_faces = load_encodings() known_faces = load_encodings("./encodings.pickle")
user_recognized: bool = False user_recognized: bool = False
# Determine the time at which we will time out. Equal to current time + timeout. # Determine the time at which we will time out. Equal to current time + timeout.
timeout_time: float = time.time() + TIMEOUT timeout_time: float = time.time() + TIMEOUT
while (time.time() < timeout_time and not user_recognized): while (time.time() < timeout_time and not user_recognized):
# Read a frame from the videostream. # Read a image_frame from the videostream.
frame = video_stream.read() image_frame = video_stream.read()
# Convert input from BGR to RGB # Convert input from BGR to RGB
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) rgb_image = cv2.cvtColor(image_frame, cv2.COLOR_BGR2RGB)
# Resize image to width of 750 PX to speed up processing. # Resize image to width of 750 PX to speed up processing.
rgb_image = imutils.resize(frame, width=750) rgb_image = imutils.resize(image_frame, width=750)
r = frame.shape[1] / float(rgb_image.shape[1]) r = image_frame.shape[1] / float(rgb_image.shape[1])
# Detect the location of each face and put a rectangle around it # Detect the location of each face and put a rectangle around it
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 each of the locations found in the previous line. # Computer the facial embeddings (the encoding) at
# 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: for encoding in encodings:
user_id: str = determine_identity(encoding, known_faces) user_id: str = determine_identity(encoding, known_faces)
if user_id: if user_id:
recognized_users_count[user_id] += 1 recognized_users_count[user_id] += 1
if draw_rectangles:
draw_rectanges_and_user_ids(image_frame, r, boxes, known_faces.keys)
# 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:
user_recognized = True user_recognized = True
break break
recognized_user = max(recognized_users_count, keys=recognized_users_count.get()) recognized_user = max(recognized_users_count,
keys=recognized_users_count.get())
if recognized_users_count[recognized_user] < MIN_USER_RECOGNITION_COUNT: if recognized_users_count[recognized_user] < MIN_USER_RECOGNITION_COUNT:
recognized_user = None recognized_user = None
return recognized_user return recognized_user
......
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