mirror of
https://github.com/deepfakes/faceswap.git
synced 2026-10-26 03:39:45 +08:00
* Add negative filters for face detection When detecting faces that are very similar, the face recognition can produce positive results for similar looking people. This commit allows the user to add multiple positive and negative reference images. The facedetection then calculates the distance to each reference image and tries to guess which is more likely using the k-nearest method. * Do not calculate knn if no negative images are given * Clean up outputting
61 lines
2.9 KiB
Python
61 lines
2.9 KiB
Python
# import dlib
|
|
# import numpy as np
|
|
import face_recognition
|
|
# import face_recognition_models
|
|
|
|
def avg(arr):
|
|
return sum(arr)*1.0/len(arr)
|
|
|
|
class FaceFilter():
|
|
def __init__(self, reference_file_paths, nreference_file_paths, threshold = 0.6):
|
|
images = list(map(face_recognition.load_image_file, reference_file_paths))
|
|
nimages = list(map(face_recognition.load_image_file, nreference_file_paths))
|
|
# Note: we take only first face, so the reference file should only contain one face.
|
|
self.encodings = list(map(lambda im: face_recognition.face_encodings(im)[0], images))
|
|
self.nencodings = list(map(lambda im: face_recognition.face_encodings(im)[0], nimages))
|
|
self.threshold = threshold
|
|
|
|
def check(self, detected_face):
|
|
# we could use detected landmarks, but I did not manage to do so. TODO The copy/paste below should help
|
|
encodings = face_recognition.face_encodings(detected_face.image)
|
|
if encodings is not None and len(encodings) > 0:
|
|
distances = list(face_recognition.face_distance(self.encodings, encodings[0]))
|
|
distance = avg(distances)
|
|
mindistance = min(distances)
|
|
maxdistance = max(distances)
|
|
if distance > self.threshold:
|
|
print("Distance above threshold: %f < %f" % (distance, self.threshold))
|
|
return False
|
|
if len(self.nencodings) > 0:
|
|
ndistances = list(face_recognition.face_distance(self.nencodings, encodings[0]))
|
|
ndistance = avg(ndistances)
|
|
nmindistance = min(ndistances)
|
|
nmaxdistance = max(ndistances)
|
|
if (mindistance > nmindistance):
|
|
print("Distance to negative sample is smaller")
|
|
return False
|
|
if (distance > ndistance):
|
|
print("Average distance to negative sample is smaller")
|
|
return False
|
|
# k-nn classifier
|
|
K=min(5, min(len(distances), len(ndistances)) + 1)
|
|
N=sum(list(map(lambda x: x[0],
|
|
list(sorted([(1,d) for d in distances] + [(0,d) for d in ndistances],
|
|
key=lambda x: x[1]))[:K])))
|
|
ratio = N/K
|
|
if (ratio < 0.5):
|
|
print("K-nn is %.2f" % ratio)
|
|
return False
|
|
return True
|
|
else:
|
|
print("No face encodings found")
|
|
return False
|
|
|
|
# # Copy/Paste (mostly) from private method in face_recognition
|
|
# face_recognition_model = face_recognition_models.face_recognition_model_location()
|
|
# face_encoder = dlib.face_recognition_model_v1(face_recognition_model)
|
|
|
|
# def convert(detected_face):
|
|
# return np.array(face_encoder.compute_face_descriptor(detected_face.image, detected_face.landmarks, 1))
|
|
# # end of Copy/Paste
|