0
# Face Analysis
1
2
Facial landmark processing tools and face alignment functionality for dlib-based face detection workflows. These utilities bridge dlib's face detection capabilities with OpenCV's image processing functions.
3
4
## Capabilities
5
6
### Face Alignment
7
8
Automatic face alignment based on eye positions, supporting both 68-point and 5-point facial landmark detectors.
9
10
```python { .api }
11
class FaceAligner:
12
def __init__(self, predictor, desiredLeftEye=(0.35, 0.35), desiredFaceWidth=256, desiredFaceHeight=None):
13
"""
14
Face alignment based on eye positions.
15
16
Args:
17
predictor: dlib facial landmark predictor object
18
desiredLeftEye (tuple): Desired left eye position as ratio (x, y) (default: (0.35, 0.35))
19
desiredFaceWidth (int): Desired output face width in pixels (default: 256)
20
desiredFaceHeight (int, optional): Desired output face height in pixels (default: uses desiredFaceWidth)
21
"""
22
23
def align(self, image, gray, rect):
24
"""
25
Align and crop face based on eye positions.
26
27
Args:
28
image (np.ndarray): Color input image
29
gray (np.ndarray): Grayscale version of input image
30
rect: dlib rectangle object representing face bounding box
31
32
Returns:
33
np.ndarray: Aligned and cropped face image
34
35
Note:
36
Automatically detects whether using 68-point or 5-point landmark detector.
37
Calculates rotation angle and scale based on eye positions.
38
Applies affine transformation to align eyes horizontally.
39
"""
40
```
41
42
**Usage Example:**
43
```python
44
import cv2
45
import dlib
46
from imutils.face_utils import FaceAligner
47
48
# Initialize dlib face detector and landmark predictor
49
detector = dlib.get_frontal_face_detector()
50
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
51
52
# Initialize face aligner
53
fa = FaceAligner(predictor, desiredFaceWidth=256)
54
55
# Load image
56
image = cv2.imread("face.jpg")
57
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
58
59
# Detect faces
60
faces = detector(gray, 1)
61
62
for face in faces:
63
# Align face
64
aligned_face = fa.align(image, gray, face)
65
cv2.imshow("Aligned Face", aligned_face)
66
cv2.waitKey(0)
67
68
cv2.destroyAllWindows()
69
```
70
71
### Coordinate Conversion Utilities
72
73
Functions for converting between dlib and OpenCV coordinate formats.
74
75
```python { .api }
76
def rect_to_bb(rect):
77
"""
78
Convert dlib rectangle to OpenCV bounding box format.
79
80
Args:
81
rect: dlib rectangle object
82
83
Returns:
84
tuple: (x, y, w, h) bounding box coordinates in OpenCV format
85
"""
86
87
def shape_to_np(shape, dtype="int"):
88
"""
89
Convert dlib shape object to numpy array of coordinates.
90
91
Args:
92
shape: dlib shape object containing facial landmarks
93
dtype (str): NumPy data type (default: "int")
94
95
Returns:
96
np.ndarray: Array of (x, y) coordinates with shape (num_points, 2)
97
"""
98
```
99
100
**Usage Example:**
101
```python
102
import cv2
103
import dlib
104
from imutils.face_utils import rect_to_bb, shape_to_np
105
106
# Initialize detector and predictor
107
detector = dlib.get_frontal_face_detector()
108
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
109
110
image = cv2.imread("face.jpg")
111
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
112
113
# Detect faces
114
faces = detector(gray, 1)
115
116
for face in faces:
117
# Convert dlib rectangle to OpenCV bounding box
118
(x, y, w, h) = rect_to_bb(face)
119
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
120
121
# Get facial landmarks
122
shape = predictor(gray, face)
123
landmarks = shape_to_np(shape)
124
125
# Draw landmarks
126
for (x, y) in landmarks:
127
cv2.circle(image, (x, y), 2, (0, 0, 255), -1)
128
129
cv2.imshow("Face Detection", image)
130
cv2.waitKey(0)
131
cv2.destroyAllWindows()
132
```
133
134
### Facial Landmark Visualization
135
136
Visualization utilities for drawing facial landmark regions on images.
137
138
```python { .api }
139
def visualize_facial_landmarks(image, shape, colors=None, alpha=0.75):
140
"""
141
Draw facial landmark regions on image.
142
143
Args:
144
image (np.ndarray): Input image (OpenCV format)
145
shape (np.ndarray): Array of facial landmark coordinates
146
colors (list, optional): List of BGR color tuples for each region
147
alpha (float): Transparency level for overlay (default: 0.75)
148
149
Returns:
150
np.ndarray: Output image with facial landmarks visualized
151
152
Note:
153
Automatically determines landmark format (68-point or 5-point).
154
Uses predefined colors if colors parameter is not provided.
155
Draws polygons for regions like jaw, eyebrows, eyes, nose, mouth.
156
"""
157
```
158
159
**Usage Example:**
160
```python
161
import cv2
162
import dlib
163
from imutils.face_utils import shape_to_np, visualize_facial_landmarks
164
165
# Initialize detector and predictor
166
detector = dlib.get_frontal_face_detector()
167
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
168
169
image = cv2.imread("face.jpg")
170
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
171
172
# Detect faces
173
faces = detector(gray, 1)
174
175
for face in faces:
176
# Get facial landmarks
177
shape = predictor(gray, face)
178
landmarks = shape_to_np(shape)
179
180
# Visualize landmarks
181
output = visualize_facial_landmarks(image, landmarks, alpha=0.6)
182
cv2.imshow("Facial Landmarks", output)
183
cv2.waitKey(0)
184
185
cv2.destroyAllWindows()
186
```
187
188
### Facial Landmark Constants
189
190
Pre-defined mappings for facial landmark regions to array indices.
191
192
```python { .api }
193
# For 68-point facial landmark detector
194
FACIAL_LANDMARKS_68_IDXS = {
195
"mouth": (48, 68),
196
"inner_mouth": (60, 68),
197
"right_eyebrow": (17, 22),
198
"left_eyebrow": (22, 27),
199
"right_eye": (36, 42),
200
"left_eye": (42, 48),
201
"nose": (27, 36),
202
"jaw": (0, 17)
203
}
204
205
# For 5-point facial landmark detector
206
FACIAL_LANDMARKS_5_IDXS = {
207
"right_eye": (0, 1),
208
"left_eye": (1, 2),
209
"nose": (2, 5)
210
}
211
212
# Legacy alias
213
FACIAL_LANDMARKS_IDXS = FACIAL_LANDMARKS_68_IDXS
214
```
215
216
**Usage Example:**
217
```python
218
import cv2
219
import dlib
220
from imutils.face_utils import (shape_to_np, FACIAL_LANDMARKS_68_IDXS,
221
visualize_facial_landmarks)
222
223
# Initialize detector and predictor
224
detector = dlib.get_frontal_face_detector()
225
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
226
227
image = cv2.imread("face.jpg")
228
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
229
230
faces = detector(gray, 1)
231
232
for face in faces:
233
shape = predictor(gray, face)
234
landmarks = shape_to_np(shape)
235
236
# Extract specific facial regions
237
(j, k) = FACIAL_LANDMARKS_68_IDXS["left_eye"]
238
left_eye = landmarks[j:k]
239
240
(j, k) = FACIAL_LANDMARKS_68_IDXS["right_eye"]
241
right_eye = landmarks[j:k]
242
243
(j, k) = FACIAL_LANDMARKS_68_IDXS["mouth"]
244
mouth = landmarks[j:k]
245
246
# Draw specific regions
247
for (x, y) in left_eye:
248
cv2.circle(image, (x, y), 2, (0, 255, 0), -1) # Green for left eye
249
250
for (x, y) in right_eye:
251
cv2.circle(image, (x, y), 2, (255, 0, 0), -1) # Blue for right eye
252
253
for (x, y) in mouth:
254
cv2.circle(image, (x, y), 2, (0, 0, 255), -1) # Red for mouth
255
256
cv2.imshow("Facial Regions", image)
257
cv2.waitKey(0)
258
cv2.destroyAllWindows()
259
```
260
261
### Complete Face Processing Pipeline
262
263
Here's a comprehensive example combining face detection, alignment, and landmark visualization:
264
265
```python
266
import cv2
267
import dlib
268
import numpy as np
269
from imutils.face_utils import (FaceAligner, rect_to_bb, shape_to_np,
270
visualize_facial_landmarks, FACIAL_LANDMARKS_68_IDXS)
271
272
def process_faces_in_image(image_path, predictor_path):
273
# Initialize dlib components
274
detector = dlib.get_frontal_face_detector()
275
predictor = dlib.shape_predictor(predictor_path)
276
fa = FaceAligner(predictor, desiredFaceWidth=256)
277
278
# Load image
279
image = cv2.imread(image_path)
280
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
281
original = image.copy()
282
283
# Detect faces
284
faces = detector(gray, 1)
285
print(f"Found {len(faces)} faces")
286
287
aligned_faces = []
288
289
for (i, face) in enumerate(faces):
290
# Convert dlib rectangle to bounding box
291
(x, y, w, h) = rect_to_bb(face)
292
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
293
cv2.putText(image, f"Face {i+1}", (x - 10, y - 10),
294
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
295
296
# Get facial landmarks
297
shape = predictor(gray, face)
298
landmarks = shape_to_np(shape)
299
300
# Visualize landmarks
301
landmark_image = visualize_facial_landmarks(original.copy(), landmarks)
302
303
# Align face
304
aligned_face = fa.align(original, gray, face)
305
aligned_faces.append(aligned_face)
306
307
# Show results for this face
308
cv2.imshow(f"Face {i+1} - Landmarks", landmark_image)
309
cv2.imshow(f"Face {i+1} - Aligned", aligned_face)
310
311
# Show original with bounding boxes
312
cv2.imshow("Face Detection", image)
313
314
# Create montage of aligned faces if multiple faces found
315
if len(aligned_faces) > 1:
316
# Resize all faces to same size
317
aligned_resized = [cv2.resize(face, (256, 256)) for face in aligned_faces]
318
319
# Create horizontal montage
320
montage = np.hstack(aligned_resized)
321
cv2.imshow("Aligned Faces Montage", montage)
322
323
cv2.waitKey(0)
324
cv2.destroyAllWindows()
325
326
return aligned_faces
327
328
# Usage
329
if __name__ == "__main__":
330
aligned_faces = process_faces_in_image(
331
"group_photo.jpg",
332
"shape_predictor_68_face_landmarks.dat"
333
)
334
print(f"Processed and aligned {len(aligned_faces)} faces")
335
```
336
337
### Custom Face Processing
338
339
Example of custom face processing with eye aspect ratio calculation:
340
341
```python
342
import cv2
343
import dlib
344
import numpy as np
345
from imutils.face_utils import shape_to_np, FACIAL_LANDMARKS_68_IDXS
346
347
def eye_aspect_ratio(eye):
348
"""Calculate eye aspect ratio for blink detection."""
349
# Vertical eye landmarks
350
A = np.linalg.norm(eye[1] - eye[5])
351
B = np.linalg.norm(eye[2] - eye[4])
352
353
# Horizontal eye landmark
354
C = np.linalg.norm(eye[0] - eye[3])
355
356
# Eye aspect ratio
357
ear = (A + B) / (2.0 * C)
358
return ear
359
360
def detect_blinks(image_path, predictor_path):
361
detector = dlib.get_frontal_face_detector()
362
predictor = dlib.shape_predictor(predictor_path)
363
364
# Eye aspect ratio threshold
365
EAR_THRESHOLD = 0.3
366
367
image = cv2.imread(image_path)
368
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
369
370
faces = detector(gray, 1)
371
372
for face in faces:
373
landmarks = shape_to_np(predictor(gray, face))
374
375
# Extract eye coordinates
376
(lStart, lEnd) = FACIAL_LANDMARKS_68_IDXS["left_eye"]
377
(rStart, rEnd) = FACIAL_LANDMARKS_68_IDXS["right_eye"]
378
379
leftEye = landmarks[lStart:lEnd]
380
rightEye = landmarks[rStart:rEnd]
381
382
# Calculate eye aspect ratios
383
leftEAR = eye_aspect_ratio(leftEye)
384
rightEAR = eye_aspect_ratio(rightEye)
385
ear = (leftEAR + rightEAR) / 2.0
386
387
# Check for blink
388
if ear < EAR_THRESHOLD:
389
cv2.putText(image, "BLINK DETECTED", (10, 30),
390
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
391
392
# Draw eye contours
393
cv2.drawContours(image, [cv2.convexHull(leftEye)], -1, (0, 255, 0), 1)
394
cv2.drawContours(image, [cv2.convexHull(rightEye)], -1, (0, 255, 0), 1)
395
396
# Display EAR value
397
cv2.putText(image, f"EAR: {ear:.2f}", (300, 30),
398
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)
399
400
cv2.imshow("Blink Detection", image)
401
cv2.waitKey(0)
402
cv2.destroyAllWindows()
403
404
# Usage
405
detect_blinks("face.jpg", "shape_predictor_68_face_landmarks.dat")
406
```