Created
April 6, 2025 13:46
-
-
Save 0187773933/a6f3e170be0c5151965d3abb4a66ad61 to your computer and use it in GitHub Desktop.
DeepFace - Retinaface - DeepID
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import cv2 | |
import json | |
import time | |
import pickle | |
from deepface import DeepFace | |
from deepface.modules import verification | |
# https://github.com/serengil/retinaface | |
# https://sefiks.com/2020/06/16/face-recognition-with-deepid-in-keras/ | |
# https://sefiks.com/2020/02/23/face-alignment-for-face-recognition-in-python-within-opencv/ | |
# https://en.wikipedia.org/wiki/Cosine_similarity | |
# https://en.wikipedia.org/wiki/Euclidean_distance | |
# something we forgot about , | |
# if there are more than one faces found in the search , | |
# then don't just take threshold cutoff , we need the lowest one in the whole set | |
# because they obviously can't appear more than once , and should be the lowest in the group | |
# add a thing that takes in multiple test inputs ? and uses same threshold | |
# like age 3 , 5 , 7 , 10 , 12 , 15 , 20 , etc | |
# so then we match at each age group ? | |
def write_pickle( file_path , python_object ): | |
with open( file_path , 'wb') as f: | |
pickle.dump( python_object , f , protocol=pickle.HIGHEST_PROTOCOL ) | |
def read_pickle( file_path ): | |
with open( file_path , 'rb' ) as f: | |
return pickle.load( f ) | |
def write_json( file_path , python_object ): | |
with open( file_path , 'w' , encoding='utf-8' ) as f: | |
json.dump( python_object , f , ensure_ascii=False , indent=4 ) | |
def extract_faces( file_path ): | |
faces = DeepFace.extract_faces( | |
img_path=image_path , | |
detector_backend="retinaface" , # 'retinaface', 'mtcnn', 'ssd', 'dlib', 'mediapipe', 'yolov8', 'yolov11n', 'yolov11s', 'yolov11m', 'centerface' | |
enforce_detection=False , | |
align=True , | |
normalize_face=False , # We'll handle normalization inside represent() | |
# expand_percentage=0 , | |
# color_face='rgb' , # optional | |
# grayscale=False , # optional | |
# anti_spoofing=False , # optional | |
) | |
return faces | |
def get_ebedding( cropped_face ): | |
representation = DeepFace.represent( | |
img_path=cropped_face , | |
model_name="DeepID" , # "VGG-Face", "Facenet", "Facenet512", "OpenFace", "DeepFace", "DeepID", "ArcFace", "Dlib", "SFace", "GhostFaceNet" | |
detector_backend="skip" , # NO detection; face is already cropped | |
enforce_detection=False , | |
align=False , # we already aligned | |
normalization="ArcFace" , | |
# anti_spoofing=False , | |
) | |
if len( representation ) != 1: | |
return [] | |
embedding = representation[ 0 ][ "embedding" ] | |
return embedding | |
def get_test_ebedding( file_path ): | |
representation = DeepFace.represent( | |
img_path=file_path , | |
model_name="DeepID" , # "VGG-Face", "Facenet", "Facenet512", "OpenFace", "DeepFace", "DeepID", "ArcFace", "Dlib", "SFace", "GhostFaceNet" | |
detector_backend="retinaface" , # NO detection; face is already cropped | |
enforce_detection=True , | |
align=True , | |
normalization="ArcFace" , | |
# anti_spoofing=False , | |
) | |
if len( representation ) != 1: | |
return [] | |
embedding = representation[ 0 ][ "embedding" ] | |
return embedding | |
def get_embedding_distance( alpha , beta ): | |
distance = verification.find_distance( alpha , beta , "cosine" ) | |
return distance | |
SHOW_IMAGES = True | |
# image_path = "/Users/morpheous/WORKSPACE/PYTHON/FaceSorter/image-tests/Winner-2022/DSC_0031.JPG" | |
# image_path = "/Users/morpheous/WORKSPACE/PYTHON/FaceSorter/image-tests/Winner-2018/20181123_170259.jpg" | |
image_path = "/Users/morpheous/WORKSPACE/PYTHON/FaceSorter/image-tests/Winner-2019/20191130_165001.jpg" | |
test_path = "/Users/morpheous/WORKSPACE/PYTHON/FaceSorter/image-misc/1.png" | |
test_embedding = get_test_ebedding( test_path ) | |
faces = extract_faces( image_path ) | |
for i , face in enumerate( faces ): | |
landmarks = face[ "facial_area" ] | |
confidence = face[ "confidence" ] | |
embedding = get_ebedding( face[ "face" ] ) | |
cosine_distance = verification.find_distance( test_embedding , embedding , "cosine" ) | |
euclidean_distance = verification.find_distance( test_embedding , embedding , "euclidean" ) | |
euclidean_l2_distance = verification.find_distance( test_embedding , embedding , "euclidean_l2" ) | |
print( f"Face #{i}:" ) | |
print( f" Bounding box = {landmarks}" ) | |
print( f" Confidence = {confidence}" ) | |
print( f" Embedding = {len(embedding)}" ) | |
print( f" Cosine Distance = {cosine_distance}" ) | |
print( f" Euclidean Distance = {euclidean_distance}" ) | |
print( f" Euclidean L2 Distance = {euclidean_l2_distance}" ) | |
print( "" ) | |
if SHOW_IMAGES: | |
# Convert RGB -> BGR for correct OpenCV color | |
face_bgr = cv2.cvtColor( face[ "face" ] , cv2.COLOR_RGB2BGR ) | |
cv2.imshow( f"Face {i} (conf={confidence},cd={cosine_distance})" , face_bgr ) | |
if SHOW_IMAGES: | |
cv2.waitKey( 0 ) | |
cv2.destroyAllWindows() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment