Skip to content
This repository was archived by the owner on May 25, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions projects/detect_align_faces/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Detect and align faces

This algorithm can detect the faces from picture and then align them.

## Requirement

**Dowload model parameters:**

You should dowload the [model parameters](http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2)
from dlib, decompress and move to `./dat`

**Installation:**

```shell
$ pip install -r requirements.txt
```

## Usage

```shell
$ python3 main.py [pic1, pic2...]
```

After the script finished, you will get some faces picture in the same
directory.
Binary file added projects/detect_align_faces/example.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions projects/detect_align_faces/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
#
# Copyright(C) 2021 wuyaoping
#


import numpy as np
import os.path as osp
import sys
import cv2
import dlib

OUT_SIZE = (224, 224)
LEFT_EYE_RANGE = (36, 42)
RIGHT_EYE_RABGE = (42, 48)
LEFT_EYE_POS = (0.35, 0.3815)
DAT_PATH = "./dat/shape_predictor_68_face_landmarks.dat"


def main(files):
detector = dlib.get_frontal_face_detector()
sp = dlib.shape_predictor(DAT_PATH)

for file in files:
img = cv2.imread(file, cv2.IMREAD_ANYCOLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

faces = detect_align_faces(detector, sp, img)
for (idx, face) in enumerate(faces):
face = cv2.cvtColor(face, cv2.COLOR_RGB2BGR)
filename, ext = osp.splitext(file)
filename += '_face_{:03}'.format(idx) + ext
cv2.imwrite(filename, face)


def detect_align_faces(detector, sp, img):
faces = detector(img, 1)
res = []
for face in faces:
shape = sp(img, face)
left, right = shape_to_pos(shape)
left_center = np.mean(left, axis=0)
right_center = np.mean(right, axis=0)

dx = right_center[0] - left_center[0]
dy = right_center[1] - left_center[1]
angle = np.degrees(np.arctan2(dy, dx))
dist = np.sqrt(dy ** 2 + dx ** 2)
out_dist = OUT_SIZE[0] * (1 - 2 * LEFT_EYE_POS[0])
scale = out_dist / dist
center = ((left_center + right_center) // 2).tolist()

mat = cv2.getRotationMatrix2D(center, angle, scale)
mat[0, 2] += (0.5 * OUT_SIZE[0] - center[0])
mat[1, 2] += (LEFT_EYE_POS[1] * OUT_SIZE[1] - center[1])
res_face = cv2.warpAffine(img, mat, OUT_SIZE, flags=cv2.INTER_CUBIC)
res.append(res_face)

return res


def shape_to_pos(shape):
parts = []
for p in shape.parts():
parts.append((p.x, p.y))

left = parts[LEFT_EYE_RANGE[0]: LEFT_EYE_RANGE[-1]]
right = parts[RIGHT_EYE_RABGE[0]: RIGHT_EYE_RABGE[-1]]

return (np.array(left), np.array(right))


if __name__ == '__main__':
main(sys.argv[1:])
3 changes: 3 additions & 0 deletions projects/detect_align_faces/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dlib==19.22.1
numpy==1.21.2
opencv-python==4.5.3.56