issue 131 normalization

This commit is contained in:
Sefik Ilkin Serengil 2021-07-31 22:14:52 +03:00
parent b4631f1562
commit e4484ac309
2 changed files with 76 additions and 8 deletions

View File

@ -66,7 +66,7 @@ def build_model(model_name):
return model_obj[model_name]
def verify(img1_path, img2_path = '', model_name = 'VGG-Face', distance_metric = 'cosine', model = None, enforce_detection = True, detector_backend = 'opencv', align = True, prog_bar = True):
def verify(img1_path, img2_path = '', model_name = 'VGG-Face', distance_metric = 'cosine', model = None, enforce_detection = True, detector_backend = 'opencv', align = True, prog_bar = True, normalization = 'base'):
"""
This function verifies an image pair is same person or different persons.
@ -161,12 +161,16 @@ def verify(img1_path, img2_path = '', model_name = 'VGG-Face', distance_metric =
img1_representation = represent(img_path = img1_path
, model_name = model_name, model = custom_model
, enforce_detection = enforce_detection, detector_backend = detector_backend
, align = align)
, align = align
, normalization = normalization
)
img2_representation = represent(img_path = img2_path
, model_name = model_name, model = custom_model
, enforce_detection = enforce_detection, detector_backend = detector_backend
, align = align)
, align = align
, normalization = normalization
)
#----------------------
#find distances between embeddings
@ -458,7 +462,7 @@ def analyze(img_path, actions = ['emotion', 'age', 'gender', 'race'] , models =
return resp_obj
def find(img_path, db_path, model_name ='VGG-Face', distance_metric = 'cosine', model = None, enforce_detection = True, detector_backend = 'opencv', align = True, prog_bar = True):
def find(img_path, db_path, model_name ='VGG-Face', distance_metric = 'cosine', model = None, enforce_detection = True, detector_backend = 'opencv', align = True, prog_bar = True, normalization = 'base'):
"""
This function applies verification several times and find an identity in a database
@ -571,7 +575,9 @@ def find(img_path, db_path, model_name ='VGG-Face', distance_metric = 'cosine',
representation = represent(img_path = employee
, model_name = model_name, model = custom_model
, enforce_detection = enforce_detection, detector_backend = detector_backend
, align = align)
, align = align
, normalization = normalization
)
instance.append(representation)
@ -613,7 +619,9 @@ def find(img_path, db_path, model_name ='VGG-Face', distance_metric = 'cosine',
target_representation = represent(img_path = img_path
, model_name = model_name, model = custom_model
, enforce_detection = enforce_detection, detector_backend = detector_backend
, align = align)
, align = align
, normalization = normalization
)
for k in metric_names:
distances = []
@ -704,7 +712,7 @@ def find(img_path, db_path, model_name ='VGG-Face', distance_metric = 'cosine',
return None
def represent(img_path, model_name = 'VGG-Face', model = None, enforce_detection = True, detector_backend = 'opencv', align = True):
def represent(img_path, model_name = 'VGG-Face', model = None, enforce_detection = True, detector_backend = 'opencv', align = True, normalization = 'base'):
"""
This function represents facial images as vectors.
@ -722,6 +730,8 @@ def represent(img_path, model_name = 'VGG-Face', model = None, enforce_detection
detector_backend (string): set face detector backend as retinaface, mtcnn, opencv, ssd or dlib
normalization (string): normalize the input image before feeding to model
Returns:
Represent function returns a multidimensional vector. The number of dimensions is changing based on the reference model. E.g. FaceNet returns 128 dimensional vector; VGG-Face returns 2622 dimensional vector.
"""
@ -741,6 +751,13 @@ def represent(img_path, model_name = 'VGG-Face', model = None, enforce_detection
, detector_backend = detector_backend
, align = align)
#---------------------------------
#custom normalization
img = functions.normalize_input(img = img, normalization = normalization)
#---------------------------------
#represent
embedding = model.predict(img)[0].tolist()

View File

@ -104,6 +104,57 @@ def detect_face(img, detector_backend = 'opencv', grayscale = False, enforce_det
else:
raise ValueError("Face could not be detected. Please confirm that the picture is a face photo or consider to set enforce_detection param to False.")
def normalize_input(img, normalization = 'base'):
#issue 131 declares that some normalization techniques improves the accuracy
if normalization == 'base':
return img
else: #@trevorgribble recommend the following idea
img *= 255 #restore input in scale of [0, 255] because it was normalized in scale of [0, 1] in preprocess_face
if normalization == 'Facenet':
mean, std = img.mean(), img.std()
img = (img - mean) / std
elif normalization == 'v1':
#BGR mean subtraction / 255 normalization
img[..., 0]-= 131.0912
img[..., 1] -= 103.8827
img[..., 2] -= 91.4953
img = img[..., ::-1]
img /= 255
elif(normalization =="v2"):
#RGB mean subtraction / 255 normalization
img[..., 0]-= 131.0912
img[..., 1] -= 103.8827
img[..., 2] -= 91.4953
img /= 255
elif(normalization =="v3"):
#BGR mean subtraction normalization
img[..., 0]-= 131.0912
img[..., 1] -= 103.8827
img[..., 2] -= 91.4953
img = img[..., ::-1]
elif(normalization =="v4"):
#RGB mean subtraction normalization
img[..., 0]-= 131.0912
img[..., 1] -= 103.8827
img[..., 2] -= 91.4953
elif(normalization=="v6"):
# simply / 127.5 - 1 (similar to facenet 2018 model preprocessing step as @iamrishab posted)
img /= 127.5
img -= 1
#-----------------------------
return img
def preprocess_face(img, target_size=(224, 224), grayscale = False, enforce_detection = True, detector_backend = 'opencv', return_region = False, align = True):
#img might be path, base64 or numpy array. Convert it to numpy whatever it is.
@ -155,7 +206,7 @@ def preprocess_face(img, target_size=(224, 224), grayscale = False, enforce_dete
#normalizing the image pixels
img_pixels = image.img_to_array(img)
img_pixels = image.img_to_array(img) #what this line doing? must?
img_pixels = np.expand_dims(img_pixels, axis = 0)
img_pixels /= 255 #normalize input in [0, 1]