Implemented conversations and better config
This commit is contained in:
parent
542549934b
commit
7b9db83ad0
6 changed files with 45 additions and 28 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -102,6 +102,3 @@ ENV/
|
||||||
|
|
||||||
# generated models
|
# generated models
|
||||||
/models
|
/models
|
||||||
|
|
||||||
# config file
|
|
||||||
config.py
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ sudo apt install libpam-python fswebcam libopencv-dev python-opencv
|
||||||
|
|
||||||
After that, install the face_recognition python module. There's an excellent step by step guide on how to do this on [its github page](https://github.com/ageitgey/face_recognition#installation).
|
After that, install the face_recognition python module. There's an excellent step by step guide on how to do this on [its github page](https://github.com/ageitgey/face_recognition#installation).
|
||||||
|
|
||||||
In the root of your cloned repo is a file called `config_template.py`. Duplicate this file and call it `config.py`. The `device_id` variable in this file is important, make sure it is the IR camera and not your normal webcam.
|
In the root of your cloned repo is a file called `config.ini`. The `device_id` variable in this file is important, make sure it is the IR camera and not your normal webcam.
|
||||||
|
|
||||||
Now it's time to let Howdy learn your face. The learn.py script will make 3 models of your face and store them as an encoded set in the `models` folder. To run the script, open a terminal, navigate to this repository and run:
|
Now it's time to let Howdy learn your face. The learn.py script will make 3 models of your face and store them as an encoded set in the `models` folder. To run the script, open a terminal, navigate to this repository and run:
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ python3 learn.py
|
||||||
|
|
||||||
The script should guide you through the process.
|
The script should guide you through the process.
|
||||||
|
|
||||||
Finally we need to tell PAM that there's a new module installed. Open `/etc/pam.d/sudo` as root (`sudo nano /etc/pam.d/sudo`) and add the following line to the top of the file:
|
Finally we need to tell PAM that there's a new module installed. Open `/etc/pam.d/common-auth` as root (`sudo nano /etc/pam.d/common-auth`) and add the following line to the top of the file:
|
||||||
|
|
||||||
```
|
```
|
||||||
auth sufficient pam_python.so /path/to/pam.py
|
auth sufficient pam_python.so /path/to/pam.py
|
||||||
|
|
|
||||||
16
compair.py
16
compair.py
|
|
@ -7,9 +7,11 @@ import cv2
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import configparser
|
||||||
|
|
||||||
# Import config
|
# Read config from disk
|
||||||
import config
|
config = configparser.ConfigParser()
|
||||||
|
config.read(os.path.dirname(__file__) + "/config.ini")
|
||||||
|
|
||||||
def stop(status):
|
def stop(status):
|
||||||
"""Stop the execution and close video stream"""
|
"""Stop the execution and close video stream"""
|
||||||
|
|
@ -34,14 +36,14 @@ tries = 0
|
||||||
try:
|
try:
|
||||||
encodings = json.load(open(os.path.dirname(__file__) + "/models/" + user + ".dat"))
|
encodings = json.load(open(os.path.dirname(__file__) + "/models/" + user + ".dat"))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
stop(10)
|
sys.exit(10)
|
||||||
|
|
||||||
# Verify that we have a valid model file
|
# Verify that we have a valid model file
|
||||||
if len(encodings) < 3:
|
if len(encodings) < 3:
|
||||||
stop(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Start video capture on the IR camera
|
# Start video capture on the IR camera
|
||||||
video_capture = cv2.VideoCapture(config.device_id)
|
video_capture = cv2.VideoCapture(int(config.get("video", "device_id")))
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# Grab a single frame of video
|
# Grab a single frame of video
|
||||||
|
|
@ -57,11 +59,11 @@ while True:
|
||||||
|
|
||||||
# Check if any match is certain enough to be the user we're looking for
|
# Check if any match is certain enough to be the user we're looking for
|
||||||
for match in matches:
|
for match in matches:
|
||||||
if match < config.certainty and match > 0:
|
if match < int(config.get("video", "certainty")) and match > 0:
|
||||||
stop(0)
|
stop(0)
|
||||||
|
|
||||||
# Stop if we've exceded the maximum retry count
|
# Stop if we've exceded the maximum retry count
|
||||||
if tries > config.frame_count:
|
if tries > int(config.get("video", "frame_count")):
|
||||||
stop(11)
|
stop(11)
|
||||||
|
|
||||||
tries += 1
|
tries += 1
|
||||||
|
|
|
||||||
19
config.ini
Normal file
19
config.ini
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
[core]
|
||||||
|
# Do not print anything when a face vericication succeeds
|
||||||
|
no_confirmation = false
|
||||||
|
|
||||||
|
# When a user without a known face model tries to use this script, don't
|
||||||
|
# show an error but fail silently
|
||||||
|
supress_unknown = false
|
||||||
|
|
||||||
|
[video]
|
||||||
|
# The certainty of the detected face belonging to the user of the account
|
||||||
|
# On a scale from 1 to 10, values above 5 are not recomended
|
||||||
|
certainty = 3
|
||||||
|
|
||||||
|
# The number of frames to capture and to process before timing out
|
||||||
|
frame_count = 30
|
||||||
|
|
||||||
|
# The /dev/videoX id to capture frames from
|
||||||
|
# In my case, video0 is the normal camera and video1 is the IR version
|
||||||
|
device_id = 1
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# The certainty of the detected face belonging to the user of the account
|
|
||||||
# On a scale from 1 to 10, values above 5 are not recomended
|
|
||||||
certainty = 3
|
|
||||||
|
|
||||||
# The number of frames to capture and to process before timing out
|
|
||||||
frame_count = 80
|
|
||||||
|
|
||||||
# The /dev/videoX id to capture frames from
|
|
||||||
# On my laptop, video0 is the normal camera and video1 is the IR version
|
|
||||||
device_id = 1
|
|
||||||
21
pam.py
21
pam.py
|
|
@ -5,6 +5,13 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
# pam-python is running python 2, so we use the old module here
|
||||||
|
import ConfigParser
|
||||||
|
|
||||||
|
# Read config from disk
|
||||||
|
config = ConfigParser.ConfigParser()
|
||||||
|
config.read(os.path.dirname(__file__) + "/config.ini")
|
||||||
|
|
||||||
def doAuth(pamh):
|
def doAuth(pamh):
|
||||||
"""Start authentication in a seperate process"""
|
"""Start authentication in a seperate process"""
|
||||||
|
|
||||||
|
|
@ -13,19 +20,21 @@ def doAuth(pamh):
|
||||||
|
|
||||||
# Status 10 means we couldn't find any face models
|
# Status 10 means we couldn't find any face models
|
||||||
if status == 10:
|
if status == 10:
|
||||||
print("No face model is known for this user, skiping")
|
if config.get("core", "supress_unknown") != "true":
|
||||||
return pamh.PAM_SYSTEM_ERR
|
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "No face model known"))
|
||||||
|
return pamh.PAM_USER_UNKNOWN
|
||||||
# Status 11 means we exceded the maximum retry count
|
# Status 11 means we exceded the maximum retry count
|
||||||
if status == 11:
|
if status == 11:
|
||||||
print("Timeout reached, could not find a known face")
|
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Face detection timeout reached"))
|
||||||
return pamh.PAM_SYSTEM_ERR
|
return pamh.PAM_AUTH_ERR
|
||||||
# Status 0 is a successful exit
|
# Status 0 is a successful exit
|
||||||
if status == 0:
|
if status == 0:
|
||||||
print("Identified face as " + os.environ.get("USER"))
|
if config.get("core", "no_confirmation") != "true":
|
||||||
|
pamh.conversation(pamh.Message(pamh.PAM_TEXT_INFO, "Identified face as " + pamh.get_user()))
|
||||||
return pamh.PAM_SUCCESS
|
return pamh.PAM_SUCCESS
|
||||||
|
|
||||||
# Otherwise, we can't discribe what happend but it wasn't successful
|
# Otherwise, we can't discribe what happend but it wasn't successful
|
||||||
print("Unknown error: " + str(status))
|
pamh.conversation(pamh.Message(pamh.PAM_ERROR_MSG, "Unknown error: " + str(status)))
|
||||||
return pamh.PAM_SYSTEM_ERR
|
return pamh.PAM_SYSTEM_ERR
|
||||||
|
|
||||||
def pam_sm_authenticate(pamh, flags, args):
|
def pam_sm_authenticate(pamh, flags, args):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue