retinaface added

This commit is contained in:
Sefik Ilkin Serengil 2021-04-26 21:37:01 +03:00
parent 577408ad69
commit 974f8bf27b
7 changed files with 223 additions and 201 deletions

View File

@ -30,7 +30,6 @@ Verification function under the deepface interface offers to verify face pairs a
```python
from deepface import DeepFace
result = DeepFace.verify("img1.jpg", "img2.jpg")
#results = DeepFace.verify([['img1.jpg', 'img2.jpg'], ['img1.jpg', 'img3.jpg']])
print("Is verified: ", result["verified"])
```
@ -46,7 +45,6 @@ Face recognition requires to apply face verification several times. Herein, deep
from deepface import DeepFace
import pandas as pd
df = DeepFace.find(img_path = "img1.jpg", db_path = "C:/workspace/my_db")
#dfs = DeepFace.find(img_path = ["img1.jpg", "img2.jpg"], db_path = "C:/workspace/my_db")
```
<p align="center"><img src="https://raw.githubusercontent.com/serengil/deepface/master/icon/stock-6-v2.jpg" width="95%" height="95%"></p>
@ -110,7 +108,6 @@ Deepface also offers facial attribute analysis including [`age`](https://sefiks.
```python
from deepface import DeepFace
obj = DeepFace.analyze(img_path = "img4.jpg", actions = ['age', 'gender', 'race', 'emotion'])
#objs = DeepFace.analyze(["img1.jpg", "img2.jpg", "img3.jpg"]) #analyzing multiple faces same time
print(obj["age"]," years old ",obj["dominant_race"]," ",obj["dominant_emotion"]," ", obj["gender"])
```
@ -170,10 +167,10 @@ The both face recognition and facial attribute analysis are covered in the API.
**Face Detectors** - [`Demo`](https://youtu.be/GZ2p2hj2H5k)
Face detection and alignment are early stages of a modern face recognition pipeline. [`OpenCV`](https://sefiks.com/2020/02/23/face-alignment-for-face-recognition-in-python-within-opencv/), [`SSD`](https://sefiks.com/2020/08/25/deep-face-detection-with-opencv-in-python/), [`Dlib`](https://sefiks.com/2020/07/11/face-recognition-with-dlib-in-python/) and [`MTCNN`](https://sefiks.com/2020/09/09/deep-face-detection-with-mtcnn-in-python/) methods are wrapped in deepface as a detector. You can optionally pass a custom detector to functions in deepface interface. MTCNN is the default detector if you won't pass any detector.
Face detection and alignment are early stages of a modern face recognition pipeline. [`OpenCV`](https://sefiks.com/2020/02/23/face-alignment-for-face-recognition-in-python-within-opencv/), [`SSD`](https://sefiks.com/2020/08/25/deep-face-detection-with-opencv-in-python/), [`Dlib`](https://sefiks.com/2020/07/11/face-recognition-with-dlib-in-python/), [`MTCNN`](https://sefiks.com/2020/09/09/deep-face-detection-with-mtcnn-in-python/) and [`RetinaFace`](https://github.com/serengil/retinaface) methods are wrapped in deepface as a facial detector. You can optionally pass a custom detector to functions in deepface interface. MTCNN is the default detector if you won't pass any detector.
```python
backends = ['opencv', 'ssd', 'dlib', 'mtcnn']
backends = ['opencv', 'ssd', 'dlib', 'mtcnn', 'retinaface']
for backend in backends:
#face detection and alignment
detected_face = DeepFace.detectFace("img.jpg", detector_backend = backend)
@ -188,27 +185,10 @@ for backend in backends:
demography = DeepFace.analyze("img4.jpg", detector_backend = backend)
```
<p align="center"><img src="https://raw.githubusercontent.com/serengil/deepface/master/icon/deepface-detectors.png" width="90%" height="90%"></p>
[MTCNN](https://sefiks.com/2020/09/09/deep-face-detection-with-mtcnn-in-python/) seems to overperform in detection and alignment stages but it is slower than [SSD](https://sefiks.com/2020/08/25/deep-face-detection-with-opencv-in-python/).
**Passing pre-built face recognition models**
You can build models once and pass to deepface functions as well. This speeds you up if you are going to call deepface several times. Consider this approach if you are going to call deepface functions in a for loop.
```python
#face recognition
models = ['VGG-Face', 'Facenet', 'OpenFace', 'DeepFace', 'DeepID', 'Dlib']
for model_name in models:
model = DeepFace.build_model(model_name)
DeepFace.verify("img1.jpg", "img2.jpg", model_name = model_name, model = model)
#facial analysis
models = {}
actions = ['Age', 'Gender', 'Emotion', 'Race']
for action in actions:
models[action.lower()] = DeepFace.build_model(action)
DeepFace.analyze("img1.jpg", models=models)
```
## FAQ and Troubleshooting
Pre-trained weights of custom models will be downloaded from Google Drive source to your environment once. Download limit of my Google Drive account might be exceeded sometimes. In this case, you might have an exception like "Too many users have viewed or downloaded this file recently. Please try accessing the file again later". You can still download the pre-trained weights from Google Drive manually. You should then download the pre-trained weights to {HOME_FOLDER}/.deepface/weights folder. It won't try to download the weight file if it exists in the weights folder. You can find out your HOME_FOLDER as shown below.
@ -219,6 +199,14 @@ home = str(Path.home())
print("HOME_FOLDER is ",home)
```
If you are going to call deepface functions in a for loop, then you should build the model once and pass to the functions. This avoids to cause a memory problem and also it will speed you up.
```python
model_name = "Facenet"
model = DeepFace.build_model(model_name)
DeepFace.verify("img1.jpg", "img2.jpg", model_name = model_name, model = model)
```
## Contribution
Pull requests are welcome. You should run the unit tests locally by running [`test/unit_tests.py`](https://github.com/serengil/deepface/blob/master/tests/unit_tests.py). Please share the unit test result logs in the PR. Deepface is currently compatible with TF 1 and 2 versions. Change requests should satisfy those requirements both.

View File

@ -7,6 +7,12 @@ def findCosineDistance(source_representation, test_representation):
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
def findEuclideanDistance(source_representation, test_representation):
if type(source_representation) == list:
source_representation = np.array(source_representation)
if type(test_representation) == list:
test_representation = np.array(test_representation)
euclidean_distance = source_representation - test_representation
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
euclidean_distance = np.sqrt(euclidean_distance)

View File

@ -135,6 +135,10 @@ def initialize_detector(detector_backend):
elif detector_backend == 'mtcnn':
face_detector = MTCNN()
elif detector_backend == 'retinaface':
from retinaface import RetinaFace
face_detector = RetinaFace.build_model()
def initializeFolder():
home = str(Path.home())
@ -313,6 +317,23 @@ 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.")
elif detector_backend == 'retinaface':
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #retinaface expects RGB but OpenCV read BGR
from retinaface import RetinaFace
faces = RetinaFace.extract_faces(img_rgb, align = True)
if len(faces) > 0:
face = faces[0]
return face, img_region
else: #if no face detected
if not enforce_detection:
return img, img_region
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.")
else:
detectors = ['opencv', 'ssd', 'dlib', 'mtcnn']
raise ValueError("Valid backends are ", detectors," but you passed ", detector_backend)
@ -437,6 +458,9 @@ def align_face(img, detector_backend = 'opencv'):
img = alignment_procedure(img, left_eye, right_eye)
return img #return img anyway
elif detector_backend == 'retinaface':
#we used extract_faces function of retinaface. it applies alignment anyway.
return img #return img anyway
def preprocess_face(img, target_size=(224, 224), grayscale = False, enforce_detection = True, detector_backend = 'opencv', return_region = False):
@ -491,4 +515,3 @@ def find_input_shape(model):
input_shape = tuple(input_shape)
return input_shape

BIN
icon/deepface-detectors.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

@ -11,3 +11,4 @@ Flask>=1.1.2
mtcnn>=0.1.0
lightgbm>=2.3.1
dlib>=19.20.0
retina-face>=0.0.1

View File

@ -20,5 +20,5 @@ setuptools.setup(
"Operating System :: OS Independent"
],
python_requires='>=3.5.5',
install_requires=["numpy>=1.14.0", "pandas>=0.23.4", "tqdm>=4.30.0", "gdown>=3.10.1", "Pillow>=5.2.0", "opencv-python>=3.4.4", "tensorflow>=1.9.0", "keras>=2.2.0", "Flask>=1.1.2", "mtcnn>=0.1.0"]
install_requires=["numpy>=1.14.0", "pandas>=0.23.4", "tqdm>=4.30.0", "gdown>=3.10.1", "Pillow>=5.2.0", "opencv-python>=3.4.4", "tensorflow>=1.9.0", "keras>=2.2.0", "Flask>=1.1.2", "mtcnn>=0.1.0", "retina-face>=0.0.1"]
)

View File

@ -47,6 +47,10 @@ print("-----------------------------------------")
print("Face detectors test")
print("retinaface detector")
res = DeepFace.verify(dataset, detector_backend = 'retinaface')
print(res)
print("ssd detector")
res = DeepFace.verify(dataset, detector_backend = 'ssd')
print(res)