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 + '/' 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}"