# firstly import the necessary libraries : import cv2 import matplotlib.pyplot as plt import numpy as np import os import zipfile from os import listdir from PIL import Image from numpy import asarray,expand_dims from matplotlib import pyplot from keras.models import load_model from keras_facenet import FaceNet import pickle from mtcnn import MTCNN import math # we are going to use harr cacade first HaarCascade = cv2.CascadeClassifier(cv2.samples.findFile(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')) # if harr cascade is unable to detect we will keep mtcnn for that case # Initialize the MTCNN detector mtcnn = MTCNN() # we are going to use Facenet architecture for creating the embeddings from faces model_face = FaceNet() def process_image(image_path): image = cv2.imread(image_path,cv2.IMREAD_UNCHANGED) # for this example we are not resizing the image dimensions : resized=image image_rgb = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB) # we need to adjust the size of window in cv 2 to display the image face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') gray_image = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5) cv2.namedWindow("output", cv2.WINDOW_NORMAL) cv2.resizeWindow("output", resized.shape[0],resized.shape[1]) for (x, y, w, h) in faces: cv2.rectangle(image_rgb, (x, y), (x+w, y+h), (0, 255, 0), 2) cv2.imshow("output", image_rgb) # cv2.waitKey(0) cv2.destroyAllWindows() # convert the image back to RGB format and adjust the brighness and contrast after processing final = cv2.cvtColor(image_rgb, cv2.COLOR_BGR2RGB) final = cv2.convertScaleAbs(final, alpha=1, beta=0) # Adjust alpha and beta as needed # save the image with bounding boxes as image_detected.jpg cv2.imwrite('image_detected.jpg',final) folder_name = 'attendance_folder' if not os.path.exists(folder_name): os.mkdir(folder_name) # List all files in the folder file_list = os.listdir(folder_name) face_images = [] # Iterate through the files and remove them for file in file_list: file_path = os.path.join(folder_name, file) if os.path.isfile(file_path): os.remove(file_path) # Save the cropped photos in the folder named attendance_class for (x, y, w, h) in faces: face_crop = resized[y:y+h, x:x+w] face_images.append(face_crop) face_filename = os.path.join(folder_name, f'face_{x}_{y}.jpg') cv2.imwrite(face_filename, face_crop) # we need to adjust the size of window in cv 2 to display the image # folder_name = 'attendance_folder' # if not os.path.exists(folder_name): # os.mkdir(folder_name) # List all files in the folder # file_list = os.listdir(folder_name) # face_images = [] # # Iterate through the files and remove them # for file in file_list: # file_path = os.path.join(folder_name, file) # if os.path.isfile(file_path): # os.remove(file_path) # cv2.namedWindow("output", cv2.WINDOW_NORMAL) # cv2.resizeWindow("output", resized.shape[0],resized.shape[1]) # for face in faces: # x, y, w, h = face['box'] # cv2.rectangle(image_rgb, (x, y), (x+w, y+h), (0, 255, 0), 2) # cv2.imshow("output", image_rgb) # # cv2.waitKey(0) # face_crop = resized[y:y+h, x:x+w] # face_images.append(face_crop) # face_filename = os.path.join(folder_name, f'face_{x}_{y}.jpg') # cv2.imwrite(face_filename, face_crop) # cv2.destroyAllWindows() # # convert the image back to RGB format and adjust the brighness and contrast after processing # final = cv2.cvtColor(image_rgb, cv2.COLOR_BGR2RGB) # final = cv2.convertScaleAbs(final, alpha=1, beta=0) # Adjust alpha and beta as needed # # save the image with bounding boxes as image_detected.jpg # cv2.imwrite('image_detected.jpg',final) def intermediate_process(gbr1): # detect the face in the cropped photo : harr = HaarCascade.detectMultiScale(gbr1,1.1,4) # if the face is detected then get the width and height if len(harr)>0: x1, y1, width, height = harr[0] # if harr cascade is unable to detect the face use mtcnn else: faces_mtcnn = mtcnn.detect_faces(gbr1) if len(faces_mtcnn)>0: x1, y1, width, height = faces_mtcnn[0]['box'] else : # if no face is detected in the image just use the top left 10x10 pixels x1, y1, width, height = 1, 1, 10, 10 x1, y1 = abs(x1), abs(y1) x2, y2 = x1 + width, y1 + height #convert from bgr to rgb gbr = cv2.cvtColor(gbr1, cv2.COLOR_BGR2RGB) gbr = Image.fromarray(gbr) # Convert from OpenCV to PIL # convert image as numpy array gbr_array = asarray(gbr) # crop the face , resize it and store in face face = gbr_array[y1:y2, x1:x2] face = Image.fromarray(face) face = face.resize((160, 160)) face = asarray(face) return gbr, face def generate_embeddings(zip_path): folder_name = os.path.splitext(zip_path)[0] # Create the directory if it does not exist if not os.path.exists(folder_name): os.makedirs(folder_name) # Unzip the file with zipfile.ZipFile(zip_path, 'r') as zip_ref: zip_ref.extractall(folder_name) folder=folder_name+'/' # now generate the embeddings : # intialize empty dictionary in which we will store the embeddings with name of the person database = {} # iterate through all the images in the training images folder for filename in listdir(folder): path = folder + filename gbr1 = cv2.imread(folder + filename) gbr, face = intermediate_process(gbr1) # facenet takes as input 4 dimensional array so we expand dimension face = expand_dims(face, axis=0) signature = model_face.embeddings(face) # store the array in the database database[os.path.splitext(filename)[0]] = signature cv2.destroyAllWindows() # make a file named data_processed.pkl and store the database in it myfile = open("embeddings.pkl", "wb") pickle.dump(database, myfile) myfile.close() def recognize_faces(embeddigns_path,date): myfile = open(embeddigns_path, "rb") database = pickle.load(myfile) myfile.close() # same procedure as training folder = 'attendance_folder/' file_list = os.listdir(folder) predicted=[] # Set up the plot num_images = len(file_list) num_rows = math.ceil(num_images / 4) if math.ceil(num_images / 4)>0 else 1 # Ceiling division to calculate the number of rows fig, axes = plt.subplots(num_rows, 4, figsize=(16, 4*num_rows)) if(num_rows==1): axes=axes.reshape(1,4) for i,filename in enumerate(file_list): path = os.path.join(folder, filename) gbr1 = cv2.imread(folder + filename) gbr,face = intermediate_process(gbr1) face = expand_dims(face, axis=0) signature = model_face.embeddings(face) min_dist=100 identity=' ' for key, value in database.items() : dist = np.linalg.norm(value-signature) if dist < min_dist: min_dist = dist identity = key # Plot the image with the identity text row = i // 4 col = i % 4 axes[row, col].imshow(gbr) axes[row, col].set_title(f"Identity: {identity}", fontsize=25) axes[row, col].axis('off') # print(identity) # cv2.namedWindow("output", cv2.WINDOW_NORMAL) # cv2.resizeWindow("output", gbr1.shape[0],gbr1.shape[1]) # cv2.putText(gbr1,identity, (100,100),cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 2, cv2.LINE_AA) # cv2.rectangle(gbr1,(x1,y1),(x2,y2), (0,255,0), 2) # cv2.imshow("output",gbr1) # cv2.waitKey(0) predicted.append(identity) # Hide any remaining empty subplots for i in range(num_images, num_rows * 4): row = i // 4 col = i % 4 axes[row, col].axis('off') plt.tight_layout() fig.savefig('image_grid.jpg') cv2.destroyAllWindows() # store the name of people present in a text file attendance = [name for name in predicted if name != 'unknown'] file_name = f"{date}.txt" with open(file_name, 'w') as file: for item in attendance: file.write(str(item) + '\n')