Commit e296995d authored by Kyle Anderson's avatar Kyle Anderson

Merge branch 'diagnose-lag' into 'master'

Optimize for RPi

See merge request !5
parents a3401c72 d2fe3f8d
......@@ -15,7 +15,8 @@ import data_handler
TIMEOUT: float = 30.0
# Minimum number of frames in which a user must be recognized in order to be authenticated.
MIN_USER_RECOGNITION_COUNT = 10
USER_IDS_KEY: str = "user_ids"
DEFAULT_CAMERA: int = 0
DEFAULT_WIDTH: int = 275
def load_encodings(file_location: str):
......@@ -72,14 +73,25 @@ def draw_rectangles_and_user_ids(image_frame, conversion: float, box_user_id_map
common.display_frame(image_frame)
def run_face_recognition(frame, known_faces: dict, encoding_model: str = "hog", draw_rectangles: bool = False) -> list:
def run_face_recognition(frame, known_faces: dict, encoding_model: str = "hog", draw_rectangles: bool = False,
image_width: int = DEFAULT_WIDTH) -> list:
"""
:param frame: The frame to use in recognition.
:param known_faces: The known faces data.
:param encoding_model: The type of encoding model to use. CNN is more reliable but much slower, HOG is faster.
:param draw_rectangles: True to draw the rectangles and user ids around identified faces, false otherwise.
:param image_width: The width to which images should be resized in order to speed up processing.
Lower quality means faster but less reliable recognition.
:return: The list of recognized user ids.
"""
recognized_user_ids: list = []
original_frame = frame
# Convert input from BGR to RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Resize image to width of 750 PX to speed up processing.
rgb_image = imutils.resize(frame, width=750)
# Resize image to speed up processing.
rgb_image = imutils.resize(frame, width=image_width)
r = frame.shape[1] / float(rgb_image.shape[1])
# Detect the location of each face and determine the boxes in which they lie
......@@ -103,12 +115,12 @@ def run_face_recognition(frame, known_faces: dict, encoding_model: str = "hog",
def recognize_user(known_faces: dict, encoding_model: str = "hog", image_flip: int = None,
draw_rectangles: bool = False):
draw_rectangles: bool = False, camera: int = DEFAULT_CAMERA, image_width: int = DEFAULT_WIDTH):
"""Attempts to recognize a user.
Returns the ID of the user if identified, or None if no users are identified."""
recognized_users_count = {}
recognized_user = None
video_stream = common.start_video_stream(0)
video_stream = common.start_video_stream(camera)
# Determine the time at which we will time out. Equal to current time + timeout.
timeout_time: float = time.time() + TIMEOUT
......@@ -119,7 +131,8 @@ def recognize_user(known_faces: dict, encoding_model: str = "hog", image_flip: i
image_frame = cv2.flip(image_frame, image_flip)
recognized_user_ids = run_face_recognition(image_frame, known_faces, encoding_model=encoding_model,
draw_rectangles=draw_rectangles)
draw_rectangles=draw_rectangles, image_width=image_width)
for user_id in recognized_user_ids:
if user_id not in recognized_users_count:
recognized_users_count[user_id] = 0
......@@ -140,18 +153,22 @@ def recognize_user(known_faces: dict, encoding_model: str = "hog", image_flip: i
def recognize_user_from_database(database_loc: str = common.DATABASE_LOC, encoding_model: str = "hog",
image_flip: int = None, draw_rectangles: bool = False):
image_flip: int = None, draw_rectangles: bool = False, camera: int = DEFAULT_CAMERA,
image_width: int = DEFAULT_WIDTH):
"""
Recognizes a user
:param database_loc: The database containing the face encodings for users.
:param encoding_model: The encoding model to be used for recognition.
:param image_flip: The type of image flip to be applied to the image, if it will be upside-down or horizontally inverted.
:param draw_rectangles: True to draw the rectangles to the screen, false otherwise.
:param camera: Which camera to use
:param image_width: The width to which images should be resized in order to speed up processing.
Lower quality means faster but less reliable recognition.
:return: The recognized user's id, or None if no user was recognized.
"""
return recognize_user(data_handler.load_database(database_loc), encoding_model=encoding_model,
image_flip=image_flip,
draw_rectangles=draw_rectangles)
draw_rectangles=draw_rectangles, camera=camera, image_width=image_width)
# If this program is the main program, authenticate the user.
......@@ -170,6 +187,10 @@ if __name__ == "__main__":
required=False, default=None, choices=[0, 1])
parser.add_argument("--show", "-s", action="store_true",
help="Include this argument to have the image shown to you.", default=False)
parser.add_argument("--camera", "-c", type=int, required=False,
help="Which camera to be used during authentication.", default=DEFAULT_CAMERA)
parser.add_argument("--width", "-w", type=int, required=False,
help=f"The image width to use, in pixels. Default is {DEFAULT_WIDTH} pixels.")
args = parser.parse_args()
args_dict = {}
......@@ -179,6 +200,6 @@ if __name__ == "__main__":
args_dict["encoding_model"] = args.model
user = recognize_user_from_database(**args_dict, image_flip=args.flip,
draw_rectangles=args.show)
draw_rectangles=args.show, camera=args.camera, image_width=args.width)
if user:
print(f"Recognized user {user}.")
......@@ -22,7 +22,7 @@ def display_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 = cv2.VideoCapture(0)
video_stream = cv2.VideoCapture(camera)
return video_stream
......
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