mirror of
https://github.com/serengil/deepface.git
synced 2025-06-07 12:05:22 +00:00
retinaface added
This commit is contained in:
parent
577408ad69
commit
974f8bf27b
36
README.md
36
README.md
@ -30,7 +30,6 @@ Verification function under the deepface interface offers to verify face pairs a
|
|||||||
```python
|
```python
|
||||||
from deepface import DeepFace
|
from deepface import DeepFace
|
||||||
result = DeepFace.verify("img1.jpg", "img2.jpg")
|
result = DeepFace.verify("img1.jpg", "img2.jpg")
|
||||||
#results = DeepFace.verify([['img1.jpg', 'img2.jpg'], ['img1.jpg', 'img3.jpg']])
|
|
||||||
print("Is verified: ", result["verified"])
|
print("Is verified: ", result["verified"])
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -46,7 +45,6 @@ Face recognition requires to apply face verification several times. Herein, deep
|
|||||||
from deepface import DeepFace
|
from deepface import DeepFace
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
df = DeepFace.find(img_path = "img1.jpg", db_path = "C:/workspace/my_db")
|
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>
|
<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
|
```python
|
||||||
from deepface import DeepFace
|
from deepface import DeepFace
|
||||||
obj = DeepFace.analyze(img_path = "img4.jpg", actions = ['age', 'gender', 'race', 'emotion'])
|
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"])
|
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 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
|
```python
|
||||||
backends = ['opencv', 'ssd', 'dlib', 'mtcnn']
|
backends = ['opencv', 'ssd', 'dlib', 'mtcnn', 'retinaface']
|
||||||
for backend in backends:
|
for backend in backends:
|
||||||
#face detection and alignment
|
#face detection and alignment
|
||||||
detected_face = DeepFace.detectFace("img.jpg", detector_backend = backend)
|
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)
|
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/).
|
[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
|
## 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.
|
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)
|
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
|
## 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.
|
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.
|
||||||
|
@ -7,6 +7,12 @@ def findCosineDistance(source_representation, test_representation):
|
|||||||
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
|
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
|
||||||
|
|
||||||
def findEuclideanDistance(source_representation, test_representation):
|
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 = source_representation - test_representation
|
||||||
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
|
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
|
||||||
euclidean_distance = np.sqrt(euclidean_distance)
|
euclidean_distance = np.sqrt(euclidean_distance)
|
||||||
|
@ -135,6 +135,10 @@ def initialize_detector(detector_backend):
|
|||||||
elif detector_backend == 'mtcnn':
|
elif detector_backend == 'mtcnn':
|
||||||
face_detector = MTCNN()
|
face_detector = MTCNN()
|
||||||
|
|
||||||
|
elif detector_backend == 'retinaface':
|
||||||
|
from retinaface import RetinaFace
|
||||||
|
face_detector = RetinaFace.build_model()
|
||||||
|
|
||||||
def initializeFolder():
|
def initializeFolder():
|
||||||
|
|
||||||
home = str(Path.home())
|
home = str(Path.home())
|
||||||
@ -313,6 +317,23 @@ def detect_face(img, detector_backend = 'opencv', grayscale = False, enforce_det
|
|||||||
else:
|
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.")
|
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:
|
else:
|
||||||
detectors = ['opencv', 'ssd', 'dlib', 'mtcnn']
|
detectors = ['opencv', 'ssd', 'dlib', 'mtcnn']
|
||||||
raise ValueError("Valid backends are ", detectors," but you passed ", detector_backend)
|
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)
|
img = alignment_procedure(img, left_eye, right_eye)
|
||||||
|
|
||||||
return img #return img anyway
|
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):
|
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)
|
input_shape = tuple(input_shape)
|
||||||
|
|
||||||
return input_shape
|
return input_shape
|
||||||
|
|
||||||
|
BIN
icon/deepface-detectors.png
Normal file
BIN
icon/deepface-detectors.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 MiB |
@ -11,3 +11,4 @@ Flask>=1.1.2
|
|||||||
mtcnn>=0.1.0
|
mtcnn>=0.1.0
|
||||||
lightgbm>=2.3.1
|
lightgbm>=2.3.1
|
||||||
dlib>=19.20.0
|
dlib>=19.20.0
|
||||||
|
retina-face>=0.0.1
|
2
setup.py
2
setup.py
@ -20,5 +20,5 @@ setuptools.setup(
|
|||||||
"Operating System :: OS Independent"
|
"Operating System :: OS Independent"
|
||||||
],
|
],
|
||||||
python_requires='>=3.5.5',
|
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"]
|
||||||
)
|
)
|
||||||
|
@ -47,6 +47,10 @@ print("-----------------------------------------")
|
|||||||
|
|
||||||
print("Face detectors test")
|
print("Face detectors test")
|
||||||
|
|
||||||
|
print("retinaface detector")
|
||||||
|
res = DeepFace.verify(dataset, detector_backend = 'retinaface')
|
||||||
|
print(res)
|
||||||
|
|
||||||
print("ssd detector")
|
print("ssd detector")
|
||||||
res = DeepFace.verify(dataset, detector_backend = 'ssd')
|
res = DeepFace.verify(dataset, detector_backend = 'ssd')
|
||||||
print(res)
|
print(res)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user