mirror of
https://github.com/boltgolt/howdy.git
synced 2024-09-19 09:51:19 +02:00
Added getext translating function
This commit is contained in:
parent
473aa9807e
commit
55f3753260
15 changed files with 152 additions and 115 deletions
30
src/cli.py
30
src/cli.py
|
@ -8,6 +8,8 @@ import getpass
|
|||
import argparse
|
||||
import builtins
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Try to get the original username (not "root") from shell
|
||||
try:
|
||||
user = os.getlogin()
|
||||
|
@ -20,48 +22,48 @@ if user == "root" or user is None:
|
|||
|
||||
# If even that fails, error out
|
||||
if env_user == "":
|
||||
print("Could not determine user, please use the --user flag")
|
||||
print(_("Could not determine user, please use the --user flag"))
|
||||
sys.exit(1)
|
||||
else:
|
||||
user = env_user
|
||||
|
||||
# Basic command setup
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Command line interface for Howdy face authentication.",
|
||||
description=_("Command line interface for Howdy face authentication."),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
add_help=False,
|
||||
prog="howdy",
|
||||
epilog="For support please visit\nhttps://github.com/boltgolt/howdy")
|
||||
epilog=_("For support please visit\nhttps://github.com/boltgolt/howdy"))
|
||||
|
||||
# Add an argument for the command
|
||||
parser.add_argument(
|
||||
"command",
|
||||
help="The command option to execute, can be one of the following: add, clear, config, disable, list, remove, snapshot, set, test or version.",
|
||||
_("command"),
|
||||
help=_("The command option to execute, can be one of the following: add, clear, config, disable, list, remove, snapshot, set, test or version."),
|
||||
metavar="command",
|
||||
choices=["add", "clear", "config", "disable", "list", "remove", "set", "snapshot", "test", "version"])
|
||||
|
||||
# Add an argument for the extra arguments of diable and remove
|
||||
parser.add_argument(
|
||||
"arguments",
|
||||
help="Optional arguments for the add, disable, remove and set commands.",
|
||||
_("arguments"),
|
||||
help=_("Optional arguments for the add, disable, remove and set commands."),
|
||||
nargs="*")
|
||||
|
||||
# Add the user flag
|
||||
parser.add_argument(
|
||||
"-U", "--user",
|
||||
default=user,
|
||||
help="Set the user account to use.")
|
||||
help=_("Set the user account to use."))
|
||||
|
||||
# Add the -y flag
|
||||
parser.add_argument(
|
||||
"-y",
|
||||
help="Skip all questions.",
|
||||
help=_("Skip all questions."),
|
||||
action="store_true")
|
||||
|
||||
# Add the --plain flag
|
||||
parser.add_argument(
|
||||
"--plain",
|
||||
help="Print machine-friendly output.",
|
||||
help=_("Print machine-friendly output."),
|
||||
action="store_true")
|
||||
|
||||
# Overwrite the default help message so we can use a uppercase S
|
||||
|
@ -69,11 +71,11 @@ parser.add_argument(
|
|||
"-h", "--help",
|
||||
action="help",
|
||||
default=argparse.SUPPRESS,
|
||||
help="Show this help message and exit.")
|
||||
help=_("Show this help message and exit."))
|
||||
|
||||
# If we only have 1 argument we print the help text
|
||||
if len(sys.argv) < 2:
|
||||
print("current active user: " + user + "\n")
|
||||
print(_("current active user: ") + user + "\n")
|
||||
parser.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
|
@ -87,13 +89,13 @@ builtins.howdy_user = args.user
|
|||
# Check if we have rootish rights
|
||||
# This is this far down the file so running the command for help is always possible
|
||||
if os.geteuid() != 0:
|
||||
print("Please run this command as root:\n")
|
||||
print(_("Please run this command as root:\n"))
|
||||
print("\tsudo howdy " + " ".join(sys.argv[1:]))
|
||||
sys.exit(1)
|
||||
|
||||
# Beond this point the user can't change anymore, if we still have root as user we need to abort
|
||||
if args.user == "root":
|
||||
print("Can't run howdy commands as root, please run this command with the --user flag")
|
||||
print(_("Can't run howdy commands as root, please run this command with the --user flag"))
|
||||
sys.exit(1)
|
||||
|
||||
# Execute the right command
|
||||
|
|
|
@ -8,7 +8,9 @@ import json
|
|||
import configparser
|
||||
import builtins
|
||||
import numpy as np
|
||||
|
||||
from recorders.video_capture import VideoCapture
|
||||
from i18n import _
|
||||
|
||||
# Try to import dlib and give a nice error if we can't
|
||||
# Add should be the first point where import issues show up
|
||||
|
@ -17,7 +19,7 @@ try:
|
|||
except ImportError as err:
|
||||
print(err)
|
||||
|
||||
print("\nCan't import the dlib module, check the output of")
|
||||
print(_("\nCan't import the dlib module, check the output of"))
|
||||
print("pip3 show dlib")
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -29,7 +31,7 @@ path = os.path.abspath(__file__ + "/..")
|
|||
|
||||
# Test if at lest 1 of the data files is there and abort if it's not
|
||||
if not os.path.isfile(path + "/../dlib-data/shape_predictor_5_face_landmarks.dat"):
|
||||
print("Data files have not been downloaded, please run the following commands:")
|
||||
print(_("Data files have not been downloaded, please run the following commands:"))
|
||||
print("\n\tcd " + os.path.realpath(path + "/../dlib-data"))
|
||||
print("\tsudo ./install.sh\n")
|
||||
sys.exit(1)
|
||||
|
@ -55,7 +57,7 @@ encodings = []
|
|||
|
||||
# Make the ./models folder if it doesn't already exist
|
||||
if not os.path.exists(path + "/../models"):
|
||||
print("No face model folder found, creating one")
|
||||
print(_("No face model folder found, creating one"))
|
||||
os.makedirs(path + "/../models")
|
||||
|
||||
# To try read a premade encodings file if it exists
|
||||
|
@ -66,12 +68,12 @@ except FileNotFoundError:
|
|||
|
||||
# Print a warning if too many encodings are being added
|
||||
if len(encodings) > 3:
|
||||
print("NOTICE: Each additional model slows down the face recognition engine slightly")
|
||||
print("Press Ctrl+C to cancel\n")
|
||||
print(_("NOTICE: Each additional model slows down the face recognition engine slightly"))
|
||||
print(_("Press Ctrl+C to cancel\n"))
|
||||
|
||||
# Make clear what we are doing if not human
|
||||
if not builtins.howdy_args.plain:
|
||||
print("Adding face model for the user " + user)
|
||||
print(_("Adding face model for the user " + user))
|
||||
|
||||
# Set the default label
|
||||
label = "Initial model"
|
||||
|
@ -82,14 +84,14 @@ if builtins.howdy_args.arguments:
|
|||
|
||||
# If models already exist, set that default label
|
||||
elif encodings:
|
||||
label = "Model #" + str(len(encodings) + 1)
|
||||
label = _("Model #") + str(len(encodings) + 1)
|
||||
|
||||
# Keep de default name if we can't ask questions
|
||||
if builtins.howdy_args.y:
|
||||
print('Using default label "%s" because of -y flag' % (label, ))
|
||||
print(_('Using default label "%s" because of -y flag') % (label, ))
|
||||
else:
|
||||
# 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 [{}]: ").format(label))
|
||||
|
||||
# Set the custom label (if any) and limit it to 24 characters
|
||||
if label_in != "":
|
||||
|
@ -97,7 +99,7 @@ else:
|
|||
|
||||
# Remove illegal characters
|
||||
if "," in label:
|
||||
print("NOTICE: Removing illegal character \",\" from model name")
|
||||
print(_("NOTICE: Removing illegal character \",\" from model name"))
|
||||
label = label.replace(",", "")
|
||||
|
||||
# Prepare the metadata for insertion
|
||||
|
@ -111,7 +113,7 @@ insert_model = {
|
|||
# Set up video_capture
|
||||
video_capture = VideoCapture(config)
|
||||
|
||||
print("\nPlease look straight into the camera")
|
||||
print(_("\nPlease look straight into the camera"))
|
||||
|
||||
# Give the user time to read
|
||||
time.sleep(2)
|
||||
|
@ -176,17 +178,17 @@ video_capture.release()
|
|||
# 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?")
|
||||
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))
|
||||
print(_("All frames were too dark, please check dark_threshold in config"))
|
||||
print(_("Average darkness: {avg}, Threshold: {threshold}").format(avg=str(dark_running_total / valid_frames), threshold=str(dark_threshold)))
|
||||
else:
|
||||
print("No face detected, aborting")
|
||||
print(_("No face detected, aborting"))
|
||||
sys.exit(1)
|
||||
|
||||
# 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")
|
||||
print(_("Multiple faces detected, aborting"))
|
||||
sys.exit(1)
|
||||
|
||||
face_location = face_locations[0]
|
||||
|
@ -207,6 +209,5 @@ with open(enc_file, "w") as datafile:
|
|||
json.dump(encodings, datafile)
|
||||
|
||||
# Give let the user know how it went
|
||||
print("""Scan complete
|
||||
|
||||
Added a new model to """ + user)
|
||||
print(_("""\nScan complete
|
||||
Added a new model to """) + user)
|
||||
|
|
|
@ -5,6 +5,8 @@ import os
|
|||
import sys
|
||||
import builtins
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Get the full path to this file
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
# Get the passed user
|
||||
|
@ -12,25 +14,25 @@ user = builtins.howdy_user
|
|||
|
||||
# Check if the models folder is there
|
||||
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(1)
|
||||
|
||||
# Check if the user has a models file to delete
|
||||
if not os.path.isfile(path + "/../models/" + user + ".dat"):
|
||||
print(user + " has no models or they have been cleared already")
|
||||
print(_("{} has no models or they have been cleared already").format(user))
|
||||
sys.exit(1)
|
||||
|
||||
# Only ask the user if there's no -y flag
|
||||
if not builtins.howdy_args.y:
|
||||
# Double check with the user
|
||||
print("This will clear all models for " + user)
|
||||
ans = input("Do you want to continue [y/N]: ")
|
||||
print(_("This will clear all models for ") + user)
|
||||
ans = input(_("Do you want to continue [y/N]: "))
|
||||
|
||||
# Abort if they don't answer y or Y
|
||||
if (ans.lower() != "y"):
|
||||
print('\nInerpeting as a "NO"')
|
||||
print(_('\nInerpeting as a "NO", aborting'))
|
||||
sys.exit(1)
|
||||
|
||||
# Delete otherwise
|
||||
os.remove(path + "/../models/" + user + ".dat")
|
||||
print("\nModels cleared")
|
||||
print(_("\nModels cleared"))
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
import os
|
||||
import subprocess
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Let the user know what we're doing
|
||||
print("Opening config.ini in the default editor")
|
||||
print(_("Opening config.ini in the default editor"))
|
||||
|
||||
# Default to the nano editor
|
||||
editor = "/bin/nano"
|
||||
|
|
|
@ -7,6 +7,8 @@ import builtins
|
|||
import fileinput
|
||||
import configparser
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Get the absolute filepath
|
||||
config_path = os.path.dirname(os.path.abspath(__file__)) + "/../config.ini"
|
||||
|
||||
|
@ -16,7 +18,7 @@ config.read(config_path)
|
|||
|
||||
# Check if enough arguments have been passed
|
||||
if not builtins.howdy_args.arguments:
|
||||
print("Please add a 0 (enable) or a 1 (disable) as an argument")
|
||||
print(_("Please add a 0 (enable) or a 1 (disable) as an argument"))
|
||||
sys.exit(1)
|
||||
|
||||
# Get the cli argument
|
||||
|
@ -29,12 +31,12 @@ elif argument == "0" or argument.lower() == "false":
|
|||
out_value = "false"
|
||||
else:
|
||||
# Of it's not a 0 or a 1, it's invalid
|
||||
print("Please only use 0 (enable) or 1 (disable) as an argument")
|
||||
print(_("Please only use 0 (enable) or 1 (disable) as an argument"))
|
||||
sys.exit(1)
|
||||
|
||||
# Don't do anything when the state is already the requested one
|
||||
if out_value == config.get("core", "disabled"):
|
||||
print("The disable option has already been set to " + out_value)
|
||||
print(_("The disable option has already been set to ") + out_value)
|
||||
sys.exit(1)
|
||||
|
||||
# Loop though the config file and only replace the line containing the disable config
|
||||
|
@ -43,6 +45,6 @@ for line in fileinput.input([config_path], inplace=1):
|
|||
|
||||
# Print what we just did
|
||||
if out_value == "true":
|
||||
print("Howdy has been disabled")
|
||||
print(_("Howdy has been disabled"))
|
||||
else:
|
||||
print("Howdy has been enabled")
|
||||
print(_("Howdy has been enabled"))
|
||||
|
|
|
@ -7,13 +7,15 @@ import json
|
|||
import time
|
||||
import builtins
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Get the absolute path and the username
|
||||
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
|
||||
user = builtins.howdy_user
|
||||
|
||||
# Check if the models file has been created yet
|
||||
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\tsudo howdy -U " + user + " add\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -24,14 +26,14 @@ enc_file = path + "/models/" + user + ".dat"
|
|||
try:
|
||||
encodings = json.load(open(enc_file))
|
||||
except FileNotFoundError:
|
||||
print("No face model known for the user " + user + ", please run:")
|
||||
print(_("No face model known for the user {}, please run:").format(user))
|
||||
print("\n\tsudo howdy -U " + user + " add\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Print a header if we're not in plain mode
|
||||
if not builtins.howdy_args.plain:
|
||||
print("Known face models for " + user + ":")
|
||||
print("\n\033[1;29mID Date Label\033[0m")
|
||||
print(_("Known face models for {}:").format(user))
|
||||
print("\n\033[1;29m" + _("ID Date Label\033[0m"))
|
||||
|
||||
# Loop through all encodings and print info about them
|
||||
for enc in encodings:
|
||||
|
|
|
@ -6,22 +6,24 @@ import os
|
|||
import json
|
||||
import builtins
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Get the absolute path and the username
|
||||
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
|
||||
user = builtins.howdy_user
|
||||
|
||||
# Check if enough arguments have been passed
|
||||
if not builtins.howdy_args.arguments:
|
||||
print("Please add the ID of the model you want to remove as an argument")
|
||||
print("For example:")
|
||||
print(_("Please add the ID of the model you want to remove as an argument"))
|
||||
print(_("For example:"))
|
||||
print("\n\thowdy remove 0\n")
|
||||
print("You can find the IDs by running:")
|
||||
print(_("You can find the IDs by running:"))
|
||||
print("\n\thowdy list\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Check if the models file has been created yet
|
||||
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 add\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -32,7 +34,7 @@ enc_file = path + "/models/" + user + ".dat"
|
|||
try:
|
||||
encodings = json.load(open(enc_file))
|
||||
except FileNotFoundError:
|
||||
print("No face model known for the user " + user + ", please run:")
|
||||
print(_("No face model known for the user " + user + ", please run:"))
|
||||
print("\n\thowdy add\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -48,12 +50,12 @@ for enc in encodings:
|
|||
# Only ask the user if there's no -y flag
|
||||
if not builtins.howdy_args.y:
|
||||
# Double check with the user
|
||||
print('This will remove the model called "' + enc["label"] + '" for ' + user)
|
||||
ans = input("Do you want to continue [y/N]: ")
|
||||
print(_('This will remove the model called "{label}" for {user}').format(label=enc["label"], user=user))
|
||||
ans = input(_("Do you want to continue [y/N]: "))
|
||||
|
||||
# Abort if the answer isn't yes
|
||||
if (ans.lower() != "y"):
|
||||
print('\nInterpreting as a "NO", aborting')
|
||||
print(_('\nInterpreting as a "NO", aborting'))
|
||||
sys.exit(1)
|
||||
|
||||
# Add a padding empty line
|
||||
|
@ -65,13 +67,13 @@ for enc in encodings:
|
|||
|
||||
# Abort if no matching id was found
|
||||
if not found:
|
||||
print("No model with ID " + id + " exists for " + user)
|
||||
print(_("No model with ID {id} exists for {user}").format(id=id, user=user))
|
||||
sys.exit(1)
|
||||
|
||||
# Remove the entire file if this encoding is the only one
|
||||
if len(encodings) == 1:
|
||||
os.remove(path + "/models/" + user + ".dat")
|
||||
print("Removed last model, howdy disabled for user")
|
||||
print(_("Removed last model, howdy disabled for user"))
|
||||
else:
|
||||
# A place holder to contain the encodings that will remain
|
||||
new_encodings = []
|
||||
|
@ -85,4 +87,4 @@ else:
|
|||
with open(enc_file, "w") as datafile:
|
||||
json.dump(new_encodings, datafile)
|
||||
|
||||
print("Removed model " + id)
|
||||
print(_("Removed model {}").format(id))
|
||||
|
|
|
@ -6,13 +6,15 @@ import os
|
|||
import builtins
|
||||
import fileinput
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Get the absolute filepath
|
||||
config_path = os.path.dirname(os.path.abspath(__file__)) + "/../config.ini"
|
||||
|
||||
# Check if enough arguments have been passed
|
||||
if len(builtins.howdy_args.arguments) < 2:
|
||||
print("Please add a setting you would like to change and the value to set it to")
|
||||
print("For example:")
|
||||
print(_("Please add a setting you would like to change and the value to set it to"))
|
||||
print(_("For example:"))
|
||||
print("\n\thowdy set certainty 3\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -31,11 +33,11 @@ for line in fileinput.input([config_path]):
|
|||
|
||||
# If we don't have the line it is not in the config file
|
||||
if not found_line:
|
||||
print('Could not find a "' + set_name + '" config option to set')
|
||||
print(_('Could not find a "{}" config option to set').format(set_name))
|
||||
sys.exit(1)
|
||||
|
||||
# Go through the file again and update the correct line
|
||||
for line in fileinput.input([config_path], inplace=1):
|
||||
print(line.replace(found_line, set_name + " = " + set_value + "\n"), end="")
|
||||
|
||||
print("Config option updated")
|
||||
print(_("Config option updated"))
|
||||
|
|
|
@ -7,6 +7,8 @@ import datetime
|
|||
import snapshot
|
||||
from recorders.video_capture import VideoCapture
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Get the absolute path to the current directory
|
||||
path = os.path.abspath(__file__ + "/..")
|
||||
|
||||
|
@ -40,12 +42,12 @@ while True:
|
|||
|
||||
# Generate a snapshot image from the frames
|
||||
file = snapshot.generate(frames, [
|
||||
"GENERATED SNAPSHOT",
|
||||
"Date: " + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
|
||||
"Dark threshold config: " + str(config.getfloat("video", "dark_threshold", fallback=50.0)),
|
||||
"Certainty config: " + str(config.getfloat("video", "certainty", fallback=3.5))
|
||||
_("GENERATED SNAPSHOT"),
|
||||
_("Date: ") + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
|
||||
_("Dark threshold config: ") + str(config.getfloat("video", "dark_threshold", fallback=50.0)),
|
||||
_("Certainty config: ") + str(config.getfloat("video", "certainty", fallback=3.5))
|
||||
])
|
||||
|
||||
# Show the file location in console
|
||||
print("Generated snapshot saved as")
|
||||
print(_("Generated snapshot saved as"))
|
||||
print(file)
|
||||
|
|
|
@ -9,6 +9,8 @@ import dlib
|
|||
import cv2
|
||||
from recorders.video_capture import VideoCapture
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Get the absolute path to the current file
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
@ -17,8 +19,7 @@ config = configparser.ConfigParser()
|
|||
config.read(path + "/../config.ini")
|
||||
|
||||
if config.get("video", "recording_plugin") != "opencv":
|
||||
print("Howdy has been configured to use a recorder which doesn't support the test command yet")
|
||||
print("Aborting")
|
||||
print(_("Howdy has been configured to use a recorder which doesn't support the test command yet, aborting"))
|
||||
sys.exit(12)
|
||||
|
||||
video_capture = VideoCapture(config)
|
||||
|
@ -28,12 +29,12 @@ exposure = config.getint("video", "exposure", fallback=-1)
|
|||
dark_threshold = config.getfloat("video", "dark_threshold")
|
||||
|
||||
# Let the user know what's up
|
||||
print("""
|
||||
print(_("""
|
||||
Opening a window with a test feed
|
||||
|
||||
Press ctrl+C in this terminal to quit
|
||||
Click on the image to enable or disable slow mode
|
||||
""")
|
||||
"""))
|
||||
|
||||
|
||||
def mouse(event, x, y, flags, param):
|
||||
|
@ -97,7 +98,7 @@ try:
|
|||
sec_frames = 0
|
||||
|
||||
# Grab a single frame of video
|
||||
_, frame = video_capture.read_frame()
|
||||
ret, frame = video_capture.read_frame()
|
||||
|
||||
frame = clahe.apply(frame)
|
||||
# Make a frame to put overlays in
|
||||
|
@ -127,22 +128,22 @@ try:
|
|||
cv2.rectangle(overlay, p1, p2, (0, 200, 0), thickness=cv2.FILLED)
|
||||
|
||||
# Print the statis in the bottom left
|
||||
print_text(0, "RESOLUTION: %dx%d" % (height, width))
|
||||
print_text(1, "FPS: %d" % (fps, ))
|
||||
print_text(2, "FRAMES: %d" % (total_frames, ))
|
||||
print_text(3, "RECOGNITION: %dms" % (round(rec_tm * 1000), ))
|
||||
print_text(0, _("RESOLUTION: %dx%d") % (height, width))
|
||||
print_text(1, _("FPS: %d") % (fps, ))
|
||||
print_text(2, _("FRAMES: %d") % (total_frames, ))
|
||||
print_text(3, _("RECOGNITION: %dms") % (round(rec_tm * 1000), ))
|
||||
|
||||
# Show that slow mode is on, if it's on
|
||||
if slow_mode:
|
||||
cv2.putText(overlay, "SLOW MODE", (width - 66, height - 10), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
|
||||
cv2.putText(overlay, _("SLOW MODE"), (width - 66, height - 10), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
|
||||
|
||||
# Ignore dark frames
|
||||
if hist_perc[0] > dark_threshold:
|
||||
# Show that this is an ignored frame in the top right
|
||||
cv2.putText(overlay, "DARK FRAME", (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
|
||||
cv2.putText(overlay, _("DARK FRAME"), (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
|
||||
else:
|
||||
# SHow that this is an active frame
|
||||
cv2.putText(overlay, "SCAN FRAME", (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 255, 0), 0, cv2.LINE_AA)
|
||||
cv2.putText(overlay, _("SCAN FRAME"), (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 255, 0), 0, cv2.LINE_AA)
|
||||
|
||||
rec_tm = time.time()
|
||||
# Get the locations of all faces and their locations
|
||||
|
@ -197,7 +198,7 @@ try:
|
|||
# On ctrl+C
|
||||
except KeyboardInterrupt:
|
||||
# Let the user know we're stopping
|
||||
print("\nClosing window")
|
||||
print(_("\nClosing window"))
|
||||
|
||||
# Release handle to the webcam
|
||||
cv2.destroyAllWindows()
|
||||
|
|
|
@ -20,7 +20,9 @@ import datetime
|
|||
import snapshot
|
||||
import numpy as np
|
||||
import _thread as thread
|
||||
|
||||
from recorders.video_capture import VideoCapture
|
||||
from i18n import _
|
||||
|
||||
|
||||
def init_detector(lock):
|
||||
|
@ -29,7 +31,7 @@ def init_detector(lock):
|
|||
|
||||
# Test if at lest 1 of the data files is there and abort if it's not
|
||||
if not os.path.isfile(PATH + "/dlib-data/shape_predictor_5_face_landmarks.dat"):
|
||||
print("Data files have not been downloaded, please run the following commands:")
|
||||
print(_("Data files have not been downloaded, please run the following commands:"))
|
||||
print("\n\tcd " + PATH + "/dlib-data")
|
||||
print("\tsudo ./install.sh\n")
|
||||
lock.release()
|
||||
|
@ -53,12 +55,12 @@ def init_detector(lock):
|
|||
def make_snapshot(type):
|
||||
"""Generate snapshot after detection"""
|
||||
snapshot.generate(snapframes, [
|
||||
type + " LOGIN",
|
||||
"Date: " + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
|
||||
"Scan time: " + str(round(time.time() - timings["fr"], 2)) + "s",
|
||||
"Frames: " + str(frames) + " (" + str(round(frames / (time.time() - timings["fr"]), 2)) + "FPS)",
|
||||
"Hostname: " + os.uname().nodename,
|
||||
"Best certainty value: " + str(round(lowest_certainty * 10, 1))
|
||||
type + _(" LOGIN"),
|
||||
_("Date: ") + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
|
||||
_("Scan time: ") + str(round(time.time() - timings["fr"], 2)) + "s",
|
||||
_("Frames: ") + str(frames) + " (" + str(round(frames / (time.time() - timings["fr"]), 2)) + "FPS)",
|
||||
_("Hostname: ") + os.uname().nodename,
|
||||
_("Best certainty value: ") + str(round(lowest_certainty * 10, 1))
|
||||
])
|
||||
|
||||
|
||||
|
@ -172,11 +174,11 @@ while True:
|
|||
if time.time() - timings["fr"] > timeout:
|
||||
# Create a timeout snapshot if enabled
|
||||
if capture_failed:
|
||||
make_snapshot("FAILED")
|
||||
make_snapshot(_("FAILED"))
|
||||
|
||||
if dark_tries == valid_frames:
|
||||
print("All frames were too dark, please check dark_threshold in config")
|
||||
print("Average darkness: " + str(dark_running_total / max(1, valid_frames)) + ", Threshold: " + str(dark_threshold))
|
||||
print(_("All frames were too dark, please check dark_threshold in config"))
|
||||
print(_("Average darkness: {avg}, Threshold: {threshold}").format(avg=str(dark_running_total / max(1, valid_frames)), threshold=str(dark_threshold)))
|
||||
sys.exit(13)
|
||||
else:
|
||||
sys.exit(11)
|
||||
|
@ -255,32 +257,32 @@ while True:
|
|||
print(" %s: %dms" % (label, round(timings[k] * 1000)))
|
||||
|
||||
# Print a nice timing report
|
||||
print("Time spent")
|
||||
print_timing("Starting up", "in")
|
||||
print(" Open cam + load libs: %dms" % (round(max(timings["ll"], timings["ic"]) * 1000, )))
|
||||
print_timing(" Opening the camera", "ic")
|
||||
print_timing(" Importing recognition libs", "ll")
|
||||
print_timing("Searching for known face", "fl")
|
||||
print_timing("Total time", "tt")
|
||||
print(_("Time spent"))
|
||||
print_timing(_("Starting up"), "in")
|
||||
print(_(" Open cam + load libs: %dms") % (round(max(timings["ll"], timings["ic"]) * 1000, )))
|
||||
print_timing(_(" Opening the camera"), "ic")
|
||||
print_timing(_(" Importing recognition libs"), "ll")
|
||||
print_timing(_("Searching for known face"), "fl")
|
||||
print_timing(_("Total time"), "tt")
|
||||
|
||||
print("\nResolution")
|
||||
print(_("\nResolution"))
|
||||
width = video_capture.fw or 1
|
||||
print(" Native: %dx%d" % (height, width))
|
||||
print(_(" Native: %dx%d") % (height, width))
|
||||
# Save the new size for diagnostics
|
||||
scale_height, scale_width = frame.shape[:2]
|
||||
print(" Used: %dx%d" % (scale_height, scale_width))
|
||||
print(_(" Used: %dx%d") % (scale_height, scale_width))
|
||||
|
||||
# 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["fl"]))
|
||||
print("Black frames ignored: %d " % (black_tries, ))
|
||||
print("Dark frames ignored: %d " % (dark_tries, ))
|
||||
print("Certainty of winning frame: %.3f" % (match * 10, ))
|
||||
print(_("\nFrames searched: %d (%.2f fps)") % (frames, frames / timings["fl"]))
|
||||
print(_("Black frames ignored: %d ") % (black_tries, ))
|
||||
print(_("Dark frames ignored: %d ") % (dark_tries, ))
|
||||
print(_("Certainty of winning frame: %.3f") % (match * 10, ))
|
||||
|
||||
print("Winning model: %d (\"%s\")" % (match_index, models[match_index]["label"]))
|
||||
print(_("Winning model: %d (\"%s\")") % (match_index, models[match_index]["label"]))
|
||||
|
||||
# Make snapshot if enabled
|
||||
if capture_successful:
|
||||
make_snapshot("SUCCESSFUL")
|
||||
make_snapshot(_("SUCCESSFUL"))
|
||||
|
||||
# Run rubberstamps if enabled
|
||||
if config.getboolean("rubberstamps", "enabled", fallback=False):
|
||||
|
|
12
src/i18n.py
Normal file
12
src/i18n.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Support file for translations
|
||||
|
||||
# Import modules
|
||||
import gettext
|
||||
import os
|
||||
|
||||
# Get the right translation based on locale, falling back to base if none found
|
||||
translation = gettext.translation("core", localedir=os.path.join(os.path.dirname(__file__), 'locales'), fallback=True)
|
||||
translation.install()
|
||||
|
||||
# Export translation function as _
|
||||
_ = translation.gettext
|
|
@ -4,14 +4,16 @@
|
|||
import numpy
|
||||
import sys
|
||||
import re
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
from cv2 import CAP_PROP_FRAME_WIDTH
|
||||
from cv2 import CAP_PROP_FRAME_HEIGHT
|
||||
from i18n import _
|
||||
|
||||
try:
|
||||
import ffmpeg
|
||||
except ImportError:
|
||||
print("Missing ffmpeg module, please run:")
|
||||
print(_("Missing ffmpeg module, please run:"))
|
||||
print(" pip3 install ffmpeg-python\n")
|
||||
sys.exit(12)
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
# Class that simulates the functionality of opencv so howdy can use v4l2 devices seamlessly
|
||||
|
||||
# Import required modules. lib4l-dev package is also required.
|
||||
from recorders import v4l2
|
||||
import fcntl
|
||||
import numpy
|
||||
import sys
|
||||
|
||||
from recorders import v4l2
|
||||
from cv2 import cvtColor, COLOR_GRAY2BGR, CAP_PROP_FRAME_WIDTH, CAP_PROP_FRAME_HEIGHT
|
||||
from i18n import _
|
||||
|
||||
try:
|
||||
from pyv4l2.frame import Frame
|
||||
except ImportError:
|
||||
print("Missing pyv4l2 module, please run:")
|
||||
print(_("Missing pyv4l2 module, please run:"))
|
||||
print(" pip3 install pyv4l2\n")
|
||||
sys.exit(13)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import cv2
|
|||
import os
|
||||
import sys
|
||||
|
||||
from i18n import _
|
||||
|
||||
# Class to provide boilerplate code to build a video recorder with the
|
||||
# correct settings from the config file.
|
||||
|
@ -33,8 +34,8 @@ class VideoCapture:
|
|||
# Check device path
|
||||
if not os.path.exists(self.config.get("video", "device_path")):
|
||||
if self.config.getboolean("video", "warn_no_device"):
|
||||
print("Howdy could not find a camera device at the path specified in the config file.")
|
||||
print("It is very likely that the path is not configured correctly, please edit the 'device_path' config value by running:")
|
||||
print(_("Howdy could not find a camera device at the path specified in the config file."))
|
||||
print(_("It is very likely that the path is not configured correctly, please edit the 'device_path' config value by running:"))
|
||||
print("\n\tsudo howdy config\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
@ -81,7 +82,7 @@ class VideoCapture:
|
|||
# Don't remove ret, it doesn't work without it
|
||||
ret, frame = self.internal.read()
|
||||
if not ret:
|
||||
print("Failed to read camera specified in your 'device_path', aborting")
|
||||
print(_("Failed to read camera specified in the 'device_path' config option, aborting"))
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
|
|
Loading…
Reference in a new issue