Skip to content

Commit d868de3

Browse files
authored
Merge pull request Python-World#444 from Jamyw7g/face_algorithm
Detect and align faces algorithm
2 parents 7962442 + bd72cec commit d868de3

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

projects/detect_align_faces/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Detect and align faces
2+
3+
This algorithm can detect the faces from picture and then align them.
4+
5+
## Requirement
6+
7+
**Dowload model parameters:**
8+
9+
You should dowload the [model parameters](http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2)
10+
from dlib, decompress and move to `./dat`
11+
12+
**Installation:**
13+
14+
```shell
15+
$ pip install -r requirements.txt
16+
```
17+
18+
## Usage
19+
20+
```shell
21+
$ python3 main.py [pic1, pic2...]
22+
```
23+
24+
After the script finished, you will get some faces picture in the same
25+
directory.
20.8 KB
Loading

projects/detect_align_faces/main.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright(C) 2021 wuyaoping
4+
#
5+
6+
7+
import numpy as np
8+
import os.path as osp
9+
import sys
10+
import cv2
11+
import dlib
12+
13+
OUT_SIZE = (224, 224)
14+
LEFT_EYE_RANGE = (36, 42)
15+
RIGHT_EYE_RABGE = (42, 48)
16+
LEFT_EYE_POS = (0.35, 0.3815)
17+
DAT_PATH = "./dat/shape_predictor_68_face_landmarks.dat"
18+
19+
20+
def main(files):
21+
detector = dlib.get_frontal_face_detector()
22+
sp = dlib.shape_predictor(DAT_PATH)
23+
24+
for file in files:
25+
img = cv2.imread(file, cv2.IMREAD_ANYCOLOR)
26+
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
27+
28+
faces = detect_align_faces(detector, sp, img)
29+
for (idx, face) in enumerate(faces):
30+
face = cv2.cvtColor(face, cv2.COLOR_RGB2BGR)
31+
filename, ext = osp.splitext(file)
32+
filename += '_face_{:03}'.format(idx) + ext
33+
cv2.imwrite(filename, face)
34+
35+
36+
def detect_align_faces(detector, sp, img):
37+
faces = detector(img, 1)
38+
res = []
39+
for face in faces:
40+
shape = sp(img, face)
41+
left, right = shape_to_pos(shape)
42+
left_center = np.mean(left, axis=0)
43+
right_center = np.mean(right, axis=0)
44+
45+
dx = right_center[0] - left_center[0]
46+
dy = right_center[1] - left_center[1]
47+
angle = np.degrees(np.arctan2(dy, dx))
48+
dist = np.sqrt(dy ** 2 + dx ** 2)
49+
out_dist = OUT_SIZE[0] * (1 - 2 * LEFT_EYE_POS[0])
50+
scale = out_dist / dist
51+
center = ((left_center + right_center) // 2).tolist()
52+
53+
mat = cv2.getRotationMatrix2D(center, angle, scale)
54+
mat[0, 2] += (0.5 * OUT_SIZE[0] - center[0])
55+
mat[1, 2] += (LEFT_EYE_POS[1] * OUT_SIZE[1] - center[1])
56+
res_face = cv2.warpAffine(img, mat, OUT_SIZE, flags=cv2.INTER_CUBIC)
57+
res.append(res_face)
58+
59+
return res
60+
61+
62+
def shape_to_pos(shape):
63+
parts = []
64+
for p in shape.parts():
65+
parts.append((p.x, p.y))
66+
67+
left = parts[LEFT_EYE_RANGE[0]: LEFT_EYE_RANGE[-1]]
68+
right = parts[RIGHT_EYE_RABGE[0]: RIGHT_EYE_RABGE[-1]]
69+
70+
return (np.array(left), np.array(right))
71+
72+
73+
if __name__ == '__main__':
74+
main(sys.argv[1:])
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dlib==19.22.1
2+
numpy==1.21.2
3+
opencv-python==4.5.3.56

0 commit comments

Comments
 (0)