from deepface import DeepFace from deepface.detectors import FaceDetector, OpenCvWrapper from deepface.extendedmodels import Emotion import cv2 import deepface.commons.functions import numpy import opennsfw2 class Emotion: labels = [emotion.capitalize() for emotion in Emotion.labels] model = DeepFace.build_model('Emotion') class NSFW: labels = [False, True] model = opennsfw2.make_open_nsfw_model() ################################################################################ class Pixels(numpy.ndarray): @classmethod def read(cls, path): return cv2.imread(path).view(type=cls) def write(self, path): cv2.imwrite(path, self) class FaceImage(Pixels): def analyze(face_img): face_img = cv2.cvtColor(face_img, cv2.COLOR_BGR2GRAY) face_img = cv2.resize(face_img, (48, 48)) face_img = numpy.expand_dims(face_img, axis=0) predictions = Emotion.model.predict(face_img).ravel() return Emotion.labels[numpy.argmax(predictions)] def represent(face_img): face_img = numpy.expand_dims(face_img, axis=0) return DeepFace.represent(face_img, 'VGG-Face', detector_backend='skip')[0]['embedding'] class Image(Pixels): def annotate(img, face, emotion): face_annotation = numpy.zeros_like(img) face_annotation = cv2.cvtColor(face_annotation, cv2.COLOR_BGR2GRAY).view(type=Pixels) x, y, w, h = face axes = (int(0.1 * w), int(0.1 * h)) cv2.ellipse(face_annotation, (x + axes[0], y + axes[1]), axes, 180, 0, 90, (1, 0, 0), 2) cv2.ellipse(face_annotation, (x + w - axes[0], y + axes[1]), axes, 270, 0, 90, (1, 0, 0), 2) cv2.ellipse(face_annotation, (x + axes[0], y + h - axes[1]), axes, 90, 0, 90, (1, 0, 0), 2) cv2.ellipse(face_annotation, (x + w - axes[0], y + h - axes[1]), axes, 0, 0, 90, (1, 0, 0), 2) emotion_annotation = numpy.zeros_like(img) emotion_annotation = cv2.cvtColor(emotion_annotation, cv2.COLOR_BGR2GRAY).view(type=Pixels) for fontScale in numpy.arange(10, 0, -0.1): textSize, _ = cv2.getTextSize(emotion, cv2.FONT_HERSHEY_SIMPLEX, fontScale, 2) if textSize[0] <= int(0.6 * w): break cv2.putText(emotion_annotation, emotion, (int(x + (w - textSize[0]) / 2), int(y + textSize[1] / 2)), cv2.FONT_HERSHEY_SIMPLEX, fontScale, (1, 0, 0), 2) return [(face_annotation, 'face'), (emotion_annotation, 'emotion')] def detect_faces(img): face_detector = FaceDetector.build_model('opencv') faces = [] for _, face, _ in FaceDetector.detect_faces(face_detector, 'opencv', img, False): face = (int(face[0]), int(face[1]), int(face[2]), int(face[3])) faces.append(face) return faces def extract_face(img, face): face_detector = FaceDetector.build_model('opencv') x, y, w, h = face img = img[y:y + h, x:x + w] img = OpenCvWrapper.align_face(face_detector['eye_detector'], img) target_size = deepface.commons.functions.find_target_size('VGG-Face') face_img, _, _ = deepface.commons.functions.extract_faces( img, target_size, 'skip')[0] face_img = numpy.squeeze(face_img, axis=0) return face_img.view(type=FaceImage) def nsfw(img): img = cv2.resize(img, (224, 224)) img = img - numpy.array([104, 117, 123], numpy.float32) img = numpy.expand_dims(img, axis=0) predictions = NSFW.model.predict(img).ravel() return NSFW.labels[numpy.argmax(predictions)] def pixelate(img): h, w, _ = img.shape img = cv2.resize(img, (16, 16)) return cv2.resize(img, (w, h), interpolation=cv2.INTER_NEAREST).view(type=Pixels) ################################################################################ class Metadata(dict): def __init__(self, img): metadata = {} for face in img.detect_faces(): face_img = img.extract_face(face) emotion = face_img.analyze() representation = face_img.represent() metadata[face] = { 'emotion': emotion, 'representation': representation } super(Metadata, self).__init__(metadata) def emotions(self): return [value['emotion'] for value in self.values()] def representations(self): return [value['representation'] for value in self.values()] ################################################################################ def verify(source_representations, test_representations): for source_representation in source_representations: for test_representation in test_representations: if deepface.commons.distance.findCosineDistance( source_representation, test_representation ) < deepface.commons.distance.findThreshold('VGG-Face', 'cosine'): return True return False