def verify(img1_path, img2_path): backend = 'opencv' img1 = functions.preprocess_face(img1_path, target_size=(h, w), detector_backend=backend) img2 = functions.preprocess_face(img2_path, target_size=(h, w), detector_backend=backend) #----------------------------------------------------- img1_embedding = model.predict(img1)[0] img2_embedding = model.predict(img2)[0] #----------------------------------------------------- #we might need to change this logic: http://cseweb.ucsd.edu/~mkchandraker/classes/CSE252C/Spring2020/Homeworks/hw2-CSE252C-Sol.html #print(np.argmax(img1_embedding), np.argmax(img2_embedding)) return (dst.findEuclideanDistance(img1_embedding, img2_embedding), dst.findEuclideanDistance(dst.l2_normalize(img1_embedding), dst.l2_normalize(img2_embedding)), dst.findCosineDistance(img1_embedding, img2_embedding))
def distanceVectorFeature(vImage1, vImage2): #metrics = ["cosine", "euclidean", "euclidean_l2"] distanceCosine = dst.findCosineDistance(vImage1, vImage2) distanceEuclidean = dst.findEuclideanDistance(vImage1, vImage2) distanceEuclidean_l2 = dst.findEuclideanDistance(dst.l2_normalize(vImage1), dst.l2_normalize(vImage2)) distanceCosine = np.float64(distanceCosine) distanceEuclidean = np.float64(distanceEuclidean) distanceEuclidean_l2 = np.float64(distanceEuclidean_l2) return distanceCosine, distanceEuclidean, distanceEuclidean_l2
def findDistance(row): distance_metric = row['distance_metric'] img2_representation = row['embedding'] distance = 1000 #initialize very large value if distance_metric == 'cosine': distance = dst.findCosineDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean': distance = dst.findEuclideanDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean_l2': distance = dst.findEuclideanDistance(dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) return distance
def verify(encode): model_name = "DeepFace" distance_metric = "euclidean_l2" #threshold = functions.findThreshold(model_name, distance_metric) prueba = [] try: for i, template in enumerate(_personas['templates']): #distance = dst.findEuclideanDistance(dst.l2_normalize(template), dst.l2_normalize(encode)) distance = dst.findCosineDistance(template, encode) if distance <= 0.23: prueba.append({ "doc": _personas['doc_ids'][i], "distance": distance }) except: pass return prueba
def find(img_path, db_path, model_name='VGG-Face', distance_metric='cosine', model=None, enforce_detection=True): tic = time.time() if type(img_path) == list: bulkProcess = True img_paths = img_path.copy() else: bulkProcess = False img_paths = [img_path] if os.path.isdir(db_path) == True: #--------------------------------------- if model == None: if model_name == 'VGG-Face': print("Using VGG-Face model backend and", distance_metric, "distance.") model = VGGFace.loadModel() elif model_name == 'OpenFace': print("Using OpenFace model backend", distance_metric, "distance.") model = OpenFace.loadModel() elif model_name == 'Facenet': print("Using Facenet model backend", distance_metric, "distance.") model = Facenet.loadModel() elif model_name == 'DeepFace': print("Using FB DeepFace model backend", distance_metric, "distance.") model = FbDeepFace.loadModel() elif model_name == 'DeepID': print("Using DeepID model backend", distance_metric, "distance.") model = DeepID.loadModel() elif model_name == 'Ensemble': print("Ensemble learning enabled") #TODO: include DeepID in ensemble method import lightgbm as lgb #lightgbm==2.3.1 model_names = ['VGG-Face', 'Facenet', 'OpenFace', 'DeepFace'] metric_names = ['cosine', 'euclidean', 'euclidean_l2'] models = {} pbar = tqdm(range(0, len(model_names)), desc='Face recognition models') for index in pbar: if index == 0: pbar.set_description("Loading VGG-Face") models['VGG-Face'] = VGGFace.loadModel() elif index == 1: pbar.set_description("Loading FaceNet") models['Facenet'] = Facenet.loadModel() elif index == 2: pbar.set_description("Loading OpenFace") models['OpenFace'] = OpenFace.loadModel() elif index == 3: pbar.set_description("Loading DeepFace") models['DeepFace'] = FbDeepFace.loadModel() else: raise ValueError("Invalid model_name passed - ", model_name) else: #model != None print("Already built model is passed") if model_name == 'Ensemble': #validate model dictionary because it might be passed from input as pre-trained found_models = [] for key, value in model.items(): found_models.append(key) if ('VGG-Face' in found_models) and ('Facenet' in found_models) and ( 'OpenFace' in found_models) and ('DeepFace' in found_models): print("Ensemble learning will be applied for ", found_models, " models") else: raise ValueError( "You would like to apply ensemble learning and pass pre-built models but models must contain [VGG-Face, Facenet, OpenFace, DeepFace] but you passed " + found_models) #threshold = functions.findThreshold(model_name, distance_metric) #--------------------------------------- file_name = "representations_%s.pkl" % (model_name) file_name = file_name.replace("-", "_").lower() if path.exists(db_path + "/" + file_name): print( "WARNING: Representations for images in ", db_path, " folder were previously stored in ", file_name, ". If you added new instances after this file creation, then please delete this file and call find function again. It will create it again." ) f = open(db_path + '/' + file_name, 'rb') representations = pickle.load(f) print("There are ", len(representations), " representations found in ", file_name) else: employees = [] for r, d, f in os.walk( db_path): # r=root, d=directories, f = files for file in f: if ('.jpg' in file): exact_path = r + "/" + file employees.append(exact_path) if len(employees) == 0: raise ValueError("There is no image in ", db_path, " folder!") #------------------------ #find representations for db images representations = [] pbar = tqdm(range(0, len(employees)), desc='Finding representations') #for employee in employees: for index in pbar: employee = employees[index] if model_name != 'Ensemble': #input_shape = model.layers[0].input_shape[1:3] #my environment returns (None, 224, 224, 3) but some people mentioned that they got [(None, 224, 224, 3)]. I think this is because of version issue. input_shape = model.layers[0].input_shape if type(input_shape) == list: input_shape = input_shape[0][1:3] else: input_shape = input_shape[1:3] input_shape_x = input_shape[0] input_shape_y = input_shape[1] img = functions.detectFace( employee, (input_shape_y, input_shape_x), enforce_detection=enforce_detection) representation = model.predict(img)[0, :] instance = [] instance.append(employee) instance.append(representation) else: #ensemble learning instance = [] instance.append(employee) for j in model_names: model = models[j] #input_shape = model.layers[0].input_shape[1:3] #my environment returns (None, 224, 224, 3) but some people mentioned that they got [(None, 224, 224, 3)]. I think this is because of version issue. input_shape = model.layers[0].input_shape if type(input_shape) == list: input_shape = input_shape[0][1:3] else: input_shape = input_shape[1:3] input_shape_x = input_shape[0] input_shape_y = input_shape[1] img = functions.detectFace( employee, (input_shape_y, input_shape_x), enforce_detection=enforce_detection) representation = model.predict(img)[0, :] instance.append(representation) #------------------------------- representations.append(instance) f = open(db_path + '/' + file_name, "wb") pickle.dump(representations, f) f.close() print( "Representations stored in ", db_path, "/", file_name, " file. Please delete this file when you add new identities in your database." ) #---------------------------- #we got representations for database if model_name != 'Ensemble': df = pd.DataFrame(representations, columns=["identity", "representation"]) else: #ensemble learning df = pd.DataFrame(representations, columns=[ "identity", "VGG-Face_representation", "Facenet_representation", "OpenFace_representation", "DeepFace_representation" ]) df_base = df.copy() resp_obj = [] global_pbar = tqdm(range(0, len(img_paths)), desc='Analyzing') for j in global_pbar: img_path = img_paths[j] #find representation for passed image if model_name == 'Ensemble': for j in model_names: model = models[j] #input_shape = model.layers[0].input_shape[1:3] #my environment returns (None, 224, 224, 3) but some people mentioned that they got [(None, 224, 224, 3)]. I think this is because of version issue. input_shape = model.layers[0].input_shape if type(input_shape) == list: input_shape = input_shape[0][1:3] else: input_shape = input_shape[1:3] img = functions.detectFace( img_path, input_shape, enforce_detection=enforce_detection) target_representation = model.predict(img)[0, :] for k in metric_names: distances = [] for index, instance in df.iterrows(): source_representation = instance[ "%s_representation" % (j)] if k == 'cosine': distance = dst.findCosineDistance( source_representation, target_representation) elif k == 'euclidean': distance = dst.findEuclideanDistance( source_representation, target_representation) elif k == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(source_representation), dst.l2_normalize(target_representation)) distances.append(distance) if j == 'OpenFace' and k == 'euclidean': continue else: df["%s_%s" % (j, k)] = distances #---------------------------------- feature_names = [] for j in model_names: for k in metric_names: if j == 'OpenFace' and k == 'euclidean': continue else: feature = '%s_%s' % (j, k) feature_names.append(feature) #print(df[feature_names].head()) x = df[feature_names].values #---------------------------------- #lightgbm model home = str(Path.home()) if os.path.isfile( home + '/.deepface/weights/face-recognition-ensemble-model.txt' ) != True: print( "face-recognition-ensemble-model.txt will be downloaded..." ) url = 'https://raw.githubusercontent.com/serengil/deepface/master/deepface/models/face-recognition-ensemble-model.txt' output = home + '/.deepface/weights/face-recognition-ensemble-model.txt' gdown.download(url, output, quiet=False) ensemble_model_path = home + '/.deepface/weights/face-recognition-ensemble-model.txt' deepface_ensemble = lgb.Booster(model_file=ensemble_model_path) y = deepface_ensemble.predict(x) verified_labels = [] scores = [] for i in y: verified = np.argmax(i) == 1 score = i[np.argmax(i)] verified_labels.append(verified) scores.append(score) df['verified'] = verified_labels df['score'] = scores df = df[df.verified == True] #df = df[df.score > 0.99] #confidence score df = df.sort_values(by=["score"], ascending=False).reset_index(drop=True) df = df[['identity', 'verified', 'score']] resp_obj.append(df) df = df_base.copy() #restore df for the next iteration #---------------------------------- if model_name != 'Ensemble': #input_shape = model.layers[0].input_shape[1:3] #my environment returns (None, 224, 224, 3) but some people mentioned that they got [(None, 224, 224, 3)]. I think this is because of version issue. input_shape = model.layers[0].input_shape if type(input_shape) == list: input_shape = input_shape[0][1:3] else: input_shape = input_shape[1:3] input_shape_x = input_shape[0] input_shape_y = input_shape[1] img = functions.detectFace(img_path, (input_shape_y, input_shape_x), enforce_detection=enforce_detection) target_representation = model.predict(img)[0, :] distances = [] for index, instance in df.iterrows(): source_representation = instance["representation"] if distance_metric == 'cosine': distance = dst.findCosineDistance( source_representation, target_representation) elif distance_metric == 'euclidean': distance = dst.findEuclideanDistance( source_representation, target_representation) elif distance_metric == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(source_representation), dst.l2_normalize(target_representation)) else: raise ValueError("Invalid distance_metric passed - ", distance_metric) distances.append(distance) threshold = functions.findThreshold(model_name, distance_metric) df["distance"] = distances df = df.drop(columns=["representation"]) df = df[df.distance <= threshold] df = df.sort_values(by=["distance"], ascending=True).reset_index(drop=True) resp_obj.append(df) df = df_base.copy() #restore df for the next iteration toc = time.time() print("find function lasts ", toc - tic, " seconds") if len(resp_obj) == 1: return resp_obj[0] return resp_obj else: raise ValueError("Passed db_path does not exist!") return None
def verify(img1_path, img2_path='', model_name='VGG-Face', distance_metric='cosine', model=None, enforce_detection=True): tic = time.time() if type(img1_path) == list: bulkProcess = True img_list = img1_path.copy() else: bulkProcess = False img_list = [[img1_path, img2_path]] #------------------------------ resp_objects = [] if model_name == 'Ensemble': print("Ensemble learning enabled") import lightgbm as lgb #lightgbm==2.3.1 if model == None: model = {} model_pbar = tqdm(range(0, 4), desc='Face recognition models') for index in model_pbar: if index == 0: model_pbar.set_description("Loading VGG-Face") model["VGG-Face"] = VGGFace.loadModel() elif index == 1: model_pbar.set_description("Loading Google FaceNet") model["Facenet"] = Facenet.loadModel() elif index == 2: model_pbar.set_description("Loading OpenFace") model["OpenFace"] = OpenFace.loadModel() elif index == 3: model_pbar.set_description("Loading Facebook DeepFace") model["DeepFace"] = FbDeepFace.loadModel() #-------------------------- #validate model dictionary because it might be passed from input as pre-trained found_models = [] for key, value in model.items(): found_models.append(key) if ('VGG-Face' in found_models) and ('Facenet' in found_models) and ( 'OpenFace' in found_models) and ('DeepFace' in found_models): print("Ensemble learning will be applied for ", found_models, " models") else: raise ValueError( "You would like to apply ensemble learning and pass pre-built models but models must contain [VGG-Face, Facenet, OpenFace, DeepFace] but you passed " + found_models) #-------------------------- model_names = ["VGG-Face", "Facenet", "OpenFace", "DeepFace"] metrics = ["cosine", "euclidean", "euclidean_l2"] pbar = tqdm(range(0, len(img_list)), desc='Verification') #for instance in img_list: for index in pbar: instance = img_list[index] if type(instance) == list and len(instance) >= 2: img1_path = instance[0] img2_path = instance[1] ensemble_features = [] ensemble_features_string = "[" for i in model_names: custom_model = model[i] #input_shape = custom_model.layers[0].input_shape[1:3] #my environment returns (None, 224, 224, 3) but some people mentioned that they got [(None, 224, 224, 3)]. I think this is because of version issue. input_shape = custom_model.layers[0].input_shape if type(input_shape) == list: input_shape = input_shape[0][1:3] else: input_shape = input_shape[1:3] img1 = functions.detectFace( img1_path, input_shape, enforce_detection=enforce_detection) img2 = functions.detectFace( img2_path, input_shape, enforce_detection=enforce_detection) img1_representation = custom_model.predict(img1)[0, :] img2_representation = custom_model.predict(img2)[0, :] for j in metrics: if j == 'cosine': distance = dst.findCosineDistance( img1_representation, img2_representation) elif j == 'euclidean': distance = dst.findEuclideanDistance( img1_representation, img2_representation) elif j == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) if i == 'OpenFace' and j == 'euclidean': #this returns same with OpenFace - euclidean_l2 continue else: ensemble_features.append(distance) if len(ensemble_features) > 1: ensemble_features_string += ", " ensemble_features_string += str(distance) #print("ensemble_features: ", ensemble_features) ensemble_features_string += "]" #------------------------------- #find deepface path home = str(Path.home()) if os.path.isfile( home + '/.deepface/weights/face-recognition-ensemble-model.txt' ) != True: print( "face-recognition-ensemble-model.txt will be downloaded..." ) url = 'https://raw.githubusercontent.com/serengil/deepface/master/deepface/models/face-recognition-ensemble-model.txt' output = home + '/.deepface/weights/face-recognition-ensemble-model.txt' gdown.download(url, output, quiet=False) ensemble_model_path = home + '/.deepface/weights/face-recognition-ensemble-model.txt' #print(ensemble_model_path) #------------------------------- deepface_ensemble = lgb.Booster(model_file=ensemble_model_path) prediction = deepface_ensemble.predict( np.expand_dims(np.array(ensemble_features), axis=0))[0] verified = np.argmax(prediction) == 1 if verified: identified = "true" else: identified = "false" score = prediction[np.argmax(prediction)] #print("verified: ", verified,", score: ", score) resp_obj = "{" resp_obj += "\"verified\": " + identified resp_obj += ", \"score\": " + str(score) resp_obj += ", \"distance\": " + ensemble_features_string resp_obj += ", \"model\": [\"VGG-Face\", \"Facenet\", \"OpenFace\", \"DeepFace\"]" resp_obj += ", \"similarity_metric\": [\"cosine\", \"euclidean\", \"euclidean_l2\"]" resp_obj += "}" #print(resp_obj) resp_obj = json.loads(resp_obj) #string to json if bulkProcess == True: resp_objects.append(resp_obj) else: return resp_obj #------------------------------- if bulkProcess == True: resp_obj = "{" for i in range(0, len(resp_objects)): resp_item = json.dumps(resp_objects[i]) if i > 0: resp_obj += ", " resp_obj += "\"pair_" + str(i + 1) + "\": " + resp_item resp_obj += "}" resp_obj = json.loads(resp_obj) return resp_obj return None #ensemble learning block end #-------------------------------- #ensemble learning disabled if model == None: if model_name == 'VGG-Face': print("Using VGG-Face model backend and", distance_metric, "distance.") model = VGGFace.loadModel() elif model_name == 'OpenFace': print("Using OpenFace model backend", distance_metric, "distance.") model = OpenFace.loadModel() elif model_name == 'Facenet': print("Using Facenet model backend", distance_metric, "distance.") model = Facenet.loadModel() elif model_name == 'DeepFace': print("Using FB DeepFace model backend", distance_metric, "distance.") model = FbDeepFace.loadModel() elif model_name == 'DeepID': print("Using DeepID2 model backend", distance_metric, "distance.") model = DeepID.loadModel() else: raise ValueError("Invalid model_name passed - ", model_name) else: #model != None print("Already built model is passed") #------------------------------ #face recognition models have different size of inputs #input_shape = model.layers[0].input_shape[1:3] #my environment returns (None, 224, 224, 3) but some people mentioned that they got [(None, 224, 224, 3)]. I think this is because of version issue. input_shape = model.layers[0].input_shape if type(input_shape) == list: input_shape = input_shape[0][1:3] else: input_shape = input_shape[1:3] input_shape_x = input_shape[0] input_shape_y = input_shape[1] #------------------------------ #tuned thresholds for model and metric pair threshold = functions.findThreshold(model_name, distance_metric) #------------------------------ pbar = tqdm(range(0, len(img_list)), desc='Verification') #for instance in img_list: for index in pbar: instance = img_list[index] if type(instance) == list and len(instance) >= 2: img1_path = instance[0] img2_path = instance[1] #---------------------- #crop and align faces img1 = functions.detectFace(img1_path, (input_shape_y, input_shape_x), enforce_detection=enforce_detection) img2 = functions.detectFace(img2_path, (input_shape_y, input_shape_x), enforce_detection=enforce_detection) #---------------------- #find embeddings img1_representation = model.predict(img1)[0, :] img2_representation = model.predict(img2)[0, :] #---------------------- #find distances between embeddings if distance_metric == 'cosine': distance = dst.findCosineDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean': distance = dst.findEuclideanDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) else: raise ValueError("Invalid distance_metric passed - ", distance_metric) #---------------------- #decision if distance <= threshold: identified = "true" else: identified = "false" #---------------------- #response object resp_obj = "{" resp_obj += "\"verified\": " + identified resp_obj += ", \"distance\": " + str(distance) resp_obj += ", \"max_threshold_to_verify\": " + str(threshold) resp_obj += ", \"model\": \"" + model_name + "\"" resp_obj += ", \"similarity_metric\": \"" + distance_metric + "\"" resp_obj += "}" resp_obj = json.loads(resp_obj) #string to json if bulkProcess == True: resp_objects.append(resp_obj) else: #K.clear_session() return resp_obj #---------------------- else: raise ValueError("Invalid arguments passed to verify function: ", instance) #------------------------- toc = time.time() #print("identification lasts ",toc-tic," seconds") if bulkProcess == True: resp_obj = "{" for i in range(0, len(resp_objects)): resp_item = json.dumps(resp_objects[i]) if i > 0: resp_obj += ", " resp_obj += "\"pair_" + str(i + 1) + "\": " + resp_item resp_obj += "}" resp_obj = json.loads(resp_obj) return resp_obj
def verify(img1_path, img2_path, model_name='VGG-Face', distance_metric='cosine', plot=False): tic = time.time() if os.path.isfile(img1_path) != True: raise ValueError("Confirm that ", img1_path, " exists") if os.path.isfile(img2_path) != True: raise ValueError("Confirm that ", img2_path, " exists") #------------------------- #tuned thresholds for model and metric pair threshold = functions.findThreshold(model_name, distance_metric) #------------------------- if model_name == 'VGG-Face': print("Using VGG-Face model backend and", distance_metric, "distance.") model = VGGFace.loadModel() input_shape = (224, 224) elif model_name == 'OpenFace': print("Using OpenFace model backend", distance_metric, "distance.") model = OpenFace.loadModel() input_shape = (96, 96) elif model_name == 'Facenet': print("Using Facenet model backend", distance_metric, "distance.") model = Facenet.loadModel() input_shape = (160, 160) elif model_name == 'DeepFace': print("Using FB DeepFace model backend", distance_metric, "distance.") model = FbDeepFace.loadModel() input_shape = (152, 152) else: raise ValueError("Invalid model_name passed - ", model_name) #------------------------- #crop face img1 = functions.detectFace(img1_path, input_shape) img2 = functions.detectFace(img2_path, input_shape) #------------------------- #find embeddings img1_representation = model.predict(img1)[0, :] img2_representation = model.predict(img2)[0, :] #------------------------- #find distances between embeddings if distance_metric == 'cosine': distance = dst.findCosineDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean': distance = dst.findEuclideanDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) else: raise ValueError("Invalid distance_metric passed - ", distance_metric) #------------------------- #decision if distance <= threshold: identified = "true" else: identified = "false" #------------------------- if plot: label = "Verified: " + identified label += "\nThreshold: " + str(round(distance, 2)) label += ", Max Threshold to Verify: " + str(threshold) label += "\nModel: " + model_name label += ", Similarity metric: " + distance_metric fig = plt.figure() fig.add_subplot(1, 2, 1) plt.imshow(img1[0][:, :, ::-1]) plt.xticks([]) plt.yticks([]) fig.add_subplot(1, 2, 2) plt.imshow(img2[0][:, :, ::-1]) plt.xticks([]) plt.yticks([]) fig.suptitle(label, fontsize=17) plt.show(block=True) #------------------------- toc = time.time() resp_obj = "{" resp_obj += "\"verified\": " + identified resp_obj += ", \"distance\": " + str(distance) resp_obj += ", \"max_threshold_to_verify\": " + str(threshold) resp_obj += ", \"model\": \"" + model_name + "\"" resp_obj += ", \"similarity_metric\": \"" + distance_metric + "\"" resp_obj += "}" resp_obj = json.loads(resp_obj) #string to json #print("identification lasts ",toc-tic," seconds") return resp_obj
def find(img_path, db_path, model_name='VGG-Face', distance_metric='cosine', model=None, enforce_detection=True, detector_backend='mtcnn'): """ This function applies verification several times and find an identity in a database Parameters: img_path: exact image path, numpy array or based64 encoded image. If you are going to find several identities, then you should pass img_path as array instead of calling find function in a for loop. e.g. img_path = ["img1.jpg", "img2.jpg"] db_path (string): You should store some .jpg files in a folder and pass the exact folder path to this. model_name (string): VGG-Face, Facenet, OpenFace, DeepFace, DeepID, Dlib or Ensemble distance_metric (string): cosine, euclidean, euclidean_l2 model: built deepface model. A face recognition models are built in every call of find function. You can pass pre-built models to speed the function up. model = DeepFace.build_model('VGG-Face') enforce_detection (boolean): The function throws exception if a face could not be detected. Set this to True if you don't want to get exception. This might be convenient for low resolution images. detector_backend (string): set face detector backend as mtcnn, opencv, ssd or dlib Returns: This function returns pandas data frame. If a list of images is passed to img_path, then it will return list of pandas data frame. """ tic = time.time() img_paths, bulkProcess = functions.initialize_input(img_path) functions.initialize_detector(detector_backend=detector_backend) #------------------------------- if os.path.isdir(db_path) == True: if model == None: if model_name == 'Ensemble': print("Ensemble learning enabled") models = Boosting.loadModel() else: #model is not ensemble model = build_model(model_name) models = {} models[model_name] = model else: #model != None print("Already built model is passed") if model_name == 'Ensemble': Boosting.validate_model(model) models = model.copy() else: models = {} models[model_name] = model #--------------------------------------- if model_name == 'Ensemble': model_names = ['VGG-Face', 'Facenet', 'OpenFace', 'DeepFace'] metric_names = ['cosine', 'euclidean', 'euclidean_l2'] elif model_name != 'Ensemble': model_names = [] metric_names = [] model_names.append(model_name) metric_names.append(distance_metric) #--------------------------------------- file_name = "representations_%s.pkl" % (model_name) file_name = file_name.replace("-", "_").lower() if path.exists(db_path + "/" + file_name): # print("WARNING: Representations for images in ",db_path," folder were previously stored in ", file_name, ". If you added new instances after this file creation, then please delete this file and call find function again. It will create it again.") f = open(db_path + '/' + file_name, 'rb') representations = pickle.load(f) print("There are ", len(representations), " representations found in ", file_name) else: #create representation.pkl from scratch employees = [] for r, d, f in os.walk( db_path): # r=root, d=directories, f = files for file in f: if ('.jpg' in file.lower()) or ('.png' in file.lower()): exact_path = r + "/" + file employees.append(exact_path) if len(employees) == 0: raise ValueError( "There is no image in ", db_path, " folder! Validate .jpg or .png files exist in this path.") #------------------------ #find representations for db images representations = [] pbar = tqdm(range(0, len(employees)), desc='Finding representations') #for employee in employees: for index in pbar: employee = employees[index] instance = [] instance.append(employee) for j in model_names: custom_model = models[j] #---------------------------------- #decide input shape input_shape = functions.find_input_shape(custom_model) input_shape_x = input_shape[0] input_shape_y = input_shape[1] #---------------------------------- img = functions.preprocess_face( img=employee, target_size=(input_shape_y, input_shape_x), enforce_detection=enforce_detection, detector_backend=detector_backend) representation = custom_model.predict(img)[0, :] instance.append(representation) #------------------------------- representations.append(instance) f = open(db_path + '/' + file_name, "wb") pickle.dump(representations, f) f.close() print( "Representations stored in ", db_path, "/", file_name, " file. Please delete this file when you add new identities in your database." ) #---------------------------- #now, we got representations for facial database if model_name != 'Ensemble': df = pd.DataFrame( representations, columns=["identity", "%s_representation" % (model_name)]) else: #ensemble learning columns = ['identity'] [columns.append('%s_representation' % i) for i in model_names] df = pd.DataFrame(representations, columns=columns) df_base = df.copy( ) #df will be filtered in each img. we will restore it for the next item. resp_obj = [] global_pbar = tqdm(range(0, len(img_paths)), desc='Analyzing') for j in global_pbar: img_path = img_paths[j] #find representation for passed image for j in model_names: custom_model = models[j] #-------------------------------- #decide input shape input_shape = functions.find_input_shape(custom_model) input_shape_x = input_shape[0] input_shape_y = input_shape[1] #-------------------------------- img = functions.preprocess_face( img=img_path, target_size=(input_shape_y, input_shape_x), enforce_detection=enforce_detection, detector_backend=detector_backend) target_representation = custom_model.predict(img)[0, :] for k in metric_names: distances = [] for index, instance in df.iterrows(): source_representation = instance["%s_representation" % (j)] if k == 'cosine': distance = dst.findCosineDistance( source_representation, target_representation) elif k == 'euclidean': distance = dst.findEuclideanDistance( source_representation, target_representation) elif k == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(source_representation), dst.l2_normalize(target_representation)) distances.append(distance) #--------------------------- if model_name == 'Ensemble' and j == 'OpenFace' and k == 'euclidean': continue else: df["%s_%s" % (j, k)] = distances if model_name != 'Ensemble': threshold = dst.findThreshold(j, k) df = df.drop(columns=["%s_representation" % (j)]) df = df[df["%s_%s" % (j, k)] <= threshold] df = df.sort_values( by=["%s_%s" % (j, k)], ascending=True).reset_index(drop=True) resp_obj.append(df) df = df_base.copy( ) #restore df for the next iteration #---------------------------------- if model_name == 'Ensemble': feature_names = [] for j in model_names: for k in metric_names: if model_name == 'Ensemble' and j == 'OpenFace' and k == 'euclidean': continue else: feature = '%s_%s' % (j, k) feature_names.append(feature) #print(df.head()) x = df[feature_names].values #-------------------------------------- boosted_tree = Boosting.build_gbm() y = boosted_tree.predict(x) verified_labels = [] scores = [] for i in y: verified = np.argmax(i) == 1 score = i[np.argmax(i)] verified_labels.append(verified) scores.append(score) df['verified'] = verified_labels df['score'] = scores df = df[df.verified == True] #df = df[df.score > 0.99] #confidence score df = df.sort_values(by=["score"], ascending=False).reset_index(drop=True) df = df[['identity', 'verified', 'score']] resp_obj.append(df) df = df_base.copy() #restore df for the next iteration #---------------------------------- toc = time.time() print("find function lasts ", toc - tic, " seconds") if len(resp_obj) == 1: return resp_obj[0] return resp_obj else: raise ValueError("Passed db_path does not exist!") return None
def verify(img1_path, img2_path='', model_name='VGG-Face', distance_metric='cosine', model=None, enforce_detection=True, detector_backend='mtcnn'): """ This function verifies an image pair is same person or different persons. Parameters: img1_path, img2_path: exact image path, numpy array or based64 encoded images could be passed. If you are going to call verify function for a list of image pairs, then you should pass an array instead of calling the function in for loops. e.g. img1_path = [ ['img1.jpg', 'img2.jpg'], ['img2.jpg', 'img3.jpg'] ] model_name (string): VGG-Face, Facenet, OpenFace, DeepFace, DeepID, Dlib, ArcFace or Ensemble distance_metric (string): cosine, euclidean, euclidean_l2 model: Built deepface model. A face recognition model is built every call of verify function. You can pass pre-built face recognition model optionally if you will call verify function several times. model = DeepFace.build_model('VGG-Face') enforce_detection (boolean): If any face could not be detected in an image, then verify function will return exception. Set this to False not to have this exception. This might be convenient for low resolution images. detector_backend (string): set face detector backend as mtcnn, opencv, ssd or dlib Returns: Verify function returns a dictionary. If img1_path is a list of image pairs, then the function will return list of dictionary. { "verified": True , "distance": 0.2563 , "max_threshold_to_verify": 0.40 , "model": "VGG-Face" , "similarity_metric": "cosine" } """ tic = time.time() img_list, bulkProcess = functions.initialize_input(img1_path, img2_path) functions.initialize_detector(detector_backend=detector_backend) resp_objects = [] #-------------------------------- if model_name == 'Ensemble': model_names = ["VGG-Face", "Facenet", "OpenFace", "DeepFace"] metrics = ["cosine", "euclidean", "euclidean_l2"] else: model_names = [] metrics = [] model_names.append(model_name) metrics.append(distance_metric) #-------------------------------- if model == None: if model_name == 'Ensemble': models = Boosting.loadModel() else: model = build_model(model_name) models = {} models[model_name] = model else: if model_name == 'Ensemble': Boosting.validate_model(model) models = model.copy() else: models = {} models[model_name] = model #------------------------------ #calling deepface in a for loop causes lots of progress bars. this prevents it. disable_option = False if len(img_list) > 1 else True pbar = tqdm(range(0, len(img_list)), desc='Verification', disable=disable_option) for index in pbar: instance = img_list[index] if type(instance) == list and len(instance) >= 2: img1_path = instance[0] img2_path = instance[1] ensemble_features = [] for i in model_names: custom_model = models[i] #decide input shape input_shape = functions.find_input_shape(custom_model) input_shape_x = input_shape[0] input_shape_y = input_shape[1] #---------------------- #detect and align faces img1 = functions.preprocess_face( img=img1_path, target_size=(input_shape_y, input_shape_x), enforce_detection=enforce_detection, detector_backend=detector_backend) img2 = functions.preprocess_face( img=img2_path, target_size=(input_shape_y, input_shape_x), enforce_detection=enforce_detection, detector_backend=detector_backend) #---------------------- #find embeddings img1_representation = custom_model.predict(img1)[0, :] img2_representation = custom_model.predict(img2)[0, :] #---------------------- #find distances between embeddings for j in metrics: if j == 'cosine': distance = dst.findCosineDistance( img1_representation, img2_representation) elif j == 'euclidean': distance = dst.findEuclideanDistance( img1_representation, img2_representation) elif j == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) else: raise ValueError("Invalid distance_metric passed - ", distance_metric) distance = np.float64( distance ) #causes trobule for euclideans in api calls if this is not set (issue #175) #---------------------- #decision if model_name != 'Ensemble': threshold = dst.findThreshold(i, j) if distance <= threshold: identified = True else: identified = False resp_obj = { "verified": identified, "distance": distance, "max_threshold_to_verify": threshold, "model": model_name, "similarity_metric": distance_metric } if bulkProcess == True: resp_objects.append(resp_obj) else: return resp_obj else: #Ensemble #this returns same with OpenFace - euclidean_l2 if i == 'OpenFace' and j == 'euclidean': continue else: ensemble_features.append(distance) #---------------------- if model_name == 'Ensemble': boosted_tree = Boosting.build_gbm() prediction = boosted_tree.predict( np.expand_dims(np.array(ensemble_features), axis=0))[0] verified = np.argmax(prediction) == 1 score = prediction[np.argmax(prediction)] resp_obj = { "verified": verified, "score": score, "distance": ensemble_features, "model": ["VGG-Face", "Facenet", "OpenFace", "DeepFace"], "similarity_metric": ["cosine", "euclidean", "euclidean_l2"] } if bulkProcess == True: resp_objects.append(resp_obj) else: return resp_obj #---------------------- else: raise ValueError("Invalid arguments passed to verify function: ", instance) #------------------------- toc = time.time() if bulkProcess == True: resp_obj = {} for i in range(0, len(resp_objects)): resp_item = resp_objects[i] resp_obj["pair_%d" % (i + 1)] = resp_item return resp_obj
def verify(img1_path, img2_path , model_name ='VGG-Face', distance_metric = 'cosine'): tic = time.time() if os.path.isfile(img1_path) != True: raise ValueError("Confirm that ",img1_path," exists") if os.path.isfile(img2_path) != True: raise ValueError("Confirm that ",img2_path," exists") #------------------------- #print("Face verification will be applied on ",model_name," model and ",distance_metric," metric") functions.validateInputs(model_name, distance_metric) #------------------------- #tuned thresholds for model and metric pair threshold = functions.findThreshold(model_name, distance_metric) #------------------------- if model_name == 'VGG-Face': model = VGGFace.loadModel() input_shape = (224, 224) elif model_name == 'OpenFace': model = OpenFace.loadModel() input_shape = (96, 96) elif model_name == 'Facenet': model = Facenet.loadModel() input_shape = (160, 160) #------------------------- #crop face img1 = functions.detectFace(img1_path, input_shape) img2 = functions.detectFace(img2_path, input_shape) #------------------------- #TO-DO: Apply face alignment here. Experiments show that aligment increases accuracy 1%. #------------------------- #find embeddings img1_representation = model.predict(img1)[0,:] img2_representation = model.predict(img2)[0,:] #------------------------- #find distances between embeddings if distance_metric == 'cosine': distance = dst.findCosineDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean': distance = dst.findEuclideanDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean_l2': distance = dst.findEuclideanDistance(dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) #------------------------- #decision if distance <= threshold: identified = True message = "The both face photos are same person." else: identified = False message = "The both face photos are not same person!" #------------------------- plot = False if plot: label = "Distance is "+str(round(distance, 2))+"\nwhereas max threshold is "+ str(threshold)+ ".\n"+ message fig = plt.figure() fig.add_subplot(1,2, 1) plt.imshow(img1[0][:, :, ::-1]) plt.xticks([]); plt.yticks([]) fig.add_subplot(1,2, 2) plt.imshow(img2[0][:, :, ::-1]) plt.xticks([]); plt.yticks([]) fig.suptitle(label, fontsize=17) plt.show(block=True) #------------------------- toc = time.time() #print("identification lasts ",toc-tic," seconds") #Return a tuple. First item is the identification result based on tuned threshold. #Second item is the threshold. You might want to customize this threshold to identify faces. return (identified, distance, threshold)
def verify(img1_path, img2_path='', model_name='VGG-Face', distance_metric='cosine', model=None, enforce_detection=True, detector_backend='mtcnn'): tic = time.time() img_list, bulkProcess = initialize_input(img1_path, img2_path) functions.initialize_detector(detector_backend=detector_backend) resp_objects = [] #-------------------------------- if model_name == 'Ensemble': model_names = ["VGG-Face", "Facenet", "OpenFace", "DeepFace"] metrics = ["cosine", "euclidean", "euclidean_l2"] else: model_names = [] metrics = [] model_names.append(model_name) metrics.append(distance_metric) #-------------------------------- if model == None: if model_name == 'Ensemble': models = Boosting.loadModel() else: model = build_model(model_name) models = {} models[model_name] = model else: if model_name == 'Ensemble': Boosting.validate_model(model) else: models = {} models[model_name] = model #------------------------------ #calling deepface in a for loop causes lots of progress bars. this prevents it. disable_option = False if len(img_list) > 1 else True pbar = tqdm(range(0, len(img_list)), desc='Verification', disable=disable_option) for index in pbar: instance = img_list[index] if type(instance) == list and len(instance) >= 2: img1_path = instance[0] img2_path = instance[1] ensemble_features = [] for i in model_names: custom_model = models[i] #decide input shape input_shape = functions.find_input_shape(custom_model) input_shape_x = input_shape[0] input_shape_y = input_shape[1] #---------------------- #detect and align faces img1 = functions.preprocess_face( img=img1_path, target_size=(input_shape_y, input_shape_x), enforce_detection=enforce_detection, detector_backend=detector_backend) img2 = functions.preprocess_face( img=img2_path, target_size=(input_shape_y, input_shape_x), enforce_detection=enforce_detection, detector_backend=detector_backend) #---------------------- #find embeddings img1_representation = custom_model.predict(img1)[0, :] img2_representation = custom_model.predict(img2)[0, :] #---------------------- #find distances between embeddings for j in metrics: if j == 'cosine': distance = dst.findCosineDistance( img1_representation, img2_representation) elif j == 'euclidean': distance = dst.findEuclideanDistance( img1_representation, img2_representation) elif j == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) else: raise ValueError("Invalid distance_metric passed - ", distance_metric) #---------------------- #decision if model_name != 'Ensemble': threshold = dst.findThreshold(i, j) if distance <= threshold: identified = True else: identified = False resp_obj = { "verified": identified, "distance": distance, "max_threshold_to_verify": threshold, "model": model_name, "similarity_metric": distance_metric } if bulkProcess == True: resp_objects.append(resp_obj) else: return resp_obj else: #Ensemble #this returns same with OpenFace - euclidean_l2 if i == 'OpenFace' and j == 'euclidean': continue else: ensemble_features.append(distance) #---------------------- if model_name == 'Ensemble': boosted_tree = Boosting.build_gbm() prediction = boosted_tree.predict( np.expand_dims(np.array(ensemble_features), axis=0))[0] verified = np.argmax(prediction) == 1 score = prediction[np.argmax(prediction)] resp_obj = { "verified": verified, "score": score, "distance": ensemble_features, "model": ["VGG-Face", "Facenet", "OpenFace", "DeepFace"], "similarity_metric": ["cosine", "euclidean", "euclidean_l2"] } if bulkProcess == True: resp_objects.append(resp_obj) else: return resp_obj #---------------------- else: raise ValueError("Invalid arguments passed to verify function: ", instance) #------------------------- toc = time.time() if bulkProcess == True: resp_obj = {} for i in range(0, len(resp_objects)): resp_item = resp_objects[i] resp_obj["pair_%d" % (i + 1)] = resp_item return resp_obj
def verify(img1_path, img2_path='', model_name='VGG-Face', distance_metric='cosine', model=None, enforce_detection=True): tic = time.time() if type(img1_path) == list: bulkProcess = True img_list = img1_path.copy() else: bulkProcess = False img_list = [[img1_path, img2_path]] #------------------------------ if model == None: if model_name == 'VGG-Face': print("Using VGG-Face model backend and", distance_metric, "distance.") model = VGGFace.loadModel() elif model_name == 'OpenFace': print("Using OpenFace model backend", distance_metric, "distance.") model = OpenFace.loadModel() elif model_name == 'Facenet': print("Using Facenet model backend", distance_metric, "distance.") model = Facenet.loadModel() elif model_name == 'DeepFace': print("Using FB DeepFace model backend", distance_metric, "distance.") model = FbDeepFace.loadModel() else: raise ValueError("Invalid model_name passed - ", model_name) else: #model != None print("Already built model is passed") #------------------------------ #face recognition models have different size of inputs input_shape = model.layers[0].input_shape[1:3] #------------------------------ #tuned thresholds for model and metric pair threshold = functions.findThreshold(model_name, distance_metric) #------------------------------ pbar = tqdm(range(0, len(img_list)), desc='Verification') resp_objects = [] #for instance in img_list: for index in pbar: instance = img_list[index] if type(instance) == list and len(instance) >= 2: img1_path = instance[0] img2_path = instance[1] #---------------------- #crop and align faces img1 = functions.detectFace(img1_path, input_shape, enforce_detection=enforce_detection) img2 = functions.detectFace(img2_path, input_shape, enforce_detection=enforce_detection) #---------------------- #find embeddings img1_representation = model.predict(img1)[0, :] img2_representation = model.predict(img2)[0, :] #---------------------- #find distances between embeddings if distance_metric == 'cosine': distance = dst.findCosineDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean': distance = dst.findEuclideanDistance(img1_representation, img2_representation) elif distance_metric == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(img1_representation), dst.l2_normalize(img2_representation)) else: raise ValueError("Invalid distance_metric passed - ", distance_metric) #---------------------- #decision if distance <= threshold: identified = "true" else: identified = "false" #---------------------- #response object resp_obj = "{" resp_obj += "\"verified\": " + identified resp_obj += ", \"distance\": " + str(distance) resp_obj += ", \"max_threshold_to_verify\": " + str(threshold) resp_obj += ", \"model\": \"" + model_name + "\"" resp_obj += ", \"similarity_metric\": \"" + distance_metric + "\"" resp_obj += "}" resp_obj = json.loads(resp_obj) #string to json if bulkProcess == True: resp_objects.append(resp_obj) else: #K.clear_session() return resp_obj #---------------------- else: raise ValueError("Invalid arguments passed to verify function: ", instance) #------------------------- toc = time.time() #print("identification lasts ",toc-tic," seconds") if bulkProcess == True: resp_obj = "{" for i in range(0, len(resp_objects)): resp_item = json.dumps(resp_objects[i]) if i > 0: resp_obj += ", " resp_obj += "\"pair_" + str(i + 1) + "\": " + resp_item resp_obj += "}" resp_obj = json.loads(resp_obj) return resp_obj
def find(img_path, db_path, model_name='VGG-Face', distance_metric='cosine', model=None, enforce_detection=True): tic = time.time() if type(img_path) == list: bulkProcess = True img_paths = img_path.copy() else: bulkProcess = False img_paths = [img_path] if os.path.isdir(db_path) == True: #--------------------------------------- if model == None: if model_name == 'VGG-Face': print("Using VGG-Face model backend and", distance_metric, "distance.") model = VGGFace.loadModel() elif model_name == 'OpenFace': print("Using OpenFace model backend", distance_metric, "distance.") model = OpenFace.loadModel() elif model_name == 'Facenet': print("Using Facenet model backend", distance_metric, "distance.") model = Facenet.loadModel() elif model_name == 'DeepFace': print("Using FB DeepFace model backend", distance_metric, "distance.") model = FbDeepFace.loadModel() else: raise ValueError("Invalid model_name passed - ", model_name) else: #model != None print("Already built model is passed") input_shape = model.layers[0].input_shape[1:3] threshold = functions.findThreshold(model_name, distance_metric) #--------------------------------------- file_name = "representations_%s.pkl" % (model_name) file_name = file_name.replace("-", "_").lower() if path.exists(db_path + "/" + file_name): print( "WARNING: Representations for images in ", db_path, " folder were previously stored in ", file_name, ". If you added new instances after this file creation, then please delete this file and call find function again. It will create it again." ) f = open(db_path + '/' + file_name, 'rb') representations = pickle.load(f) print("There are ", len(representations), " representations found in ", file_name) else: employees = [] for r, d, f in os.walk( db_path): # r=root, d=directories, f = files for file in f: if ('.jpg' in file): exact_path = r + "/" + file employees.append(exact_path) if len(employees) == 0: raise ValueError("There is no image in ", db_path, " folder!") #------------------------ #find representations for db images representations = [] pbar = tqdm(range(0, len(employees)), desc='Finding representations') #for employee in employees: for index in pbar: employee = employees[index] img = functions.detectFace(employee, input_shape, enforce_detection=enforce_detection) representation = model.predict(img)[0, :] instance = [] instance.append(employee) instance.append(representation) representations.append(instance) f = open(db_path + '/' + file_name, "wb") pickle.dump(representations, f) f.close() print( "Representations stored in ", db_path, "/", file_name, " file. Please delete this file when you add new identities in your database." ) #---------------------------- #we got representations for database df = pd.DataFrame(representations, columns=["identity", "representation"]) df_base = df.copy() resp_obj = [] global_pbar = tqdm(range(0, len(img_paths)), desc='Analyzing') for j in global_pbar: img_path = img_paths[j] #find representation for passed image img = functions.detectFace(img_path, input_shape, enforce_detection=enforce_detection) target_representation = model.predict(img)[0, :] distances = [] for index, instance in df.iterrows(): source_representation = instance["representation"] if distance_metric == 'cosine': distance = dst.findCosineDistance(source_representation, target_representation) elif distance_metric == 'euclidean': distance = dst.findEuclideanDistance( source_representation, target_representation) elif distance_metric == 'euclidean_l2': distance = dst.findEuclideanDistance( dst.l2_normalize(source_representation), dst.l2_normalize(target_representation)) else: raise ValueError("Invalid distance_metric passed - ", distance_metric) distances.append(distance) df["distance"] = distances df = df.drop(columns=["representation"]) df = df[df.distance <= threshold] df = df.sort_values(by=["distance"], ascending=True).reset_index(drop=True) resp_obj.append(df) df = df_base.copy() #restore df for the next iteration toc = time.time() print("find function lasts ", toc - tic, " seconds") if len(resp_obj) == 1: return resp_obj[0] return resp_obj else: raise ValueError("Passed db_path does not exist!") return None
def metrics_dataframe(img_df, one_compair=False): cosine_distance = [] euclidean_distance = [] l2_distance = [] distances = [] metrics = ['Cosine', 'Euclidean', 'L2'] model = list(img_df.columns) column_names = [] index_names = [] for i in model: for j in metrics: column_names.append(j + ' with ' + i) for i in img_df.index: for j in img_df.index: index_names.append(i + '-' + j) metrics_df = pd.DataFrame(columns=column_names, index=index_names) metrics_df = metrics_df.astype(object) if one_compair: people_pbar = tqdm( range(1, len(img_df.index)), desc='Avaliando a primeira pessoa em relação à todas as outras') for index in people_pbar: image_index = img_df.index[0] real_index = img_df.index[index] cosine_distance.clear() euclidean_distance.clear() l2_distance.clear() distances.clear() for model in img_df.columns: #Cosine: cosine_distance.append( dst.findCosineDistance(img_df.at[image_index, model], img_df.at[real_index, model])) #Euclidean: euclidean_distance.append( dst.findEuclideanDistance(img_df.at[image_index, model], img_df.at[real_index, model])) #L2: l2_distance.append( dst.findEuclideanDistance( dst.l2_normalize(img_df.at[image_index, model]), dst.l2_normalize(img_df.at[real_index, model]))) for i in range(0, len(img_df.columns)): distances.append(cosine_distance[i]) distances.append(euclidean_distance[i]) distances.append(l2_distance[i]) string = real_index + '-' + image_index metrics_df.loc[string] = distances else: people_pbar = tqdm( range(0, len(img_df.index)), desc='Avaliando cada pessoa em relação à todas as outras') for index in people_pbar: real_index = img_df.index[index] for jndex in people_pbar: real_jndex = img_df.index[jndex] cosine_distance.clear() euclidean_distance.clear() l2_distance.clear() distances.clear() for model in img_df.columns: #Cosine: cosine_distance.append( dst.findCosineDistance(img_df.at[real_index, model], img_df.at[real_jndex, model])) #Euclidean: euclidean_distance.append( dst.findEuclideanDistance(img_df.at[real_index, model], img_df.at[real_jndex, model])) #L2: l2_distance.append( dst.findEuclideanDistance( dst.l2_normalize(img_df.at[real_index, model]), dst.l2_normalize(img_df.at[real_jndex, model]))) for i in range(0, len(img_df.columns)): distances.append(cosine_distance[i]) distances.append(euclidean_distance[i]) distances.append(l2_distance[i]) string = real_index + '-' + real_jndex metrics_df.loc[string] = distances metrics_df.dropna(inplace=True) return metrics_df