To do this, we will need

From the beginning we import dependencies

from keras.models 
import load_model 
import numpy as np 
from keras.utils 
import plot_model 
import math 
import glob 
import os 
import cv2 
import serial

 Then we load the grid and specify the path for the face detector

model_path = 'facenet_keras.h5'
model = load_model(model_path) 
cascade_path = 'haarcascade_frontalface_alt2.xml'

A function that formats an image and runs it through a neural network

def calc_embs(imgs, margin, batch_size):    
    fram1e = cv2.resize(imgs,(160,160))     
    ofg2 = np.array(fram1e)     
    aligned_images = prewhiten(ofg2)     
    pd = []     
    x_train = np.array([aligned_images])     
    embs1 = model.predict_on_batch(x_train)     
    embs1.reshape(1,-1)     
    embs = l2_normalize(np.concatenate(embs1))          
    return embs

 A function that, when a button is pressed for the first time, saves the face of a person who has passed through the neural network, and the second time, having driven a new face through the network, compares it with the saved one

def reco_face(frame, i):
#frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = frame
#i = 0
h = 0
v = 0
u = 0
name_out = 'i dont know you'
#print(ofg.shape)
#img = search_face(img, frame, face_cascade)
#frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
faces = face_cascade.detectMultiScale(frame, 1.3, 5)
print(faces)
if faces == ():
    v = 5
# Loop through all the faces detected and determine whether or not they are in the database
identities = []
for (x, y, w, h) in faces:
    x1 = x-PADDING
    y1 = y-PADDING
    x2 = x+w+PADDING
    y2 = y+h+PADDING

    frame = cv2.rectangle(frame,(x1, y1),(x2, y2),(255,0,0),2)
    height, width, channels = frame.shape
    # The padding is necessary since the OpenCV face detector creates the bounding box around the face and not the head
    part_image = frame[max(0, y1):min(height, y2), max(0, x1):min(width, x2)]
    if i == 1:
        pre[0:] = calc_embs(part_image,10,1)
        while u!=1:

            u = ser.write( b'P') 
        u=0  
    else: ofg = calc_embs(part_image,10,1)
    #print(ofg)
    #i = i + 1
    if i > 1:
        for m in pre:
            dot = np.sum(np.multiply(m, ofg), axis=0)
            norm = np.linalg.norm(m, axis=0) * np.linalg.norm(ofg, axis=0)
            similarity = dot / norm
            dist1 = np.arccos(similarity) / math.pi
            if dist1<0.32:
                print(dist1)
                h = 1
return h,v

 Well, the main. It all starts with the arduino, when the letter B is fed through the uart, which means that the button is pressed. Next, a command is sent to the arduino to open the drawer and the face recognition and preservation function is launched. Then, if the command to press the button came from the arduino again, we run the recognition function again and if the faces converge, then open the box.

ser = serial.Serial('COM3', 9600, write_timeout=1, timeout=0.1)   
print(ser.name)         
# check which port was really used 
cap = cv2.VideoCapture(0) 
zz = 0 
while(True):     
    ret, frame = cap.read()     
    frame1 = search_face(frame)     
    cv2.imshow('ffff', frame1)     
    ff=ser.read(1)    
    if(ff == b'B'):         
        print("press_button")         
        ff = b'u'         
        zz = zz + 1         
        mmm, f = reco_face(frame, zz)         
        if f == 5:             
            zz = 0         
            print(mmm)         
            if mmm == 1:             
                print("otkrivaio")                 
                while u!=1:                 
                   u = ser.write( b'P')              
                u=0               
                h = 0               
                zz = 0          
     if cv2.waitKey(33) == ord('q'):         
        break cap.release() 
        cv2.destroyAllWindows()