hackathon-4 / app /Hackathon_setup /face_recognition.py
care2achieve's picture
updated arch
5e64ee3
Raw
History Blame Contribute Delete
8.99 kB
import numpy as np
import cv2
from matplotlib import pyplot as plt
import torch
# In the below line,remove '.' while working on your local system. However Make sure that '.' is present before face_recognition_model while uploading to the server, Do not remove it.
from .face_recognition_model import *
from PIL import Image
import base64
import io
import os
import joblib
import pickle
# Add more imports if required
###########################################################################################################################################
# Caution: Don't change any of the filenames, function names and definitions #
# Always use the current_path + file_name for refering any files, without it we cannot access files on the server #
###########################################################################################################################################
# Current_path stores absolute path of the file from where it runs.
current_path = os.path.dirname(os.path.abspath(__file__))
#1) The below function is used to detect faces in the given image.
#2) It returns only one image which has maximum area out of all the detected faces in the photo.
#3) If no face is detected,then it returns zero(0).
def detected_face(image):
eye_haar = current_path + '/haarcascade_eye.xml'
face_haar = current_path + '/haarcascade_frontalface_default.xml'
face_cascade = cv2.CascadeClassifier(face_haar)
eye_cascade = cv2.CascadeClassifier(eye_haar)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
face_areas=[]
images = []
required_image=0
for i, (x,y,w,h) in enumerate(faces):
face_cropped = gray[y:y+h, x:x+w]
face_areas.append(w*h)
images.append(face_cropped)
required_image = images[np.argmax(face_areas)]
required_image = Image.fromarray(required_image)
return required_image
#1) Images captured from mobile is passed as parameter to the below function in the API call. It returns the similarity measure between given images.
#2) The image is passed to the function in base64 encoding, Code for decoding the image is provided within the function.
#3) Define an object to your siamese network here in the function and load the weight from the trained network, set it in evaluation mode.
#4) Get the features for both the faces from the network and return the similarity measure, Euclidean,cosine etc can be it. But choose the Relevant measure.
#5) For loading your model use the current_path+'your model file name', anyhow detailed example is given in comments to the function
#Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
def get_similarity(img1, img2):
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
####################################################################
# Detect faces
####################################################################
det_img1 = detected_face(img1)
det_img2 = detected_face(img2)
# fallback if no face detected
if(det_img1 == 0):
det_img1 = Image.fromarray(
cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
)
if(det_img2 == 0):
det_img2 = Image.fromarray(
cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
)
####################################################################
# Transform images
####################################################################
face1 = trnscm(det_img1).unsqueeze(0).to(device)
face2 = trnscm(det_img2).unsqueeze(0).to(device)
####################################################################
# Load trained Siamese model
####################################################################
model = Siamese().to(device)
checkpoint = torch.load(
current_path + '/siamese_model.t7',
map_location=device
)
# support both wrapped and direct state_dict
if isinstance(checkpoint, dict) and 'net_dict' in checkpoint:
model.load_state_dict(checkpoint['net_dict'])
else:
model.load_state_dict(checkpoint)
model.eval()
####################################################################
# Generate embeddings
####################################################################
with torch.no_grad():
output1 = model.forward_once(face1)
output2 = model.forward_once(face2)
####################################################################
# Euclidean distance
# lower distance => more similar
####################################################################
similarity = F.cosine_similarity(
output1,
output2
).item()
####################################################################
# Convert distance to similarity score
# similarity closer to 1 => same person
####################################################################
similarity = (similarity + 1) / 2
return float(similarity)
#1) Image captured from mobile is passed as parameter to this function in the API call, It returns the face class in the string form ex: "Person1"
#2) The image is passed to the function in base64 encoding, Code to decode the image provided within the function
#3) Define an object to your network here in the function and load the weight from the trained network, set it in evaluation mode
#4) Perform necessary transformations to the input(detected face using the above function).
#5) Along with the siamese, you need the classifier as well, which is to be finetuned with the faces that you are training
##Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
def get_face_class(img1):
device = torch.device(
"cuda:0" if torch.cuda.is_available() else "cpu"
)
####################################################################
# Detect face
####################################################################
det_img1 = detected_face(img1)
if(det_img1 == 0):
det_img1 = Image.fromarray(
cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
)
####################################################################
# Transform image
####################################################################
face = trnscm(det_img1).unsqueeze(0).to(device)
####################################################################
# Load Siamese model
####################################################################
model = Siamese().to(device)
checkpoint = torch.load(
current_path + '/siamese_model.t7',
map_location=device
)
if isinstance(checkpoint, dict) and 'net_dict' in checkpoint:
model.load_state_dict(
checkpoint['net_dict']
)
else:
model.load_state_dict(
checkpoint
)
model.eval()
####################################################################
# Load classifier
####################################################################
classifier = joblib.load(
current_path + '/face_recognition_classifier.pkl'
)
####################################################################
# Load scaler
####################################################################
scaler = joblib.load(
current_path + '/face_recognition_scaler.pkl'
)
####################################################################
# Load class names
####################################################################
classes = joblib.load(
current_path + '/class_names.pkl'
)
####################################################################
# Generate embedding
####################################################################
with torch.no_grad():
embedding = model.forward_once(face)
embedding = embedding.cpu().numpy()
####################################################################
# Scale embedding
####################################################################
embedding_scaled = scaler.transform(
embedding
)
####################################################################
# Predict class
####################################################################
predicted_label = classifier.predict(
embedding_scaled
)[0]
####################################################################
# Return class name
####################################################################
if predicted_label >= len(classes):
return "Unknown"
return classes[predicted_label]