This shows you the differences between two versions of the page.
iothings:proiecte:2022:dor_bell [2023/01/19 22:50] adriana.boncu [Implementation of the solution] |
iothings:proiecte:2022:dor_bell [2023/01/20 11:31] (current) adriana.boncu [Demo Video] |
||
---|---|---|---|
Line 553: | Line 553: | ||
The software implementation on the Raspberry Pi was made in python and consists of two scripts. | The software implementation on the Raspberry Pi was made in python and consists of two scripts. | ||
- | 1. Face recognition | + | 1. Face recognition |
+ | In this script, the following is done: camera preview, face detection and calling the function to send the opening command to the ESP32. | ||
+ | |||
+ | <code python> | ||
+ | #!/usr/bin/python3 | ||
+ | import face_recognition | ||
+ | import cv2 | ||
+ | import numpy as np | ||
+ | import os | ||
+ | import glob | ||
+ | from transmisie import * | ||
+ | |||
+ | |||
+ | # Get a reference to webcam #0 (the default one) | ||
+ | video_capture = cv2.VideoCapture(0) | ||
+ | |||
+ | #make array of sample pictures with encodings | ||
+ | known_face_encodings = [] | ||
+ | known_face_names = [] | ||
+ | dirname = os.path.dirname(__file__) | ||
+ | path = os.path.join(dirname, 'known_people/') | ||
+ | |||
+ | #make an array of all the saved jpg files' paths | ||
+ | list_of_files = [f for f in glob.glob(path+'*.jpg')] | ||
+ | #find number of known faces | ||
+ | number_files = len(list_of_files) | ||
+ | |||
+ | names = list_of_files.copy() | ||
+ | |||
+ | for i in range(number_files): | ||
+ | globals()['image_{}'.format(i)] = face_recognition.load_image_file(list_of_files[i]) | ||
+ | globals()['image_encoding_{}'.format(i)] = face_recognition.face_encodings(globals()['image_{}'.format(i)])[0] | ||
+ | known_face_encodings.append(globals()['image_encoding_{}'.format(i)]) | ||
+ | |||
+ | # Create array of known names | ||
+ | names[i] = names[i].replace("known_people/", "") | ||
+ | known_face_names.append(names[i]) | ||
+ | |||
+ | # Initialize some variables | ||
+ | face_locations = [] | ||
+ | face_encodings = [] | ||
+ | face_names = [] | ||
+ | process_this_frame = True | ||
+ | |||
+ | while True: | ||
+ | # Grab a single frame of video | ||
+ | ret, frame = video_capture.read() | ||
+ | |||
+ | # Resize frame of video to 1/4 size for faster face recognition processing | ||
+ | small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) | ||
+ | |||
+ | # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses) | ||
+ | rgb_small_frame = small_frame[:, :, ::-1] | ||
+ | |||
+ | # Only process every other frame of video to save time | ||
+ | if process_this_frame: | ||
+ | # Find all the faces and face encodings in the current frame of video | ||
+ | face_locations = face_recognition.face_locations(rgb_small_frame) | ||
+ | face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) | ||
+ | |||
+ | face_names = [] | ||
+ | for face_encoding in face_encodings: | ||
+ | # See if the face is a match for the known face(s) | ||
+ | matches = face_recognition.compare_faces(known_face_encodings, face_encoding) | ||
+ | name = "Unknown" | ||
+ | |||
+ | # # If a match was found in known_face_encodings, just use the first one. | ||
+ | # if True in matches: | ||
+ | # first_match_index = matches.index(True) | ||
+ | # name = known_face_names[first_match_index] | ||
+ | |||
+ | # Or instead, use the known face with the smallest distance to the new face | ||
+ | face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) | ||
+ | best_match_index = np.argmin(face_distances) | ||
+ | if matches[best_match_index]: | ||
+ | name = known_face_names[best_match_index] | ||
+ | |||
+ | face_names.append(name) | ||
+ | |||
+ | process_this_frame = not process_this_frame | ||
+ | |||
+ | |||
+ | # Display the results | ||
+ | for (top, right, bottom, left), name in zip(face_locations, face_names): | ||
+ | # Scale back up face locations since the frame we detected in was scaled to 1/4 size | ||
+ | top *= 4 | ||
+ | right *= 4 | ||
+ | bottom *= 4 | ||
+ | left *= 4 | ||
+ | |||
+ | # Draw a box around the face | ||
+ | cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) | ||
+ | |||
+ | # Draw a label with a name below the face | ||
+ | cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) | ||
+ | font = cv2.FONT_HERSHEY_DUPLEX | ||
+ | cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1) | ||
+ | if name != "Unknown": | ||
+ | print("Known face detected!") | ||
+ | trimite_comanda() | ||
+ | |||
+ | # Display the resulting image | ||
+ | cv2.imshow('Video', frame) | ||
+ | |||
+ | # Hit 'q' on the keyboard to quit! | ||
+ | if cv2.waitKey(1) & 0xFF == ord('q'): | ||
+ | break | ||
+ | |||
+ | # Release handle to the webcam | ||
+ | video_capture.release() | ||
+ | cv2.destroyAllWindows() | ||
+ | |||
+ | </code> | ||
+ | |||
+ | 2. The opening command | ||
+ | |||
+ | When the door opening function is called in the facial recognition script, the 5 layers of security are applied and the command is sent to the ESP32. | ||
+ | |||
+ | <code python> | ||
+ | |||
+ | import socket | ||
+ | import random | ||
+ | import numpy as np | ||
+ | import math | ||
+ | import time | ||
+ | |||
+ | # criptare cu cifrul Caesar | ||
+ | def encrypt(text,s): | ||
+ | result = "" | ||
+ | for i in range(len(text)): | ||
+ | char = text[i] | ||
+ | if (char.isupper()): | ||
+ | result+=chr((ord(char) + s-65) % 26 + 65) | ||
+ | else: | ||
+ | result+=chr((ord(char) + s - 97) % 26 + 97) | ||
+ | return result | ||
+ | | ||
+ | def obtine_cheie_TCP(): | ||
+ | |||
+ | HOST = '192.168.43.5' # Adresa IP server | ||
+ | PORT = 80 # Port server | ||
+ | |||
+ | C_cunoscut = 23 | ||
+ | S_cunoscut = 9 | ||
+ | |||
+ | print('Valoarea aleasa de client cunoscuta este :%d'%(C_cunoscut)) | ||
+ | print('Valoarea aleasa de server cunoscuta este :%d'%(S_cunoscut)) | ||
+ | |||
+ | C_secret = random.randint(3, 15) | ||
+ | |||
+ | # gets the generated key | ||
+ | x_client = int(pow(S_cunoscut,C_secret,C_cunoscut)) | ||
+ | x_client_byte=bytes([x_client]) | ||
+ | |||
+ | print(x_client_byte) | ||
+ | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | ||
+ | s.connect((HOST, PORT)) | ||
+ | s.sendall(x_client_byte) | ||
+ | data = s.recv(1024) | ||
+ | # print('S-a primit', data) | ||
+ | x_server=int.from_bytes(data, "big") | ||
+ | k_secreta_client = int(pow(x_server,C_secret,C_cunoscut)) | ||
+ | print('Cheia secreta pentru client este: %d'%(k_secreta_client)) | ||
+ | | ||
+ | return k_secreta_client | ||
+ | | ||
+ | def generare_medie(x): | ||
+ | medie = [] | ||
+ | medie_com = [] | ||
+ | for i in x: | ||
+ | if i < 0: | ||
+ | medie.append(str(bin(i)[3:])) | ||
+ | aux = str(medie[len(medie) - 1]) | ||
+ | | ||
+ | for k in range(1,7-len(medie[len(medie) - 1])): | ||
+ | if k==7-len(medie[len(medie) - 1])-1: | ||
+ | aux = str(1) + aux | ||
+ | else: | ||
+ | aux = str(0) + aux | ||
+ | |||
+ | medie_com.append(aux) | ||
+ | else: | ||
+ | medie.append((str(bin(i))[2:])) | ||
+ | aux = str(medie[len(medie) - 1]) | ||
+ | |||
+ | for k in range(1,7-len(medie[len(medie) - 1])): | ||
+ | aux = str(0) + aux | ||
+ | medie_com.append(aux) | ||
+ | # print(medie) | ||
+ | # print(medie_com) | ||
+ | string_medie=str(medie_com[0])+str(medie_com[1])+str(medie_com[2])+str(medie_com[3]) | ||
+ | return string_medie | ||
+ | | ||
+ | def generare_cheie(k_secreta_client): | ||
+ | comanda='deschide' | ||
+ | start_time_enc = time.time() | ||
+ | string=encrypt(comanda,k_secreta_client) | ||
+ | print("--- Timp criptare: %.4f seconds ---" % (time.time() - start_time_enc)) | ||
+ | |||
+ | start_time_compresie = time.time() | ||
+ | i=0 | ||
+ | # "deschide" este scris in cod ascii | ||
+ | valori_ascii=[] | ||
+ | for fiecare in string: | ||
+ | valori_ascii.append(ord(fiecare)-97) | ||
+ | i=i+1 | ||
+ | |||
+ | # print(f"valori_ascii = {valori_ascii}") | ||
+ | |||
+ | x = [] # stochez media | ||
+ | diff = [] # stochez diferenta | ||
+ | even_nos = [num for num in range(len(valori_ascii)) if num % 2 == 0] | ||
+ | |||
+ | for l in even_nos: | ||
+ | x.append(math.ceil(0.5*(valori_ascii[l]+valori_ascii[l+1]))) | ||
+ | diff.append(valori_ascii[l]-valori_ascii[l+1]) | ||
+ | | ||
+ | # print(f"medie = {x}") | ||
+ | # print(f"diff = {diff}") | ||
+ | |||
+ | diff_b = [] | ||
+ | aux = str() | ||
+ | diff_b_com = [] | ||
+ | |||
+ | # adug totul la forma dorita | ||
+ | for i in diff: | ||
+ | if i < 0: | ||
+ | diff_b.append(str(bin(i)[3:])) | ||
+ | aux = str(diff_b[len(diff_b) - 1]) | ||
+ | |||
+ | for k in range(1,7-len(diff_b[len(diff_b) - 1])): | ||
+ | if k==7-len(diff_b[len(diff_b) - 1])-1: | ||
+ | aux = str(1) + aux | ||
+ | else: | ||
+ | aux = str(0) + aux | ||
+ | |||
+ | diff_b_com.append(aux) | ||
+ | else: | ||
+ | diff_b.append((str(bin(i))[2:])) | ||
+ | aux = str(diff_b[len(diff_b) - 1]) | ||
+ | |||
+ | for k in range(1,7-len(diff_b[len(diff_b) - 1])): | ||
+ | aux = str(0) + aux | ||
+ | diff_b_com.append(aux) | ||
+ | | ||
+ | | ||
+ | # print(diff_b) | ||
+ | # print(diff_b_com) | ||
+ | | ||
+ | string_medie = generare_medie(x) # generez media corespunzator | ||
+ | print("--- Timp compresie: %.4f seconds ---" % (time.time() - start_time_compresie)) | ||
+ | |||
+ | start_time_gen_cheie = time.time() | ||
+ | # declar chei pentru integrare in cheia mare si le procesez | ||
+ | ak = (bin(1))[2:] | ||
+ | bk = (bin(7))[2:] | ||
+ | |||
+ | for i in range(1,6-len(ak)): | ||
+ | ak = str(0)+ak | ||
+ | |||
+ | for i in range(1,6-len(bk)): | ||
+ | bk = str(0)+bk | ||
+ | |||
+ | key = ak+bk | ||
+ | seg1 = key[:4] | ||
+ | seg2 = key[4:8] | ||
+ | seg3 = key[8:] | ||
+ | key = str(diff_b_com[0])+seg1+str(diff_b_com[1])+seg2+str(diff_b_com[2])+seg3+str(diff_b_com[3]) | ||
+ | print("--- Timp generare cheie: %.4f seconds ---" % (time.time() - start_time_gen_cheie)) | ||
+ | return key, string_medie # returnez key si media | ||
+ | |||
+ | # Converitre lista in string | ||
+ | def listToString(s): | ||
+ | # initializez string gol | ||
+ | str1 = "" | ||
+ | # parcurg stringul | ||
+ | for ele in s: | ||
+ | str1 += ele | ||
+ | # returnez string | ||
+ | return str1 | ||
+ | |||
+ | # realizez parcurgerea orizontala | ||
+ | def vertical(key,string_medie): | ||
+ | array = [] | ||
+ | row1=[] | ||
+ | row2=[] | ||
+ | for i in range(len(key)): | ||
+ | if i%2 == 0: | ||
+ | row1.append(key[i]) | ||
+ | else: | ||
+ | row2.append(key[i]) | ||
+ | array.append(row1) | ||
+ | array.append(row2) | ||
+ | row_1 = listToString(row1) | ||
+ | row_2 = listToString(row2) | ||
+ | string = str(str(row_1)+str(row_2)+str(string_medie)) | ||
+ | return string | ||
+ | | ||
+ | def UDP_trimite_cheie(string): | ||
+ | UDP_IP = '192.168.43.5' | ||
+ | UDP_PORT = 1234 | ||
+ | MESSAGE = string | ||
+ | |||
+ | # print("UDP IP: %s" % UDP_IP) | ||
+ | # print("UDP port: %s" % UDP_PORT) | ||
+ | # print("Mesaj: %s" % MESSAGE) | ||
+ | |||
+ | sock = socket.socket(socket.AF_INET, # Internet | ||
+ | socket.SOCK_DGRAM) # UDP | ||
+ | sock.sendto(MESSAGE.encode(), (UDP_IP, UDP_PORT)) | ||
+ | |||
+ | def trimite_comanda(): | ||
+ | start_time_TCP = time.time() | ||
+ | k_secreta_client = obtine_cheie_TCP() | ||
+ | print("--- Timp TCP: %.4f seconds ---" % (time.time() - start_time_TCP)) | ||
+ | key, string_medie = generare_cheie(k_secreta_client) | ||
+ | start_time_parcurgere = time.time() | ||
+ | string = vertical(key, string_medie) | ||
+ | print("--- Timp parcurgere: %.4f seconds ---" % (time.time() - start_time_parcurgere)) | ||
+ | start_time_UDP = time.time() | ||
+ | UDP_trimite_cheie(string) | ||
+ | print("--- Timp UDP: %.4f seconds ---" % (time.time() - start_time_UDP)) | ||
+ | |||
+ | if __name__ == '__main__': | ||
+ | print("Main") | ||
+ | |||
+ | |||
+ | </code> | ||
+ | |||
+ | ====== Results obtained ====== | ||
+ | |||
+ | **1. Door Opening System | ||
+ | ** | ||
+ | |||
+ | {{ :iothings:proiecte:2022:boncu_rez_esp32.png | ESP32 | ||
+ | Results System}} | ||
+ | |||
+ | |||
+ | **2. Video Capturing System | ||
+ | ** | ||
+ | |||
+ | {{ :iothings:proiecte:2022:boncu_rez_rpi.jpeg?500x400 | RPI | ||
+ | Results System}} | ||
+ | |||
+ | |||
+ | |||
+ | ====== Demo Video ====== | ||