vrvundyala's picture
face recognition
50f9fa8
import numpy as np
import cv2
from matplotlib import pyplot as plt
import torch
import torch.nn.functional as F
# 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 .face_recognition_model import Siamese
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")
det_img1 = detected_face(img1)
det_img2 = detected_face(img2)
if(det_img1 == 0 or det_img2 == 0):
det_img1 = Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY))
det_img2 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY))
face1 = trnscm(det_img1).unsqueeze(0)
face2 = trnscm(det_img2).unsqueeze(0)
##########################################################################################
##Example for loading a model using weight state dictionary: ##
## feature_net = light_cnn() #Example Network ##
## model = torch.load(current_path + '/siamese_model.t7', map_location=device) ##
## feature_net.load_state_dict(model['net_dict']) ##
## ##
##current_path + '/<network_definition>' is path of the saved model if present in ##
##the same path as this file, we recommend to put in the same directory ##
##########################################################################################
##########################################################################################
# YOUR CODE HERE, load the model
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
myModel = Siamese().to(device)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ckpt_path = os.path.join(BASE_DIR, "siamese_model.t7")
ckpt = torch.load(ckpt_path, map_location=device)
myModel.load_state_dict(ckpt['net_dict'])
myModel.eval()
# Forward pass
with torch.no_grad():
output1, output2 = myModel(face1, face2)
euclidean_distance = F.pairwise_distance(output1, output2)
# YOUR CODE HERE, return similarity measure using your model
euclidean_distance = F.pairwise_distance(output1, output2)
similarity = 1 / (1 + euclidean_distance.item())
return 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" if torch.cuda.is_available() else "cpu")
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# 1 Load the Decision Tree classifier
# clf_path = os.path.join(BASE_DIR, "decision_tree_model.sav")
clf_path = os.path.join(BASE_DIR, "SVC_3.sav")
clf = joblib.load(clf_path)
scaler_path = os.path.join(BASE_DIR, "scaler.joblib")
scaler = joblib.load(scaler_path)
# 2 Load the Siamese feature extractor
myModel = Siamese().to(device)
ckpt_path = os.path.join(BASE_DIR, "siamese_model_1.t7")
ckpt = torch.load(ckpt_path, map_location=device)
myModel.load_state_dict(ckpt['net_dict'])
myModel.eval()
# myModel = myModel.float()
# 3 Face detection (if available)
# det_img1 = detected_face(img1) # returns cropped face or 0 if not detected
# if det_img1 == 0:
# # fallback: use original image
# det_img1 = Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY))
# 4 Transform the face
img_tensor = transform1(img1).unsqueeze(0).to(device)
# 5 Extract embeddings
with torch.no_grad():
embedding = myModel.forward_once(img_tensor)
embedding = embedding.view(embedding.size(0), -1).cpu().numpy() # shape (1, embedding_dim)
# 6 Predict class using Decision Tree
pred_label = clf.predict(scaler.transform(embedding))[0]
# --- Predict ---
# scaled_emb = scaler.transform(embedding)
# probs = clf.predict_proba(scaled_emb)
# pred_label = np.argmax(probs)
# confidence = probs[0, pred_label]
# 7 Optional: return class name (if available)
# If you have the dataset available:
# class_names = finalClassifierDset.classes
# return class_names[pred_label]
# class_names = ['Aayush', 'Aditya', 'Vikram']
# return class_names[pred_label] + " " + str(pred_label)
class_names = ['Aayush', 'Aditya', 'Vikram']
return f"{class_names[pred_label]} {pred_label} {embedding}"
# def get_face_class(img1):
#
# device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# BASE_DIR = os.path.dirname(os.path.abspath(__file__))
#
# # 1 Load the Decision Tree classifier
# # clf_path = os.path.join(BASE_DIR, "decision_tree_model.sav")
# clf_path = os.path.join(BASE_DIR, "SVC_3.sav")
# clf = joblib.load(clf_path)
#
# scaler_path = os.path.join(BASE_DIR, "scaler.joblib")
# scaler = joblib.load(scaler_path)
#
# # 2 Load the Siamese feature extractor
# myModel = Siamese().to(device)
# ckpt_path = os.path.join(BASE_DIR, "siamese_model.t7")
# ckpt = torch.load(ckpt_path, map_location=device)
#
# myModel.load_state_dict(ckpt['net_dict'])
# myModel.eval()
# myModel = myModel.float()
#
# img_tensor = transform1(img1).unsqueeze(0).to(device).float()
#
# with torch.no_grad():
# embedding = myModel.forward_once(img_tensor)
# embedding = embedding.view(embedding.size(0), -1).cpu().numpy() # shape (1, embedding_dim)
# pred_label = clf.predict(scaler.transform(embedding))[0]
#
# class_names = ['Aayush', 'Aditya', 'Vikram']
# return f"{class_names[pred_label]} {pred_label} {embedding}"
# def get_face_class(img1):
# """
# img1: BGR image as numpy array (from cv2) OR path string accepted by detected_face.
# Returns: "Name label_index" or debug info.
# """
#
# device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# BASE_DIR = os.path.dirname(os.path.abspath(__file__))
#
# # 1) Load classifier + scaler
# clf_path = os.path.join(BASE_DIR, "logistic_regression_5.sav")
# scaler_path = os.path.join(BASE_DIR, "standar_scaler.sav")
# clf = joblib.load(clf_path)
# scaler = joblib.load(scaler_path)
#
# # 2) Load Siamese feature extractor
# myModel = Siamese().to(device)
# ckpt_path = os.path.join(BASE_DIR, "siamese_model.t7")
# ckpt = torch.load(ckpt_path, map_location=device)
# myModel.load_state_dict(ckpt['net_dict'])
# myModel.eval()
#
# # 3) Face detection & crop
# det_img1 = detected_face(img1) # your function: should return cropped face (preferably PIL.Image or np.uint8)
# if det_img1 == 0:
# # fallback: convert original to grayscale PIL
# if isinstance(img1, str):
# pil_img = Image.open(img1).convert("L")
# else:
# # img1 assumed BGR numpy (cv2)
# gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
# pil_img = Image.fromarray(gray)
# det_img1 = pil_img
#
# # Ensure det_img1 is a PIL Image in mode 'L' (single channel). Convert if needed.
# if isinstance(det_img1, np.ndarray):
# # if it's color BGR -> convert to gray
# if det_img1.ndim == 3 and det_img1.shape[2] == 3:
# det_img1 = cv2.cvtColor(det_img1, cv2.COLOR_BGR2GRAY)
# det_img1 = Image.fromarray(det_img1)
# det_img1 = det_img1.convert("L") # enforce single-channel
#
# # 4) Transform the face: trnscm must be the exact same transform used when creating embeddings
# img_tensor = trnscm(det_img1).unsqueeze(0) # shape: (1, C, H, W)
# img_tensor = img_tensor.to(device) # <--- IMPORTANT: move to device!
#
# # 5) Extract embeddings
# with torch.no_grad():
# embedding_t = myModel.forward_once(img_tensor) # tensor on device
# embedding_t = embedding_t.view(embedding_t.size(0), -1)
# embedding = embedding_t.cpu().numpy() # shape (1, embedding_dim)
#
# # Debug prints (uncomment if needed)
# # print("embedding shape:", embedding.shape)
# # print("embedding min/max:", embedding.min(), embedding.max())
# # print("embedding mean/std:", embedding.mean(), embedding.std())
#
# # 6) Check for NaNs / inf
# if np.isnan(embedding).any() or np.isinf(embedding).any():
# return "ERROR: embedding contains NaN or inf"
#
# # 7) Scale + predict
# try:
# scaled = scaler.transform(embedding) # ensure scaler expects shape (1, D)
# except Exception as e:
# return f"Scaler transform error: {e}"
#
# try:
# pred_label = clf.predict(scaled)[0]
# except Exception as e:
# return f"Classifier predict error: {e}"
#
# # 8) Optional: probabilities (if classifier supports it)
# confidence = None
# if hasattr(clf, "predict_proba"):
# try:
# probs = clf.predict_proba(scaled)
# confidence = float(probs.max())
# except Exception:
# confidence = None
#
# # 9) Map to class names
# class_names = ['Aayush', 'Aditya', 'Vikram'] # replace with your saved names or load from file
# name = class_names[pred_label] if pred_label < len(class_names) else str(pred_label)
#
# if confidence is not None:
# return f"{name} {pred_label} (conf={confidence:.3f})"
# else:
# return f"{name} {pred_label}"