face_detection_utils.py 8.63 KB
Newer Older
1
2
3
4
5
6
7
8
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
"""
This file contains face detection utils.
"""
#==============================================================================
# Import here:

9
import importlib
10
import numpy as np
11
12


13
14
#==============================================================================
def get_eye_pos(lm):
Anjith GEORGE's avatar
Anjith GEORGE committed
15
    """
16
    This function returns the locations of left and right eyes
Anjith GEORGE's avatar
Anjith GEORGE committed
17
18
19

    **Parameters:**

20
    ``lm`` : :py:class:`numpy.ndarray`
Anjith GEORGE's avatar
Anjith GEORGE committed
21
22
23
24
        A numpy array containing the coordinates of facial landmarks, (68X2)

    **Returns:**

25
26
    ``right_eye``
        A tuple containing the location of right eye,
Anjith GEORGE's avatar
Anjith GEORGE committed
27

28
    ``left_eye``
Anjith GEORGE's avatar
Anjith GEORGE committed
29
30
31
32
33
34
        A tuple containing the location of left eye

    """

    # Mean position of eye corners as eye centers , casted to int()

35
36
    left_eye_t = (lm[36, :] + lm[39, :]) / 2.0
    right_eye_t = (lm[42, :] + lm[45, :]) / 2.0
Anjith GEORGE's avatar
Anjith GEORGE committed
37

38
39
    right_eye = (int(left_eye_t[1]), int(left_eye_t[0]))
    left_eye = (int(right_eye_t[1]), int(right_eye_t[0]))
Anjith GEORGE's avatar
Anjith GEORGE committed
40

41
    return right_eye, left_eye
Anjith GEORGE's avatar
Anjith GEORGE committed
42
43


44
#==============================================================================
45
def detect_face_in_image(image, method="dlib"):
46
47
48
49
50
51
52
53
    """
    This function detects a face in the input image.

    **Parameters:**

    ``image`` : 3D :py:class:`numpy.ndarray`
        A color image to detect the face in.

54
    ``method`` : :py:class:`str`
55
56
57
58
        A package to be used for face detection. Options supported by this
        package: "dlib" (dlib is a dependency of this package). If  bob.ip.mtcnn
        is installed in your system you can use it as-well (bob.ip.mtcnn is NOT
        a dependency of this package).
59

60
61
62
63
64
    **Returns:**

    ``annotations`` : :py:class:`dict`
        A dictionary containing annotations of the face bounding box.
        Dictionary must be as follows ``{'topleft': (row, col), 'bottomright': (row, col)}``.
65
        If no annotations found an empty dictionary is returned.
66
67
    """

68
69
70
71
    try:
        face_detection_module = importlib.import_module("bob.ip." + method)
    except ImportError:
        raise ImportError("No module named bob.ip." + method)
72

73
    if not hasattr(face_detection_module, 'FaceDetector'):
74
75
        raise AttributeError(
            "bob.ip." + method + " module has no attribute FaceDetector")
76

77
    data = face_detection_module.FaceDetector().detect_single_face(image)
78
79
80

    annotations = {}

81
    if (data is not None) and (not all([x is None for x in data])):
82

83
        bounding_box = data[0]
84

85
86
87
        annotations['topleft'] = bounding_box.topleft

        annotations['bottomright'] = bounding_box.bottomright
88
89
90
91
92

    return annotations


#==============================================================================
93
def detect_faces_in_video(frame_container, method="dlib"):
94
95
96
97
98
99
100
101
    """
    This function detects a face in each farme of the input video.

    **Parameters:**

    ``frame_container`` : FrameContainer
        FrameContainer containing the frames data.

102
    ``method`` : :py:class:`str`
103
104
105
106
        A package to be used for face detection. Options supported by this
        package: "dlib" (dlib is a dependency of this package). If  bob.ip.mtcnn
        is installed in your system you can use it as-well (bob.ip.mtcnn is NOT
        a dependency of this package).
107

108
109
110
111
112
113
114
    **Returns:**

    ``annotations`` : :py:class:`dict`
        A dictionary containing the annotations for each frame in the video.
        Dictionary structure: ``annotations = {'1': frame1_dict, '2': frame1_dict, ...}``.
        Where ``frameN_dict = {'topleft': (row, col), 'bottomright': (row, col)}``
        is the dictionary defining the coordinates of the face bounding box in frame N.
115
        If no annotations found an empty dictionary is returned.
116
117
118
119
120
121
122
123
    """

    annotations = {}

    for idx, frame in enumerate(frame_container):

        image = frame[1]

124
        frame_annotations = detect_face_in_image(image, method)
125

126
127
128
        if frame_annotations:

            annotations[str(idx)] = frame_annotations
129
130
131

    return annotations

Anjith GEORGE's avatar
Anjith GEORGE committed
132

133
#==============================================================================
134
def detect_face_landmarks_in_image(image, method="dlib"):
135
    """
Anjith GEORGE's avatar
Anjith GEORGE committed
136
    This function detects a face in the input image. Two oprions for face detector , but landmark detector is always the same
137
138
139

    **Parameters:**

Anjith GEORGE's avatar
Anjith GEORGE committed
140
141
    ``image`` : 3D :py:class:`numpy.ndarray`
        A color image to detect the face in.
142

Anjith GEORGE's avatar
Anjith GEORGE committed
143
144
145
146
147
    ``method`` : :py:class:`str`
        A package to be used for face detection. Options supported by this
        package: "dlib" (dlib is a dependency of this package). If  bob.ip.mtcnn
        is installed in your system you can use it as-well (bob.ip.mtcnn is NOT
        a dependency of this package).
148
149
150

    **Returns:**

Anjith GEORGE's avatar
Anjith GEORGE committed
151
152
153
154
155
156
    ``annotations`` : :py:class:`dict`
        A dictionary containing annotations of the face bounding box, eye locations and facial landmarks.
        Dictionary must be as follows ``{'topleft': (row, col), 'bottomright': (row, col), 'left_eye': (row, col), 'right_eye': (row, col), 'landmarks': [(col1,row1), (col2,row2), ...]}``.
        If no annotations found an empty dictionary is returned.
        Where (rowK,colK) is the location of Kth facial landmark (K=0,...,67).
    """
157

Anjith GEORGE's avatar
Anjith GEORGE committed
158
    ### Face detector
159

Anjith GEORGE's avatar
Anjith GEORGE committed
160
    try:
161
        face_detection_module = importlib.import_module("bob.ip." + method)
162

Anjith GEORGE's avatar
Anjith GEORGE committed
163
    except ImportError:
164

165
166
        print("No module named bob.ip." + method +
              " trying to use default method!")
167

168
169
170
171
172
        try:
            face_detection_module = importlib.import_module("bob.ip.dlib")
            method = "dlib"
        except ImportError:
            raise ImportError("No module named bob.ip.dlib")
Anjith GEORGE's avatar
Anjith GEORGE committed
173
174

    if not hasattr(face_detection_module, 'FaceDetector'):
175
176
        raise AttributeError(
            "bob.ip." + method + " module has no attribute FaceDetector!")
Anjith GEORGE's avatar
Anjith GEORGE committed
177
178
179
180

    #### Landmark detector

    try:
181
182
        landmark_detection_module = importlib.import_module(
            "bob.ip.facelandmarks")
Anjith GEORGE's avatar
Anjith GEORGE committed
183
184
185
    except ImportError:
        raise ImportError("No module named bob.ip.facelandmarks!!")

186
187
188
189
190
    if not hasattr(landmark_detection_module,
                   'detect_landmarks_on_boundingbox'):
        raise AttributeError(
            "bob.ip.facelandmarksmodule has no attribute detect_landmarks_on_boundingbox!"
        )
Anjith GEORGE's avatar
Anjith GEORGE committed
191
192

    face_detector = face_detection_module.FaceDetector()
193

Anjith GEORGE's avatar
Anjith GEORGE committed
194
    data = face_detector.detect_single_face(image)
195

Anjith GEORGE's avatar
Anjith GEORGE committed
196
    annotations = {}
197

198
    if (data is not None) and (not all([x is None for x in data])):
199

Anjith GEORGE's avatar
Anjith GEORGE committed
200
        bounding_box = data[0]
201

202
        bounding_box_scaled = bounding_box.scale(0.95, True)  # is ok for dlib
203

204
205
        lm = landmark_detection_module.detect_landmarks_on_boundingbox(
            image, bounding_box_scaled)
206

Anjith GEORGE's avatar
Anjith GEORGE committed
207
        if lm is not None:
208

209
            lm = np.array(lm)
210

211
            lm = np.vstack((lm[:, 1], lm[:, 0])).T
212

Anjith GEORGE's avatar
Anjith GEORGE committed
213
            #print("LM",lm)
214

215
            right_eye, left_eye = get_eye_pos(lm)
216

Anjith GEORGE's avatar
Anjith GEORGE committed
217
218
219
220
            points = []

            for i in range(lm.shape[0]):

221
                points.append((int(lm[i, 0]), int(lm[i, 1])))
222

Anjith GEORGE's avatar
Anjith GEORGE committed
223
            annotations['topleft'] = bounding_box.topleft
224

Anjith GEORGE's avatar
Anjith GEORGE committed
225
            annotations['bottomright'] = bounding_box.bottomright
226

Anjith GEORGE's avatar
Anjith GEORGE committed
227
            annotations['landmarks'] = points
228

Anjith GEORGE's avatar
Anjith GEORGE committed
229
            annotations['left_eye'] = left_eye
230

Anjith GEORGE's avatar
Anjith GEORGE committed
231
            annotations['right_eye'] = right_eye
232
233
234
235

    return annotations


236
#==============================================================================
237
def detect_face_landmarks_in_video(frame_container, method="dlib"):
238
239
240
241
242
243
244
245
246
247
    """
    This function detects a face and face landmarks  in each farme of the input video.

    **Parameters:**

    ``frame_container`` : FrameContainer
        FrameContainer containing the frames data.

    ``method`` : :py:class:`str`
        A package to be used for face detection. Options supported by this
Anjith GEORGE's avatar
Anjith GEORGE committed
248
249
        package: "dlib" (dlib is a dependency of this package) and "mtcnn".
        If its found it will be used else defaults to "dlib"
250
251
252
253
254
255

    **Returns:**

    ``annotations`` : :py:class:`dict`
        A dictionary containing the annotations for each frame in the video.
        Dictionary structure: ``annotations = {'1': frame1_dict, '2': frame1_dict, ...}``.
Anjith GEORGE's avatar
Anjith GEORGE committed
256
        Where ``frameN_dict = {'topleft': (row, col), 'bottomright': (row, col), 'left_eye': (row, col), 'right_eye': (row, col), 'landmarks': [(col1,row1), (col2,row2), ...]}``
257
        is the dictionary defining the coordinates of the face bounding box in frame N.
Anjith GEORGE's avatar
Anjith GEORGE committed
258
        Where (colK,rowK) is the location of Kth facial landmark (K=0,...,67).
259
260
261
262
263
264
265
266
267
        If no annotations found an empty dictionary is returned.
    """

    annotations = {}

    for idx, frame in enumerate(frame_container):

        image = frame[1]

268
        frame_annotations = detect_face_landmarks_in_image(image, method)
269
270
271
272
273
274

        if frame_annotations:

            annotations[str(idx)] = frame_annotations

    return annotations