From 20974697429a2cd1a1d922bdefb9b2c5cc418bfc Mon Sep 17 00:00:00 2001 From: Andrew Villeneuve Date: Mon, 8 Jun 2020 20:55:26 -0700 Subject: [PATCH 1/2] Detect and report errors caused by incorrectly set dark_threshold --- src/compare.py | 25 +++++++++++++++++++++++-- src/pam.py | 4 ++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/compare.py b/src/compare.py index c316fef..3bc9d03 100644 --- a/src/compare.py +++ b/src/compare.py @@ -66,6 +66,8 @@ user = sys.argv[1] models = [] # Encoded face models encodings = [] +# Amount of ignored 100% black frames +black_tries = 0 # Amount of ingnored dark frames dark_tries = 0 # Total amount of frames captured @@ -170,7 +172,9 @@ end_report = config.getboolean("debug", "end_report") # Start the read loop frames = 0 +valid_frames = 0 timings["fr"] = time.time() +dark_running_total = 0 while True: # Increment the frame count every loop @@ -178,6 +182,11 @@ while True: # Stop if we've exceded the time limit if time.time() - timings["fr"] > timeout: + average_darkness = dark_running_total / frames + if (dark_tries == valid_frames ): + print("All frames were too dark, please check dark_threshold in config") + print("Average darkness: " + str(dark_running_total / valid_frames) + ", Threshold: " + str(dark_threshold)) + stop(13) stop(11) # Grab a single frame of video @@ -202,9 +211,20 @@ while True: # All values combined for percentage calculation hist_total = np.sum(hist) - # If the image is fully black or the frame exceeds threshold, + # Calculate frame darkness + darkness = (hist[0] / hist_total * 100) + + # If the image is fully black due to a bad camera read, # skip to the next frame - if hist_total == 0 or (hist[0] / hist_total * 100 > dark_threshold): + if (hist_total == 0) or (darkness == 100): + black_tries += 1 + continue + + dark_running_total += darkness + valid_frames += 1 + # If the image exceeds darkness threshold due to subject distance, + # skip to the next frame + if (darkness > dark_threshold): dark_tries += 1 continue @@ -263,6 +283,7 @@ while True: # Show the total number of frames and calculate the FPS by deviding it by the total scan time print("\nFrames searched: %d (%.2f fps)" % (frames, frames / timings["fr"])) + print("Black frames ignored: %d " % (black_tries, )) print("Dark frames ignored: %d " % (dark_tries, )) print("Certainty of winning frame: %.3f" % (match * 10, )) diff --git a/src/pam.py b/src/pam.py index 3d44114..ea8ae16 100644 --- a/src/pam.py +++ b/src/pam.py @@ -50,6 +50,10 @@ def doAuth(pamh): # Status 12 means we aborted elif status == 12: return pamh.PAM_AUTH_ERR + # Status 13 means the image was too dark + elif status == 13: + pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Face detection image too dark")) + return pamh.PAM_AUTH_ERR # Status 0 is a successful exit elif status == 0: # Show the success message if it isn't suppressed From f6629776d840b08fae55cabae7bfcac4e149b5e5 Mon Sep 17 00:00:00 2001 From: Andrew Villeneuve Date: Tue, 9 Jun 2020 12:30:45 -0700 Subject: [PATCH 2/2] Added darkness detection to face registration logic --- src/cli/add.py | 46 +++++++++++++++++++++++++++++++++++++--------- src/compare.py | 1 - 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/cli/add.py b/src/cli/add.py index e97c627..8b489b3 100644 --- a/src/cli/add.py +++ b/src/cli/add.py @@ -135,12 +135,22 @@ time.sleep(2) # Will contain found face encodings enc = [] -# Count the amount or read frames +# Count the number of read frames frames = 0 +# Count the number of illuminated read frames +valid_frames = 0 +# Count the number of illuminated frames that +# were rejected for being too dark +dark_tries = 0 +# Track the running darkness total +dark_running_total = 0 +face_locations = None + dark_threshold = config.getfloat("video", "dark_threshold") # Loop through frames till we hit a timeout while frames < 60: + frames += 1 # Grab a single frame of video # Don't remove ret, it doesn't work without it ret, frame = video_capture.read() @@ -151,12 +161,23 @@ while frames < 60: # All values combined for percentage calculation hist_total = np.sum(hist) - # If the image is fully black or the frame exceeds threshold, + # Calculate frame darkness + darkness = (hist[0] / hist_total * 100) + + # If the image is fully black due to a bad camera read, # skip to the next frame - if hist_total == 0 or (hist[0] / hist_total * 100 > dark_threshold): + if (hist_total == 0) or (darkness == 100): continue - frames += 1 + # Include this frame in calculating our average session brightness + dark_running_total += darkness + valid_frames += 1 + + # If the image exceeds darkness threshold due to subject distance, + # skip to the next frame + if (darkness > dark_threshold): + dark_tries += 1 + continue # Get all faces from that frame as encodings face_locations = face_detector(gsframe, 1) @@ -167,12 +188,19 @@ while frames < 60: video_capture.release() -# If more than 1 faces are detected we can't know wich one belongs to the user -if len(face_locations) > 1: - print("Multiple faces detected, aborting") +# If we've found no faces, try to determine why +if face_locations is None or not face_locations: + if valid_frames == 0: + print("Camera saw only black frames - is IR emitter working?") + elif valid_frames == dark_tries: + print("All frames were too dark, please check dark_threshold in config") + print("Average darkness: " + str(dark_running_total / valid_frames) + ", Threshold: " + str(dark_threshold)) + else: + print("No face detected, aborting") sys.exit(1) -elif not face_locations: - print("No face detected, aborting") +# If more than 1 faces are detected we can't know wich one belongs to the user +elif len(face_locations) > 1: + print("Multiple faces detected, aborting") sys.exit(1) face_location = face_locations[0] diff --git a/src/compare.py b/src/compare.py index 3bc9d03..8f3356d 100644 --- a/src/compare.py +++ b/src/compare.py @@ -182,7 +182,6 @@ while True: # Stop if we've exceded the time limit if time.time() - timings["fr"] > timeout: - average_darkness = dark_running_total / frames if (dark_tries == valid_frames ): print("All frames were too dark, please check dark_threshold in config") print("Average darkness: " + str(dark_running_total / valid_frames) + ", Threshold: " + str(dark_threshold))