File size: 3,864 Bytes
c61b6f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import os
import cv2
import torch
import numpy as np
from PIL import Image
from dlib import cnn_face_detection_model_v1 as face_detect_model


def center_crop(im, length):
    w, h = im.size
    left = w//2 - length//2
    right = w//2 + length//2
    top = h//2 - length//2
    bottom = h//2 + length//2
    return im.crop((left, top, right, bottom)), (left, top)


def remove_boundary(img):
    """

    Remove boundary artifacts that FAL causes.

    """
    w, h = img.size
    left = w//80
    top = h//50
    right = w*79//80
    bottom = h*24//25
    return img.crop((left, top, right, bottom))


def resize_shorter_side(img, min_length):
    """

    Resize the shorter side of img to min_length while

    preserving the aspect ratio.

    """
    ow, oh = img.size
    mult = 8
    if ow < oh:
        if ow == min_length and oh % mult == 0:
            return img, (ow, oh)
        w = min_length
        h = int(min_length * oh / ow)
    else:
        if oh == min_length and ow % mult == 0:
            return img, (ow, oh)
        h = min_length
        w = int(min_length * ow / oh)
    return img.resize((w, h), Image.BICUBIC), (w, h)


def flow_resize(flow, sz):
    oh, ow, _ = flow.shape
    w, h = sz
    u_ = cv2.resize(flow[:,:,0], (w, h))
    v_ = cv2.resize(flow[:,:,1], (w, h))
    u_ *= w / float(ow)
    v_ *= h / float(oh)
    return np.dstack((u_,v_))


def warp(im, flow, alpha=1, interp=cv2.INTER_CUBIC):
    height, width, _ = flow.shape
    cart = np.dstack(np.meshgrid(np.arange(width), np.arange(height)))
    pixel_map = (cart + alpha * flow).astype(np.float32)
    warped = cv2.remap(
        im,
        pixel_map[:, :, 0],
        pixel_map[:, :, 1],
        interp,
        borderMode=cv2.BORDER_REPLICATE)
    return warped


cnn_face_detector = None
def face_detection(

        img_path,

        verbose=False,

        model_file='utils/dlib_face_detector/mmod_human_face_detector.dat'):
    """

    Detects faces using dlib cnn face detection, and extend the bounding box

    to include the entire face.

    """
    def shrink(img, max_length=2048):
        ow, oh = img.size
        if max_length >= max(ow, oh):
            return img, 1.0

        if ow > oh:
            mult = max_length / ow
        else:
            mult = max_length / oh
        w = int(ow * mult)
        h = int(oh * mult)
        return img.resize((w, h), Image.BILINEAR), mult

    global cnn_face_detector
    if cnn_face_detector is None:
        cnn_face_detector = face_detect_model(model_file)

    img = Image.open(img_path).convert('RGB')
    w, h = img.size
    img_shrinked, mult = shrink(img)

    im = np.asarray(img_shrinked)
    if len(im.shape) != 3 or im.shape[2] != 3:
        return []

    crop_ims = []
    dets = cnn_face_detector(im, 0)
    for k, d in enumerate(dets):
        top = d.rect.top() / mult
        bottom = d.rect.bottom() / mult
        left = d.rect.left() / mult
        right = d.rect.right() / mult

        wid = right - left
        left = max(0, left - wid // 2.5)
        top = max(0, top - wid // 1.5)
        right = min(w - 1, right + wid // 2.5)
        bottom = min(h - 1, bottom + wid // 2.5)

        if d.confidence > 1:
            if verbose:
                print("%d-th face detected: (%d, %d, %d, %d)" %
                      (k, left, top, right, bottom))
            crop_im = img.crop((left, top, right, bottom))
            crop_ims.append((crop_im, (left, top, right, bottom)))

    return crop_ims


def mkdirs(paths):
    if isinstance(paths, list) and not isinstance(paths, str):
        for path in paths:
            mkdir(path)
    else:
        mkdir(paths)


def mkdir(path):
    if not os.path.exists(path):
        os.makedirs(path)