Cleanup
This commit is contained in:
parent
47acb8f729
commit
542549934b
4 changed files with 58 additions and 2 deletions
21
compair.py
21
compair.py
|
|
@ -1,49 +1,66 @@
|
|||
# Compair incomming video with known faces
|
||||
# Running in a local python instance to get around PATH issues
|
||||
|
||||
# Import required modules
|
||||
import face_recognition
|
||||
import cv2
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
# Import config
|
||||
import config
|
||||
|
||||
def stop(status):
|
||||
"""Stop the execution and close video stream"""
|
||||
video_capture.release()
|
||||
sys.exit(status)
|
||||
|
||||
# Make sure we were given an username to tast against
|
||||
try:
|
||||
if not isinstance(sys.argv[1], str):
|
||||
sys.exit(1)
|
||||
except IndexError:
|
||||
sys.exit(1)
|
||||
|
||||
# The username of the authenticating user
|
||||
user = sys.argv[1]
|
||||
# List of known faces, encoded by face_recognition
|
||||
encodings = []
|
||||
# Amount of frames already matched
|
||||
tries = 0
|
||||
|
||||
# Try to load the face model from the models folder
|
||||
try:
|
||||
encodings = json.load(open(os.path.dirname(__file__) + "/models/" + user + ".dat"))
|
||||
except FileNotFoundError:
|
||||
stop(10)
|
||||
|
||||
# Verify that we have a valid model file
|
||||
if len(encodings) < 3:
|
||||
stop(1)
|
||||
|
||||
# Start video capture on the IR camera
|
||||
video_capture = cv2.VideoCapture(config.device_id)
|
||||
|
||||
while True:
|
||||
# Grab a single frame of video
|
||||
ret, frame = video_capture.read()
|
||||
|
||||
# Get all faces from that frame as encodings
|
||||
face_encodings = face_recognition.face_encodings(frame)
|
||||
|
||||
# Loop through each face in this frame of video
|
||||
# Loop through each face
|
||||
for face_encoding in face_encodings:
|
||||
# Match this found face against a known face
|
||||
matches = face_recognition.face_distance(encodings, face_encoding)
|
||||
|
||||
# Check if any match is certain enough to be the user we're looking for
|
||||
for match in matches:
|
||||
if match < config.certainty:
|
||||
if match < config.certainty and match > 0:
|
||||
stop(0)
|
||||
|
||||
# Stop if we've exceded the maximum retry count
|
||||
if tries > config.frame_count:
|
||||
stop(11)
|
||||
|
||||
|
|
|
|||
22
learn.py
22
learn.py
|
|
@ -1,3 +1,6 @@
|
|||
# Save the face of the user in encoded form
|
||||
|
||||
# Import required modules
|
||||
import face_recognition
|
||||
import subprocess
|
||||
import time
|
||||
|
|
@ -5,58 +8,77 @@ import os
|
|||
import sys
|
||||
import json
|
||||
|
||||
# Import config and extra functions
|
||||
import config
|
||||
import utils
|
||||
|
||||
def captureFrame(delay):
|
||||
"""Capture and encode 1 frame of video"""
|
||||
|
||||
# Call fswebcam to save a frame to /tmp with a set delay
|
||||
subprocess.call(["fswebcam", "-S", str(delay), "--no-banner", "-d", "/dev/video" + str(config.device_id), tmp_file], stderr=open(os.devnull, "wb"))
|
||||
|
||||
# Get the faces in htat image
|
||||
ref = face_recognition.load_image_file(tmp_file)
|
||||
enc = face_recognition.face_encodings(ref)
|
||||
|
||||
# If 0 faces are detected we can't continue
|
||||
if len(enc) == 0:
|
||||
print("No face detected, aborting")
|
||||
sys.exit()
|
||||
# If more than 1 faces are detected we can't know wich one belongs to the user
|
||||
if len(enc) > 1:
|
||||
print("Multiple faces detected, aborting")
|
||||
sys.exit()
|
||||
|
||||
clean_enc = []
|
||||
|
||||
# Copy the values into a clean array so we can export it as JSON later on
|
||||
for point in enc[0]:
|
||||
clean_enc.append(point)
|
||||
|
||||
encodings.append(clean_enc)
|
||||
|
||||
# The current user
|
||||
user = os.environ.get("USER")
|
||||
# The name of the tmp frame file to user
|
||||
tmp_file = "/tmp/howdy_" + user + ".jpg"
|
||||
# The permanent file to store the encoded model in
|
||||
enc_file = "./models/" + user + ".dat"
|
||||
# Known encodings
|
||||
encodings = []
|
||||
|
||||
# Make the ./models folder if it doesn't already exist
|
||||
if not os.path.exists("models"):
|
||||
print("No face model folder found, creating one")
|
||||
os.makedirs("models")
|
||||
|
||||
# To try read a premade encodings file if it exists
|
||||
try:
|
||||
encodings = json.load(open(enc_file))
|
||||
except FileNotFoundError:
|
||||
encodings = False
|
||||
|
||||
# If a file does exist, ask the user what needs to be done
|
||||
if encodings != False:
|
||||
encodings = utils.print_menu(encodings)
|
||||
|
||||
print("\nLearning face for the user account " + user)
|
||||
print("Please look straight into the camera for 5 seconds")
|
||||
|
||||
# Give the user time to read
|
||||
time.sleep(2)
|
||||
|
||||
# Capture with 3 different delays to simulate different camera exposures
|
||||
for delay in [30, 6, 0]:
|
||||
time.sleep(.3)
|
||||
captureFrame(delay)
|
||||
|
||||
# Save the new encodings to disk
|
||||
with open(enc_file, "w") as datafile:
|
||||
json.dump(encodings, datafile)
|
||||
|
||||
# Remove any left over temp files
|
||||
os.remove(tmp_file)
|
||||
|
||||
print("Done.")
|
||||
|
|
|
|||
14
pam.py
14
pam.py
|
|
@ -1,31 +1,45 @@
|
|||
# PAM interface in python, launches compair.py
|
||||
|
||||
# Import required modules
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
def doAuth(pamh):
|
||||
"""Start authentication in a seperate process"""
|
||||
|
||||
# Run compair as python3 subprocess to circumvent python version and import issues
|
||||
status = subprocess.call(["python3", os.path.dirname(__file__) + "/compair.py", pamh.get_user()])
|
||||
|
||||
# Status 10 means we couldn't find any face models
|
||||
if status == 10:
|
||||
print("No face model is known for this user, skiping")
|
||||
return pamh.PAM_SYSTEM_ERR
|
||||
# Status 11 means we exceded the maximum retry count
|
||||
if status == 11:
|
||||
print("Timeout reached, could not find a known face")
|
||||
return pamh.PAM_SYSTEM_ERR
|
||||
# Status 0 is a successful exit
|
||||
if status == 0:
|
||||
print("Identified face as " + os.environ.get("USER"))
|
||||
return pamh.PAM_SUCCESS
|
||||
|
||||
# Otherwise, we can't discribe what happend but it wasn't successful
|
||||
print("Unknown error: " + str(status))
|
||||
return pamh.PAM_SYSTEM_ERR
|
||||
|
||||
def pam_sm_authenticate(pamh, flags, args):
|
||||
"""Called by PAM when the user wants to authenticate, in sudo for example"""
|
||||
return doAuth(pamh)
|
||||
|
||||
def pam_sm_open_session(pamh, flags, args):
|
||||
"""Called when starting a session, such as su"""
|
||||
return doAuth(pamh)
|
||||
|
||||
def pam_sm_close_session(pamh, flags, argv):
|
||||
"""We don't need to clean anyting up at the end of a session, so return true"""
|
||||
return pamh.PAM_SUCCESS
|
||||
|
||||
def pam_sm_setcred(pamh, flags, argv):
|
||||
"""We don't need set any credentials, so return true"""
|
||||
return pamh.PAM_SUCCESS
|
||||
|
|
|
|||
3
utils.py
3
utils.py
|
|
@ -1,4 +1,7 @@
|
|||
# Useful support functions
|
||||
|
||||
def print_menu(encodings):
|
||||
"""Show a menu asking the user what he wants to do"""
|
||||
if len(encodings) == 3:
|
||||
print("There is 1 existing face model for this user")
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in a new issue