75 lines
2.2 KiB
Python
75 lines
2.2 KiB
Python
import queue
|
|
import threading
|
|
import logging
|
|
import base64
|
|
from urllib.parse import urlparse
|
|
import pickle
|
|
import json
|
|
|
|
import cv2
|
|
import numpy as np
|
|
import requests
|
|
|
|
from cloud.models import (
|
|
User,
|
|
DBSession
|
|
)
|
|
|
|
compute_queue = queue.Queue()
|
|
|
|
|
|
def find_identity(face, db, recognizer, labels, threshold=.6):
|
|
preds = recognizer.predict_proba([face])[0]
|
|
idx = np.argmax(preds)
|
|
proba = preds[idx]
|
|
if proba > threshold:
|
|
uid = labels.classes_[idx]
|
|
user = db.query(User).filter_by(uid=uid).one()
|
|
return (user, proba)
|
|
|
|
|
|
def load_recognizer(filename):
|
|
with open(filename, 'rb') as infile:
|
|
model = pickle.load(infile)
|
|
recognizer = model['recognizer']
|
|
labels = model['labels']
|
|
return (recognizer, labels)
|
|
|
|
|
|
def process_face(recognizer, labels):
|
|
logging.info('Processing thread started')
|
|
session = DBSession()
|
|
while True:
|
|
uid, b64faces = compute_queue.get()
|
|
bytefaces = map(base64.b64decode, b64faces)
|
|
faces = (np.frombuffer(bf, dtype='float32') for bf in bytefaces)
|
|
identities = set(filter(None, (find_identity(
|
|
face, session, recognizer, labels) for face in faces)))
|
|
users = [id[0] for id in identities]
|
|
|
|
logging.info(
|
|
'Found %d distinct indentities from faces from %s',
|
|
len(identities), uid)
|
|
logging.info(repr(identities))
|
|
|
|
for user, proba in identities:
|
|
matches = [device for device in user.devices if device.uid == uid]
|
|
if matches:
|
|
device = matches[0]
|
|
try:
|
|
logging.info('Sending opening door action')
|
|
payload = json.dumps({'state': 'open'})
|
|
requests.put(device.callback, data=payload)
|
|
except Exception as e:
|
|
logging.warning('Error while sending action: %s', str(e))
|
|
break
|
|
|
|
|
|
def start_processing(settings, nb_thread=4):
|
|
logging.info('Starting processing threads...')
|
|
recognizer, labels = load_recognizer(settings.get('iot.model'))
|
|
for i in range(nb_thread):
|
|
thread = threading.Thread(
|
|
target=process_face, args=(recognizer, labels), daemon=True)
|
|
thread.start()
|