0
0
Fork 0
mirror of https://github.com/boltgolt/howdy.git synced 2024-09-19 09:51:19 +02:00
howdy/compare.py

166 lines
4.8 KiB
Python
Raw Normal View History

2018-02-10 12:40:26 +01:00
# Compare incomming video with known faces
2018-01-05 16:37:00 +01:00
# Running in a local python instance to get around PATH issues
# Import time so we can start timing asap
import time
# Start timing
timings = [time.time()]
2018-01-05 16:37:00 +01:00
# Import required modules
2018-01-05 01:59:44 +01:00
import cv2
import sys
import os
2018-01-05 14:34:18 +01:00
import json
2018-02-13 16:31:30 +01:00
import math
import configparser
2018-01-05 01:59:44 +01:00
# Read config from disk
config = configparser.ConfigParser()
config.read(os.path.dirname(os.path.abspath(__file__)) + "/config.ini")
2018-01-05 02:41:56 +01:00
2018-01-05 01:59:44 +01:00
def stop(status):
2018-01-05 16:37:00 +01:00
"""Stop the execution and close video stream"""
2018-01-05 01:59:44 +01:00
video_capture.release()
sys.exit(status)
2018-01-05 16:37:00 +01:00
# Make sure we were given an username to tast against
2018-01-05 01:59:44 +01:00
try:
if not isinstance(sys.argv[1], str):
sys.exit(1)
except IndexError:
sys.exit(1)
2018-01-05 16:37:00 +01:00
# The username of the authenticating user
2018-01-05 01:59:44 +01:00
user = sys.argv[1]
2018-02-13 16:31:30 +01:00
# The model file contents
models = []
# Encoded face models
2018-01-05 01:59:44 +01:00
encodings = []
2018-01-05 16:37:00 +01:00
# Amount of frames already matched
2018-01-05 14:34:18 +01:00
tries = 0
2018-02-16 17:00:24 +01:00
# Amount of ingnored dark frames
dark_tries = 0
2018-01-05 01:59:44 +01:00
2018-01-05 16:37:00 +01:00
# Try to load the face model from the models folder
2018-01-05 01:59:44 +01:00
try:
2018-02-13 16:31:30 +01:00
models = json.load(open(os.path.dirname(os.path.abspath(__file__)) + "/models/" + user + ".dat"))
2018-01-05 01:59:44 +01:00
except FileNotFoundError:
sys.exit(10)
2018-01-05 01:59:44 +01:00
2018-02-13 16:31:30 +01:00
# Check if the file contains a model
if len(models) < 1:
sys.exit(10)
# Put all models together into 1 array
for model in models:
encodings += model["data"]
2018-01-05 14:34:18 +01:00
# Add the time needed to start the script
2018-02-13 22:03:03 +01:00
timings.append(time.time())
2018-01-05 16:37:00 +01:00
# Start video capture on the IR camera
video_capture = cv2.VideoCapture(int(config.get("video", "device_id")))
# Capture a single frame so the camera becomes active
# This will let the camera adjust its light levels while we're importing for faster scanning
video_capture.read()
# Note the time it took to open the camera
timings.append(time.time())
# Import face recognition, takes some time
import face_recognition
2018-02-13 16:31:30 +01:00
timings.append(time.time())
2018-01-05 01:59:44 +01:00
# Fetch the max frame height
max_height = int(config.get("video", "max_height"))
2018-02-13 16:31:30 +01:00
# Start the read loop
frames = 0
2018-01-05 01:59:44 +01:00
while True:
2018-02-13 16:31:30 +01:00
frames += 1
2018-01-05 01:59:44 +01:00
# Grab a single frame of video
2018-02-13 16:31:30 +01:00
# Don't remove ret, it doesn't work without it
2018-01-05 01:59:44 +01:00
ret, frame = video_capture.read()
2018-02-16 17:00:24 +01:00
# Create a histogram of the image with 8 values
hist = cv2.calcHist([frame], [0], None, [8], [0, 256])
# All values combined for percentage calculation
hist_total = int(sum(hist)[0])
# Scrip the frame if it exceeds the threshold
if float(hist[0]) / hist_total * 100 > float(config.get("video", "dark_threshold")):
dark_tries += 1
continue
2018-02-13 23:22:13 +01:00
# Get the height and with of the image
height, width = frame.shape[:2]
2018-02-13 23:22:13 +01:00
# If the hight is too high
if max_height < height:
2018-02-13 23:22:13 +01:00
# Calculate the amount the image has to shrink
scaling_factor = max_height / float(height)
2018-02-13 23:22:13 +01:00
# Apply that factor to the frame
frame = cv2.resize(frame, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA)
2018-02-13 23:22:13 +01:00
# Save the new size for diagnostics
scale_height, scale_width = frame.shape[:2]
# Convert from BGR to RGB
frame = frame[:, :, ::-1]
2018-01-05 16:37:00 +01:00
# Get all faces from that frame as encodings
2018-01-05 01:59:44 +01:00
face_encodings = face_recognition.face_encodings(frame)
2018-01-05 16:37:00 +01:00
# Loop through each face
2018-01-05 01:59:44 +01:00
for face_encoding in face_encodings:
2018-01-05 16:37:00 +01:00
# Match this found face against a known face
2018-01-05 01:59:44 +01:00
matches = face_recognition.face_distance(encodings, face_encoding)
2018-01-05 16:37:00 +01:00
# Check if any match is certain enough to be the user we're looking for
2018-02-13 16:31:30 +01:00
match_index = 0
2018-01-05 01:59:44 +01:00
for match in matches:
2018-02-13 16:31:30 +01:00
match_index += 1
# Try to find a match that's confident enough
if match * 10 < float(config.get("video", "certainty")) and match > 0:
timings.append(time.time())
# If set to true in the config, print debug text
if config.get("debug", "end_report") == "true":
2018-02-13 22:03:03 +01:00
def print_timing(label, offset):
"""Helper function to print a timing from the list"""
print(" " + label + ": " + str(round((timings[1 + offset] - timings[offset]) * 1000)) + "ms")
2018-02-13 16:31:30 +01:00
print("Time spend")
2018-02-13 22:03:03 +01:00
print_timing("Starting up", 0)
print_timing("Opening the camera", 1)
print_timing("Importing face_recognition", 2)
2018-02-13 22:03:03 +01:00
print_timing("Searching for known face", 3)
2018-02-13 16:31:30 +01:00
print("\nResolution")
print(" Native: " + str(height) + "x" + str(width))
print(" Used: " + str(scale_height) + "x" + str(scale_width))
# Show the total number of frames and calculate the FPS by deviding it by the total scan time
print("\nFrames searched: " + str(frames) + " (" + str(round(float(frames) / (timings[4] - timings[3]), 2)) + " fps)")
2018-02-16 17:00:24 +01:00
print("Dark frames ignored: " + str(dark_tries))
2018-02-13 22:03:03 +01:00
print("Certainty of winning frame: " + str(round(match * 10, 3)))
2018-02-13 16:31:30 +01:00
2018-02-16 16:28:10 +01:00
# Catch older 3-encoding models
if not match_index in models:
match_index = 0
2018-02-13 16:31:30 +01:00
2018-02-16 16:28:10 +01:00
print("Winning model: " + str(match_index) + " (\"" + models[match_index]["label"] + "\")")
2018-02-13 16:31:30 +01:00
# End peacegully
2018-01-05 01:59:44 +01:00
stop(0)
2018-01-05 16:37:00 +01:00
# Stop if we've exceded the maximum retry count
if time.time() - timings[3] > int(config.get("video", "timout")):
2018-01-05 02:41:56 +01:00
stop(11)
2018-01-05 01:59:44 +01:00
tries += 1