mirror of
https://github.com/serengil/deepface.git
synced 2025-06-07 20:15:21 +00:00
clean codes
This commit is contained in:
parent
1f41ceb793
commit
3907515a0d
13
README.md
13
README.md
@ -175,12 +175,6 @@ models["race"] = DeepFace.build_model('Race')
|
|||||||
DeepFace.analyze("img1.jpg", models=models)
|
DeepFace.analyze("img1.jpg", models=models)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Disclaimer
|
|
||||||
|
|
||||||
Reference face recognition models have different type of licenses. This framework is just a wrapper for those models. That's why, licence types are inherited as well. You should check the licenses for the face recognition models before use.
|
|
||||||
|
|
||||||
Herein, [OpenFace](https://github.com/cmusatyalab/openface/blob/master/LICENSE) is licensed under Apache License 2.0. [FB DeepFace](https://github.com/swghosh/DeepFace) and [Facenet](https://github.com/davidsandberg/facenet/blob/master/LICENSE.md) is licensed under MIT License. [Dlib](https://github.com/davisking/dlib/blob/master/dlib/LICENSE.txt) is licensed under Boost Software License. They all allow you to use for personal and commercial purpose free. On the other hand, [VGG-Face](http://www.robots.ox.ac.uk/~vgg/software/vgg_face/) is licensed under Creative Commons Attribution License. That's why, it is restricted to adopt VGG-Face for commercial use.
|
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
There are many ways to support a project - starring⭐️ the GitHub repos is just one.
|
There are many ways to support a project - starring⭐️ the GitHub repos is just one.
|
||||||
@ -189,11 +183,12 @@ There are many ways to support a project - starring⭐️ the GitHub repos is ju
|
|||||||
|
|
||||||
Please cite [deepface](https://ieeexplore.ieee.org/document/9259802) in your publications if it helps your research. Here is an example BibTeX entry:
|
Please cite [deepface](https://ieeexplore.ieee.org/document/9259802) in your publications if it helps your research. Here is an example BibTeX entry:
|
||||||
|
|
||||||
```
|
```BibTeX
|
||||||
@inproceedings{9259802,
|
@inproceedings{serengil2020lightface,
|
||||||
title={LightFace: A Hybrid Deep Face Recognition Framework},
|
title={LightFace: A Hybrid Deep Face Recognition Framework},
|
||||||
author={Serengil, Sefik Ilkin and Ozpinar, Alper},
|
author={Serengil, Sefik Ilkin and Ozpinar, Alper},
|
||||||
booktitle={2020 Innovations in Intelligent Systems and Applications Conference (ASYU)},
|
booktitle={2020 Innovations in Intelligent Systems and Applications Conference (ASYU)},
|
||||||
|
pages={23--27},
|
||||||
year={2020},
|
year={2020},
|
||||||
doi={10.1109/ASYU50717.2020.9259802},
|
doi={10.1109/ASYU50717.2020.9259802},
|
||||||
organization={IEEE}
|
organization={IEEE}
|
||||||
@ -202,6 +197,6 @@ Please cite [deepface](https://ieeexplore.ieee.org/document/9259802) in your pub
|
|||||||
|
|
||||||
## Licence
|
## Licence
|
||||||
|
|
||||||
Deepface is licensed under the MIT License - see [`LICENSE`](https://github.com/serengil/deepface/blob/master/LICENSE) for more details.
|
Deepface is licensed under the MIT License - see [`LICENSE`](https://github.com/serengil/deepface/blob/master/LICENSE) for more details. However, the library wraps some face recognition models: [VGG-Face](http://www.robots.ox.ac.uk/~vgg/software/vgg_face/), [Facenet](https://github.com/davidsandberg/facenet/blob/master/LICENSE.md), [OpenFace](https://github.com/cmusatyalab/openface/blob/master/LICENSE), [DeepFace](https://github.com/swghosh/DeepFace) and [Dlib](https://github.com/davisking/dlib/blob/master/dlib/LICENSE.txt). Licence types will be inherited if you are going to use those models.
|
||||||
|
|
||||||
[Logo](https://thenounproject.com/term/face-recognition/2965879/) is created by [Adrien Coquet](https://thenounproject.com/coquet_adrien/). Licensed under [Creative Commons: By Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/).
|
[Logo](https://thenounproject.com/term/face-recognition/2965879/) is created by [Adrien Coquet](https://thenounproject.com/coquet_adrien/). Licensed under [Creative Commons: By Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/).
|
||||||
|
@ -58,7 +58,6 @@ def verify(img1_path, img2_path = '', model_name = 'VGG-Face', distance_metric =
|
|||||||
metrics.append(distance_metric)
|
metrics.append(distance_metric)
|
||||||
|
|
||||||
#--------------------------------
|
#--------------------------------
|
||||||
#ensemble learning disabled
|
|
||||||
|
|
||||||
if model == None:
|
if model == None:
|
||||||
if model_name == 'Ensemble':
|
if model_name == 'Ensemble':
|
||||||
@ -135,7 +134,7 @@ def verify(img1_path, img2_path = '', model_name = 'VGG-Face', distance_metric =
|
|||||||
|
|
||||||
if model_name != 'Ensemble':
|
if model_name != 'Ensemble':
|
||||||
|
|
||||||
threshold = functions.findThreshold(i, j)
|
threshold = dst.findThreshold(i, j)
|
||||||
|
|
||||||
if distance <= threshold:
|
if distance <= threshold:
|
||||||
identified = True
|
identified = True
|
||||||
@ -197,8 +196,6 @@ def verify(img1_path, img2_path = '', model_name = 'VGG-Face', distance_metric =
|
|||||||
|
|
||||||
toc = time.time()
|
toc = time.time()
|
||||||
|
|
||||||
#print("identification lasts ",toc-tic," seconds")
|
|
||||||
|
|
||||||
if bulkProcess == True:
|
if bulkProcess == True:
|
||||||
|
|
||||||
resp_obj = {}
|
resp_obj = {}
|
||||||
@ -520,7 +517,7 @@ def find(img_path, db_path, model_name ='VGG-Face', distance_metric = 'cosine',
|
|||||||
df["%s_%s" % (j, k)] = distances
|
df["%s_%s" % (j, k)] = distances
|
||||||
|
|
||||||
if model_name != 'Ensemble':
|
if model_name != 'Ensemble':
|
||||||
threshold = functions.findThreshold(j, k)
|
threshold = dst.findThreshold(j, k)
|
||||||
df = df.drop(columns = ["%s_representation" % (j)])
|
df = df.drop(columns = ["%s_representation" % (j)])
|
||||||
df = df[df["%s_%s" % (j, k)] <= threshold]
|
df = df[df["%s_%s" % (j, k)] <= threshold]
|
||||||
|
|
||||||
|
@ -9,24 +9,19 @@ import lightgbm as lgb #lightgbm==2.3.1
|
|||||||
from deepface.commons import functions, distance as dst
|
from deepface.commons import functions, distance as dst
|
||||||
|
|
||||||
def loadModel():
|
def loadModel():
|
||||||
|
|
||||||
|
model_names = ['VGG-Face', 'Facenet', 'OpenFace', 'DeepFace']
|
||||||
|
|
||||||
model = {}
|
model = {}
|
||||||
|
|
||||||
model_pbar = tqdm(range(0, 4), desc='Face recognition models')
|
model_pbar = tqdm(range(0, 4), desc='Face recognition models')
|
||||||
|
|
||||||
for index in model_pbar:
|
for index in model_pbar:
|
||||||
|
|
||||||
if index == 0:
|
model_name = model_names[index]
|
||||||
model_pbar.set_description("Loading VGG-Face")
|
|
||||||
model["VGG-Face"] = DeepFace.build_model('VGG-Face')
|
model_pbar.set_description("Loading %s" % (model_name))
|
||||||
elif index == 1:
|
model[model_name] = DeepFace.build_model(model_name)
|
||||||
model_pbar.set_description("Loading Google FaceNet")
|
|
||||||
model["Facenet"] = DeepFace.build_model('Facenet')
|
|
||||||
elif index == 2:
|
|
||||||
model_pbar.set_description("Loading OpenFace")
|
|
||||||
model["OpenFace"] = DeepFace.build_model('OpenFace')
|
|
||||||
elif index == 3:
|
|
||||||
model_pbar.set_description("Loading Facebook DeepFace")
|
|
||||||
model["DeepFace"] = DeepFace.build_model('DeepFace')
|
|
||||||
|
|
||||||
return model
|
return model
|
||||||
|
|
||||||
@ -37,7 +32,8 @@ def validate_model(model):
|
|||||||
found_models.append(key)
|
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):
|
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")
|
#print("Ensemble learning will be applied for ", found_models," models")
|
||||||
|
valid = True
|
||||||
else:
|
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)
|
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)
|
||||||
|
|
||||||
|
@ -14,3 +14,20 @@ def findEuclideanDistance(source_representation, test_representation):
|
|||||||
|
|
||||||
def l2_normalize(x):
|
def l2_normalize(x):
|
||||||
return x / np.sqrt(np.sum(np.multiply(x, x)))
|
return x / np.sqrt(np.sum(np.multiply(x, x)))
|
||||||
|
|
||||||
|
def findThreshold(model_name, distance_metric):
|
||||||
|
|
||||||
|
base_threshold = {'cosine': 0.40, 'euclidean': 0.55, 'euclidean_l2': 0.75}
|
||||||
|
|
||||||
|
thresholds = {
|
||||||
|
'VGG-Face': {'cosine': 0.40, 'euclidean': 0.55, 'euclidean_l2': 0.75},
|
||||||
|
'OpenFace': {'cosine': 0.10, 'euclidean': 0.55, 'euclidean_l2': 0.55},
|
||||||
|
'Facenet': {'cosine': 0.40, 'euclidean': 10, 'euclidean_l2': 0.80},
|
||||||
|
'DeepFace': {'cosine': 0.23, 'euclidean': 64, 'euclidean_l2': 0.64},
|
||||||
|
'DeepID': {'cosine': 0.015, 'euclidean': 45, 'euclidean_l2': 0.17},
|
||||||
|
'Dlib': {'cosine': 0.07, 'euclidean': 0.6, 'euclidean_l2': 0.6}
|
||||||
|
}
|
||||||
|
|
||||||
|
threshold = thresholds.get(model_name, base_threshold).get(distance_metric, 0.4)
|
||||||
|
|
||||||
|
return threshold
|
@ -98,12 +98,6 @@ def initialize_detector(detector_backend):
|
|||||||
elif detector_backend == 'mtcnn':
|
elif detector_backend == 'mtcnn':
|
||||||
face_detector = MTCNN()
|
face_detector = MTCNN()
|
||||||
|
|
||||||
def loadBase64Img(uri):
|
|
||||||
encoded_data = uri.split(',')[1]
|
|
||||||
nparr = np.fromstring(base64.b64decode(encoded_data), np.uint8)
|
|
||||||
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
|
|
||||||
return img
|
|
||||||
|
|
||||||
def initializeFolder():
|
def initializeFolder():
|
||||||
|
|
||||||
home = str(Path.home())
|
home = str(Path.home())
|
||||||
@ -116,22 +110,11 @@ def initializeFolder():
|
|||||||
os.mkdir(home+"/.deepface/weights")
|
os.mkdir(home+"/.deepface/weights")
|
||||||
print("Directory ",home,"/.deepface/weights created")
|
print("Directory ",home,"/.deepface/weights created")
|
||||||
|
|
||||||
def findThreshold(model_name, distance_metric):
|
def loadBase64Img(uri):
|
||||||
|
encoded_data = uri.split(',')[1]
|
||||||
base_threshold = {'cosine': 0.40, 'euclidean': 0.55, 'euclidean_l2': 0.75}
|
nparr = np.fromstring(base64.b64decode(encoded_data), np.uint8)
|
||||||
|
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
|
||||||
thresholds = {
|
return img
|
||||||
'VGG-Face': {'cosine': 0.40, 'euclidean': 0.55, 'euclidean_l2': 0.75},
|
|
||||||
'OpenFace': {'cosine': 0.10, 'euclidean': 0.55, 'euclidean_l2': 0.55},
|
|
||||||
'Facenet': {'cosine': 0.40, 'euclidean': 10, 'euclidean_l2': 0.80},
|
|
||||||
'DeepFace': {'cosine': 0.23, 'euclidean': 64, 'euclidean_l2': 0.64},
|
|
||||||
'DeepID': {'cosine': 0.015, 'euclidean': 45, 'euclidean_l2': 0.17},
|
|
||||||
'Dlib': {'cosine': 0.07, 'euclidean': 0.6, 'euclidean_l2': 0.6}
|
|
||||||
}
|
|
||||||
|
|
||||||
threshold = thresholds.get(model_name, base_threshold).get(distance_metric, 0.4)
|
|
||||||
|
|
||||||
return threshold
|
|
||||||
|
|
||||||
def get_opencv_path():
|
def get_opencv_path():
|
||||||
opencv_home = cv2.__file__
|
opencv_home = cv2.__file__
|
||||||
|
@ -76,7 +76,7 @@ def analysis(db_path, model_name, distance_metric, enable_face_analysis = True):
|
|||||||
input_shape_y = input_shape[1]
|
input_shape_y = input_shape[1]
|
||||||
|
|
||||||
#tuned thresholds for model and metric pair
|
#tuned thresholds for model and metric pair
|
||||||
threshold = functions.findThreshold(model_name, distance_metric)
|
threshold = dst.findThreshold(model_name, distance_metric)
|
||||||
|
|
||||||
#------------------------
|
#------------------------
|
||||||
#facial attribute analysis models
|
#facial attribute analysis models
|
||||||
|
@ -177,13 +177,15 @@ for model in models:
|
|||||||
|
|
||||||
print("Passed unit tests: ",passed_tests," / ",test_cases)
|
print("Passed unit tests: ",passed_tests," / ",test_cases)
|
||||||
|
|
||||||
|
threshold = 70
|
||||||
|
|
||||||
accuracy = 100 * passed_tests / test_cases
|
accuracy = 100 * passed_tests / test_cases
|
||||||
accuracy = round(accuracy, 2)
|
accuracy = round(accuracy, 2)
|
||||||
|
|
||||||
if accuracy > 75:
|
if accuracy >= threshold:
|
||||||
print("Unit tests are completed successfully. Score: ",accuracy,"%")
|
print("Unit tests are completed successfully. Score: ",accuracy,"%")
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unit test score does not satisfy the minimum required accuracy. Minimum expected score is 80% but this got ",accuracy,"%")
|
raise ValueError("Unit test score does not satisfy the minimum required accuracy. Minimum expected score is ",threshold,"% but this got ",accuracy,"%")
|
||||||
|
|
||||||
#-----------------------------------
|
#-----------------------------------
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user