File size: 2,859 Bytes
bd096d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970f13d
bd096d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970f13d
 
 
bd096d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# -*- coding: utf-8 -*-
# Max-Planck-Gesellschaft zur Förderung der Wissenschaften e.V. (MPG) is
# holder of all proprietary rights on this computer program.
# You can only use this computer program if you have closed
# a license agreement with MPG or you get the right to use the computer
# program from someone who is authorized to grant you that right.
# Any use of the computer program without a valid license is prohibited and
# liable to prosecution.
#
# Copyright©2023 Max-Planck-Gesellschaft zur Förderung
# der Wissenschaften e.V. (MPG). acting on behalf of its Max Planck Institute
# for Intelligent Systems. All rights reserved.
#
# Contact: mica@tue.mpg.de


import face_alignment
import numpy as np
from insightface.app import FaceAnalysis
from pixel3dmm import env_paths
from loguru import logger

from datasets.creation.util import get_bbox


class Detectors:
    def __init__(self):
        self.RETINAFACE = 'RETINAFACE'
        self.FAN = 'FAN'


detectors = Detectors()


class LandmarksDetector:
    def __init__(self, model='retinaface', device='cuda:0'):
        model = model.upper()
        self.predictor = model
        if model == detectors.RETINAFACE:
            self._face_detector = FaceAnalysis(name='antelopev2', 
                            root=f'{env_paths.ANT_DIR}',
                            providers=['CUDAExecutionProvider'])
            self._face_detector.prepare(ctx_id=0, det_size=(224, 224))
        elif model == detectors.FAN:
            self._face_detector = face_alignment.FaceAlignment(face_alignment.LandmarksType._2D, device=device)
        else:
            logger.error(f'[ERROR] Landmark predictor not supported {model}')
            exit(-1)

        logger.info(f'[DETECTOR] Selected {model} as landmark detector.')

    def detect(self, img):
        if self.predictor == detectors.RETINAFACE:
            bboxes, kpss = self._face_detector.det_model.detect(img, max_num=0, metric='default')
            return bboxes, kpss

        if self.predictor == detectors.FAN:
            lmks, scores, detected_faces = self._face_detector.get_landmarks_from_image(img, return_landmark_score=True, return_bboxes=True)
            if detected_faces is None:
                return np.empty(0), np.empty(0)
            bboxes = np.stack(detected_faces)
            # bboxes = get_bbox(img, np.stack(lmks))
            # bboxes[:, 4] = detected_faces[:, 4]
            # https://github.com/Rubikplayer/flame-fitting/blob/master/data/landmarks_51_annotated.png
            lmk51 = np.stack(lmks)[:, 17:, :]
            kpss = lmk51[:, [20, 27, 13, 43, 47], :]  # left eye, right eye, nose, left mouth, right mouth
            kpss[:, 0, :] = lmk51[:, [21, 24], :].mean(1)  # center of eye
            kpss[:, 1, :] = lmk51[:, [27, 29], :].mean(1)
            return bboxes, kpss

        return None, None