Commit d8f897a1 authored by Kyle Anderson's avatar Kyle Anderson

Prepare for user registration

Still preparing for user registration stuff. Made some changes to
authentication to make some of its general methods available for the
user registration module as well.
parent ccc1ae8c
...@@ -5,31 +5,22 @@ Methods for authenticating a user. ...@@ -5,31 +5,22 @@ Methods for authenticating a user.
from imutils.video import VideoStream from imutils.video import VideoStream
import face_recognition import face_recognition
import imutils import imutils
import pickle
import time import time
import cv2 import cv2
import common
from data_handler import load_database
# How long to wait before timing out and saying failed authentication. # How long to wait before timing out and saying failed authentication.
TIMEOUT: float = 30.0 TIMEOUT: float = 30.0
# 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
image_writer = None USER_IDS_KEY: str = "user_ids"
USER_IDS_KEY: str = "names" # TODO change
def load_encodings(file_location: str): def load_encodings(file_location: str):
"""Loads the encodings for faces from the given file location.""" """Loads the encodings for faces from the given file location."""
with open(file_location, "rb") as encodings_file: return load_database(file_location)
encodings = pickle.loads(encodings_file.read())
return encodings
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."""
video_stream = VideoStream(src=camera).start()
time.sleep(2.0)
return video_stream
def determine_identity(face_encoding, known_faces): def determine_identity(face_encoding, known_faces):
...@@ -77,15 +68,10 @@ def draw_rectanges_and_user_ids(image_frame, conversion: float, boxes, user_ids: ...@@ -77,15 +68,10 @@ def draw_rectanges_and_user_ids(image_frame, conversion: float, boxes, user_ids:
# Find the top so we can put the text there. # Find the top so we can put the text there.
y = top - 15 if top - 15 > 15 else top + 15 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) cv2.putText(image_frame, user_id, (left, y), cv2.FONT_HERSHEY_PLAIN, 0.75, (0, 255, 0), 2)
display_frame(image_frame) common.display_frame(image_frame)
def display_frame(frame):
"""Displays the frame to the user."""
cv2.imshow("Frame", frame)
def recognize_user(encodings_location: str = "./encodings.pickle", encoding_model: str = "hog", image_flip: int = None, def recognize_user(known_faces: dict, encoding_model: str = "hog", image_flip: int = None,
draw_rectangles=False): draw_rectangles=False):
"""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.
...@@ -93,9 +79,7 @@ def recognize_user(encodings_location: str = "./encodings.pickle", encoding_mode ...@@ -93,9 +79,7 @@ def recognize_user(encodings_location: str = "./encodings.pickle", encoding_mode
track of how many times each user was recognized.""" 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) # TODO add back video_stream = common.start_video_stream(0)
video_stream = VideoStream(src=0).start() # TODO remove
known_faces = load_encodings(encodings_location)
# 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
...@@ -158,7 +142,7 @@ if __name__ == "__main__": ...@@ -158,7 +142,7 @@ if __name__ == "__main__":
parser.add_argument("--show", "-s", action="store_true", parser.add_argument("--show", "-s", action="store_true",
help="Include this argument to have the image shown to you.", default=False) help="Include this argument to have the image shown to you.", default=False)
args = parser.parse_args() args = parser.parse_args()
user = recognize_user(encoding_model=args.model, encodings_location=args.encodings, image_flip=args.flip, user = recognize_user(encoding_model=args.model, encodings=load_encodings(args.encodings), image_flip=args.flip,
draw_rectangles=args.show) draw_rectangles=args.show)
if user: if user:
print(f"Recognized user {user}.") print(f"Recognized user {user}.")
import time
import cv2
from imutils.video import VideoStream
USER_IDS_KEY = "user_ids"
def display_frame(frame):
"""Displays the frame to the user."""
cv2.imshow("Frame", frame)
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."""
video_stream = VideoStream(src=camera).start()
time.sleep(2.0)
return video_stream
"""
Creates a facial recognition profile for a new user.
"""
"""
General IO for pickle database operations.
"""
import pickle
def load_database(file_location: str):
"""
Attempts to load the pickle database at the given file location
:param file_location: String location of file to be loaded.
:return: The loaded pickle database.
"""
with open(file_location, "rb") as database:
file_content = pickle.load(database)
return file_content
def write_database(output_file: str, database_content: dict) -> None:
"""
Writes the dictionary database to the given file location
:param output_file: The location of the file to be outputted on.
:param database_content: The database content to be written to the file.
:return: None
"""
with open(output_file, "wb") as output:
output.write(pickle.dump(database_content, output))
"""
Creates a facial recognition profile for a new user.
"""
from common import USER_IDS_KEY, start_video_stream
import face_recognition
import cv2
def process_image(image, encoding_model: str = "hog"):
"""
Processes a single image, returning the encoded face object
:param image: The image containing the face to be processed.
:param encoding_model: The encoding model, either CNN or HOG
:return: The processed facial recognition profile encoding.
"""
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Convert between the image formats
# Detect the coordinates of the boxes corresponding to faces in the input image
boxes = face_recognition.face_locations(image_rgb, model=encoding_model)
# Actually make the encodings for the face.
return face_recognition.face_encodings(image_rgb, boxes)
def register_user(user_id: str, encoding_model="hog", image_flip: int = None, video_source=None):
"""
Function for registering a new user using the given video source. If video source isn't provided, then the camera
on id 0 is used.
:param user_id: The user id for the user that is being registered.
:param encoding_model: The type of encoding model. Must be either "hog" or "cnn". HOG is faster, CNN is more thorough.
:param image_flip: The integer by which this image should be flipped. 0 for reflect about x-axis, 1 for reflect on y-axis
:return: Encoded face that was detected, or None if no face was detected or if there was another error.
"""
if video_source is None:
video_source = start_video_stream(0)
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