diff --git a/deepface/DeepFace.py b/deepface/DeepFace.py index 3eaa057..067a1b5 100644 --- a/deepface/DeepFace.py +++ b/deepface/DeepFace.py @@ -15,7 +15,7 @@ import tensorflow as tf import pickle from deepface import DeepFace -from deepface.basemodels import VGGFace, OpenFace, Facenet, FbDeepFace +from deepface.basemodels import VGGFace, OpenFace, Facenet, FbDeepFace, DeepID from deepface.extendedmodels import Age, Gender, Race, Emotion from deepface.commons import functions, realtime, distance as dst @@ -195,6 +195,10 @@ def verify(img1_path, img2_path='' elif model_name == 'DeepFace': print("Using FB DeepFace model backend", distance_metric,"distance.") model = FbDeepFace.loadModel() + + if model_name == 'DeepID': + print("Using DeepID2 model backend", distance_metric,"distance.") + model = DeepID.loadModel() else: raise ValueError("Invalid model_name passed - ", model_name) @@ -204,6 +208,9 @@ def verify(img1_path, img2_path='' #------------------------------ #face recognition models have different size of inputs input_shape = model.layers[0].input_shape[1:3] + + input_shape_x = input_shape[0] + input_shape_y = input_shape[1] #------------------------------ @@ -225,8 +232,8 @@ def verify(img1_path, img2_path='' #---------------------- #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) + 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 @@ -499,9 +506,13 @@ def find(img_path, db_path 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 @@ -585,7 +596,9 @@ def find(img_path, db_path if model_name != 'Ensemble': input_shape = model.layers[0].input_shape[1:3] - img = functions.detectFace(employee, input_shape, enforce_detection = enforce_detection) + 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 = [] @@ -600,7 +613,9 @@ def find(img_path, db_path for j in model_names: model = models[j] input_shape = model.layers[0].input_shape[1:3] - img = functions.detectFace(employee, input_shape, enforce_detection = enforce_detection) + 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) @@ -705,7 +720,9 @@ def find(img_path, db_path if model_name != 'Ensemble': input_shape = model.layers[0].input_shape[1:3] - img = functions.detectFace(img_path, input_shape, enforce_detection = enforce_detection) + 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 = [] diff --git a/deepface/basemodels/DeepID.py b/deepface/basemodels/DeepID.py new file mode 100644 index 0000000..c31bb0e --- /dev/null +++ b/deepface/basemodels/DeepID.py @@ -0,0 +1,52 @@ +import os +from pathlib import Path +import gdown +import keras +from keras.models import Model +from keras.layers import Conv2D, Activation, Input, Add, MaxPooling2D, Flatten, Dense, Dropout +import zipfile + +#------------------------------------- + +def loadModel(): + + myInput = Input(shape=(55, 47, 3)) + + x = Conv2D(20, (4, 4), name='Conv1', activation='relu', input_shape=(55, 47, 3))(myInput) + x = MaxPooling2D(pool_size=2, strides=2, name='Pool1')(x) + x = Dropout(rate=1, name='D1')(x) + + x = Conv2D(40, (3, 3), name='Conv2', activation='relu')(x) + x = MaxPooling2D(pool_size=2, strides=2, name='Pool2')(x) + x = Dropout(rate=1, name='D2')(x) + + x = Conv2D(60, (3, 3), name='Conv3', activation='relu')(x) + x = MaxPooling2D(pool_size=2, strides=2, name='Pool3')(x) + x = Dropout(rate=1, name='D3')(x) + + x1 = Flatten()(x) + fc11 = Dense(160, name = 'fc11')(x1) + + x2 = Conv2D(80, (2, 2), name='Conv4', activation='relu')(x) + x2 = Flatten()(x2) + fc12 = Dense(160, name = 'fc12')(x2) + + y = Add()([fc11, fc12]) + y = Activation('relu', name = 'deepid')(y) + + model = Model(inputs=[myInput], outputs=y) + + #--------------------------------- + + home = str(Path.home()) + + if os.path.isfile(home+'/.deepface/weights/deepid_keras_weights.h5') != True: + print("deepid_keras_weights.h5 will be downloaded...") + + url = 'https://drive.google.com/uc?id=1uRLtBCTQQAvHJ_KVrdbRJiCKxU8m5q2J' + output = home+'/.deepface/weights/deepid_keras_weights.h5' + gdown.download(url, output, quiet=False) + + model.load_weights(home+'/.deepface/weights/deepid_keras_weights.h5') + + return model \ No newline at end of file diff --git a/deepface/commons/functions.py b/deepface/commons/functions.py index e006e0e..286af4c 100644 --- a/deepface/commons/functions.py +++ b/deepface/commons/functions.py @@ -129,6 +129,14 @@ def findThreshold(model_name, distance_metric): elif distance_metric == 'euclidean_l2': threshold = 0.64 + elif model_name == 'DeepID': + if distance_metric == 'cosine': + threshold = 0.015 + elif distance_metric == 'euclidean': + threshold = 45 + elif distance_metric == 'euclidean_l2': + threshold = 0.17 + return threshold def get_opencv_path(): diff --git a/tests/unit_tests.py b/tests/unit_tests.py index d8718b7..0eacdf8 100644 --- a/tests/unit_tests.py +++ b/tests/unit_tests.py @@ -105,7 +105,8 @@ dataset = [ ['dataset/img6.jpg', 'dataset/img9.jpg', False], ] -models = ['VGG-Face', 'Facenet', 'OpenFace', 'DeepFace'] +models = ['DeepID'] +#models = ['VGG-Face', 'Facenet', 'OpenFace', 'DeepFace', 'DeepID'] metrics = ['cosine', 'euclidean', 'euclidean_l2'] passed_tests = 0; test_cases = 0 @@ -178,3 +179,4 @@ facial_attribute_models["gender"] = gender_model facial_attribute_models["race"] = race_model resp_obj = DeepFace.analyze("dataset/img1.jpg", models=facial_attribute_models) +