Commented everything
This commit is contained in:
parent
d7f8510226
commit
818be92838
10 changed files with 72 additions and 6 deletions
|
|
@ -12,7 +12,7 @@ Run the installer by pasting (`ctrl+shift+V`) the following command into the ter
|
||||||
wget -O /tmp/howdy_install.py https://raw.githubusercontent.com/Boltgolt/howdy/master/installer.py && sudo python3 /tmp/howdy_install.py
|
wget -O /tmp/howdy_install.py https://raw.githubusercontent.com/Boltgolt/howdy/master/installer.py && sudo python3 /tmp/howdy_install.py
|
||||||
```
|
```
|
||||||
|
|
||||||
This will guide you through the installation. When that's done run `howdy add` to add a face model for the current user.
|
This will guide you through the installation. When that's done run `howdy USER add` and replace `USER` with your username to add a face model.
|
||||||
|
|
||||||
If nothing went wrong we should be able to run sudo by just showing your face. Open a new terminal and run `sudo -i` to see it in action.
|
If nothing went wrong we should be able to run sudo by just showing your face. Open a new terminal and run `sudo -i` to see it in action.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Autocomplete file run in bash
|
||||||
|
# Will sugest arguments on tab
|
||||||
|
|
||||||
_howdy() {
|
_howdy() {
|
||||||
local cur prev opts
|
local cur prev opts
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
|
|
|
||||||
10
cli.py
10
cli.py
|
|
@ -1,19 +1,26 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# CLI directly called by running the howdy command
|
||||||
|
|
||||||
|
# Import required modules
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
# Check if the minimum of 3 arugemnts has been met and print help otherwise
|
||||||
if (len(sys.argv) < 3):
|
if (len(sys.argv) < 3):
|
||||||
print("Howdy IR face recognition help")
|
print("Howdy IR face recognition help")
|
||||||
import cli.help
|
import cli.help
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
user = sys.argv[1]
|
# The command given
|
||||||
cmd = sys.argv[2]
|
cmd = sys.argv[2]
|
||||||
|
|
||||||
|
# Requre sudo for comamnds that need root rights to read the model files
|
||||||
if cmd in ["list", "add", "remove", "clear"] and os.getenv("SUDO_USER") is None:
|
if cmd in ["list", "add", "remove", "clear"] and os.getenv("SUDO_USER") is None:
|
||||||
print("Please run this command with sudo")
|
print("Please run this command with sudo")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# Call the right files for the given command
|
||||||
if cmd == "list":
|
if cmd == "list":
|
||||||
import cli.list
|
import cli.list
|
||||||
elif cmd == "help":
|
elif cmd == "help":
|
||||||
|
|
@ -26,6 +33,7 @@ elif cmd == "remove":
|
||||||
elif cmd == "clear":
|
elif cmd == "clear":
|
||||||
import cli.clear
|
import cli.clear
|
||||||
else:
|
else:
|
||||||
|
# If the comand is invalid, check if the user hasn't swapped the username and command
|
||||||
if sys.argv[1] in ["list", "add", "remove", "clear", "help"]:
|
if sys.argv[1] in ["list", "add", "remove", "clear", "help"]:
|
||||||
print("Usage: howdy <user> <command>")
|
print("Usage: howdy <user> <command>")
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
14
cli/add.py
14
cli/add.py
|
|
@ -6,19 +6,21 @@ import time
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# Import config
|
|
||||||
import configparser
|
import configparser
|
||||||
|
|
||||||
|
|
||||||
|
# Try to import face_recognition and give a nice error if we can't
|
||||||
|
# Add should be the first point where import issues show up
|
||||||
try:
|
try:
|
||||||
import face_recognition
|
import face_recognition
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
print(err)
|
print(err)
|
||||||
|
|
||||||
print("\nCan't import face_recognition module, check the output of")
|
print("\nCan't import the face_recognition module, check the output of")
|
||||||
print("pip3 show face_recognition")
|
print("pip3 show face_recognition")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# Get the absolute path to the current file
|
||||||
path = os.path.dirname(os.path.abspath(__file__))
|
path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
# Read config from disk
|
# Read config from disk
|
||||||
|
|
@ -87,16 +89,21 @@ except FileNotFoundError:
|
||||||
|
|
||||||
print("Adding face model for the user account " + user)
|
print("Adding face model for the user account " + user)
|
||||||
|
|
||||||
|
# Set the default label
|
||||||
label = "Initial model"
|
label = "Initial model"
|
||||||
|
|
||||||
|
# If models already exist, set that default label
|
||||||
if len(encodings) > 0:
|
if len(encodings) > 0:
|
||||||
label = "Model #" + str(len(encodings) + 1)
|
label = "Model #" + str(len(encodings) + 1)
|
||||||
|
|
||||||
|
# Ask the user for a custom label
|
||||||
label_in = input("Enter a label for this new model [" + label + "]: ")
|
label_in = input("Enter a label for this new model [" + label + "]: ")
|
||||||
|
|
||||||
|
# Set the custom label (if any) and limit it to 24 characters
|
||||||
if label_in != "":
|
if label_in != "":
|
||||||
label = label_in[:24]
|
label = label_in[:24]
|
||||||
|
|
||||||
|
# Prepare the metadata for insertion
|
||||||
insert_model = {
|
insert_model = {
|
||||||
"time": int(time.time()),
|
"time": int(time.time()),
|
||||||
"label": label,
|
"label": label,
|
||||||
|
|
@ -114,6 +121,7 @@ for delay in [30, 6, 0]:
|
||||||
time.sleep(.3)
|
time.sleep(.3)
|
||||||
captureFrame(delay)
|
captureFrame(delay)
|
||||||
|
|
||||||
|
# Insert full object into the list
|
||||||
encodings.append(insert_model)
|
encodings.append(insert_model)
|
||||||
|
|
||||||
# Save the new encodings to disk
|
# Save the new encodings to disk
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Clear all models by deleting the whole file
|
||||||
|
|
||||||
|
# Import required modules
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -6,20 +9,25 @@ path = os.path.dirname(os.path.abspath(__file__))
|
||||||
# Get the passed user
|
# Get the passed user
|
||||||
user = sys.argv[1]
|
user = sys.argv[1]
|
||||||
|
|
||||||
|
# Check if the models folder is there
|
||||||
if not os.path.exists(path + "/../models"):
|
if not os.path.exists(path + "/../models"):
|
||||||
print("No models created yet, can't clear them if they don't exist")
|
print("No models created yet, can't clear them if they don't exist")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# Check if the user has a models file to delete
|
||||||
if not os.path.isfile(path + "/../models/" + user + ".dat"):
|
if not os.path.isfile(path + "/../models/" + user + ".dat"):
|
||||||
print(user + " has no models or they have been cleared already")
|
print(user + " has no models or they have been cleared already")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# Double check with the user
|
||||||
print("This will clear all models for " + user)
|
print("This will clear all models for " + user)
|
||||||
ans = input("Do you want to continue [y/N]: ")
|
ans = input("Do you want to continue [y/N]: ")
|
||||||
|
|
||||||
|
# Abort if they don't answer y or Y
|
||||||
if (ans.lower() != "y"):
|
if (ans.lower() != "y"):
|
||||||
print('\nInerpeting as a "NO"')
|
print('\nInerpeting as a "NO"')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# Delete otherwise
|
||||||
os.remove(path + "/../models/" + user + ".dat")
|
os.remove(path + "/../models/" + user + ".dat")
|
||||||
print("\nModels cleared")
|
print("\nModels cleared")
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
# Prints a simple help page for the CLI
|
||||||
|
|
||||||
print("""
|
print("""
|
||||||
Usage:
|
Usage:
|
||||||
howdy <user> <command> [argument]
|
howdy <user> <command> [argument]
|
||||||
|
|
|
||||||
14
cli/list.py
14
cli/list.py
|
|
@ -1,18 +1,25 @@
|
||||||
|
# List all models for a user
|
||||||
|
|
||||||
|
# Import required modules
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
# Get the absolute path and the username
|
||||||
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
|
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
|
||||||
user = sys.argv[1]
|
user = sys.argv[1]
|
||||||
|
|
||||||
|
# Check if the models file has been created yet
|
||||||
if not os.path.exists(path + "/models"):
|
if not os.path.exists(path + "/models"):
|
||||||
print("Face models have not been initialized yet, please run:")
|
print("Face models have not been initialized yet, please run:")
|
||||||
print("\n\thowdy " + user + " add\n")
|
print("\n\thowdy " + user + " add\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Path to the models file
|
||||||
enc_file = path + "/models/" + user + ".dat"
|
enc_file = path + "/models/" + user + ".dat"
|
||||||
|
|
||||||
|
# Try to load the models file and abort if the user does not have it yet
|
||||||
try:
|
try:
|
||||||
encodings = json.load(open(enc_file))
|
encodings = json.load(open(enc_file))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
|
@ -20,13 +27,20 @@ except FileNotFoundError:
|
||||||
print("\n\thowdy " + user + " add\n")
|
print("\n\thowdy " + user + " add\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Print a header
|
||||||
print("Known face models for " + user + ":")
|
print("Known face models for " + user + ":")
|
||||||
print("\n\t\033[1;29mID Date Label\033[0m")
|
print("\n\t\033[1;29mID Date Label\033[0m")
|
||||||
|
|
||||||
|
# Loop through all encodings and print info about them
|
||||||
for enc in encodings:
|
for enc in encodings:
|
||||||
|
# Start with a tab and print the id
|
||||||
print("\t" + str(enc["id"]), end="")
|
print("\t" + str(enc["id"]), end="")
|
||||||
|
# Print padding spaces after the id
|
||||||
print((4 - len(str(enc["id"]))) * " ", end="")
|
print((4 - len(str(enc["id"]))) * " ", end="")
|
||||||
|
# Format the time as ISO in the local timezone
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(enc["time"])), end="")
|
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(enc["time"])), end="")
|
||||||
|
# End with the label
|
||||||
print(" " + enc["label"])
|
print(" " + enc["label"])
|
||||||
|
|
||||||
|
# Add a closing enter
|
||||||
print()
|
print()
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,31 @@
|
||||||
|
# Remove a encoding from the models file
|
||||||
|
|
||||||
|
# Import required modules
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
# Get the absolute path and the username
|
||||||
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
|
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
|
||||||
user = sys.argv[1]
|
user = sys.argv[1]
|
||||||
|
|
||||||
|
# Check if enough arguments have been passed
|
||||||
if len(sys.argv) == 3:
|
if len(sys.argv) == 3:
|
||||||
print("Please add the ID of the model to remove as an argument")
|
print("Please add the ID of the model to remove as an argument")
|
||||||
print("You can find the IDs by running:")
|
print("You can find the IDs by running:")
|
||||||
print("\n\thowdy " + user + " list\n")
|
print("\n\thowdy " + user + " list\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Check if the models file has been created yet
|
||||||
if not os.path.exists(path + "/models"):
|
if not os.path.exists(path + "/models"):
|
||||||
print("Face models have not been initialized yet, please run:")
|
print("Face models have not been initialized yet, please run:")
|
||||||
print("\n\thowdy " + user + " add\n")
|
print("\n\thowdy " + user + " add\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Path to the models file
|
||||||
enc_file = path + "/models/" + user + ".dat"
|
enc_file = path + "/models/" + user + ".dat"
|
||||||
|
|
||||||
|
# Try to load the models file and abort if the user does not have it yet
|
||||||
try:
|
try:
|
||||||
encodings = json.load(open(enc_file))
|
encodings = json.load(open(enc_file))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
|
@ -25,35 +33,45 @@ except FileNotFoundError:
|
||||||
print("\n\thowdy " + user + " add\n")
|
print("\n\thowdy " + user + " add\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Tracks if a encoding with that id has been found
|
||||||
found = False
|
found = False
|
||||||
|
|
||||||
|
# Loop though all encodings and check if they match the argument
|
||||||
for enc in encodings:
|
for enc in encodings:
|
||||||
if str(enc["id"]) == sys.argv[3]:
|
if str(enc["id"]) == sys.argv[3]:
|
||||||
|
# Double check with the user
|
||||||
print('This will remove the model called "' + enc["label"] + '" for ' + user)
|
print('This will remove the model called "' + enc["label"] + '" for ' + user)
|
||||||
ans = input("Do you want to continue [y/N]: ")
|
ans = input("Do you want to continue [y/N]: ")
|
||||||
|
|
||||||
|
# Abort if the answer isn't yes
|
||||||
if (ans.lower() != "y"):
|
if (ans.lower() != "y"):
|
||||||
print('\nInerpeting as a "NO"')
|
print('\nInerpeting as a "NO"')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# Mark as found and print an enter
|
||||||
found = True
|
found = True
|
||||||
print()
|
print()
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Abort if no matching id was found
|
||||||
if not found:
|
if not found:
|
||||||
print("No model with ID " + sys.argv[3] + " exists for " + user)
|
print("No model with ID " + sys.argv[3] + " exists for " + user)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
# Remove the entire file if this encoding is the only one
|
||||||
if len(encodings) == 1:
|
if len(encodings) == 1:
|
||||||
os.remove(path + "/models/" + user + ".dat")
|
os.remove(path + "/models/" + user + ".dat")
|
||||||
print("Removed last model, howdy disabled for user")
|
print("Removed last model, howdy disabled for user")
|
||||||
else:
|
else:
|
||||||
|
# A place holder to contain the encodings that will remain
|
||||||
new_encodings = []
|
new_encodings = []
|
||||||
|
|
||||||
|
# Loop though all encodin and only add thos that don't need to be removed
|
||||||
for enc in encodings:
|
for enc in encodings:
|
||||||
if str(enc["id"]) != sys.argv[3]:
|
if str(enc["id"]) != sys.argv[3]:
|
||||||
new_encodings.append(enc)
|
new_encodings.append(enc)
|
||||||
|
|
||||||
|
# Save this new set to disk
|
||||||
with open(enc_file, "w") as datafile:
|
with open(enc_file, "w") as datafile:
|
||||||
json.dump(new_encodings, datafile)
|
json.dump(new_encodings, datafile)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,17 @@ while True:
|
||||||
# Don't remove ret, it doesn't work without it
|
# Don't remove ret, it doesn't work without it
|
||||||
ret, frame = video_capture.read()
|
ret, frame = video_capture.read()
|
||||||
|
|
||||||
|
# Get the height and with of the image
|
||||||
height, width = frame.shape[:2]
|
height, width = frame.shape[:2]
|
||||||
|
|
||||||
|
# If the hight is too high
|
||||||
if max_height < height:
|
if max_height < height:
|
||||||
|
# Calculate the amount the image has to shrink
|
||||||
scaling_factor = max_height / float(height)
|
scaling_factor = max_height / float(height)
|
||||||
|
# Apply that factor to the frame
|
||||||
frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA)
|
frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA)
|
||||||
|
|
||||||
|
# Save the new size for diagnostics
|
||||||
scale_height, scale_width = frame.shape[:2]
|
scale_height, scale_width = frame.shape[:2]
|
||||||
|
|
||||||
# Convert from BGR to RGB
|
# Convert from BGR to RGB
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ handleStatus(subprocess.call(["rm", "-rf", "/tmp/dlib_clone"]))
|
||||||
|
|
||||||
log("Installing face_recognition")
|
log("Installing face_recognition")
|
||||||
|
|
||||||
handleStatus(subprocess.call(["pip3", "install", "face_recognition", "sty"]))
|
handleStatus(subprocess.call(["pip3", "install", "face_recognition"]))
|
||||||
|
|
||||||
log("Cloning howdy")
|
log("Cloning howdy")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue