File size: 5,728 Bytes
e5ba844
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# coding: utf-8

import cv2
import numpy as np


class BBox(object):
    # bbox is a list of [left, right, top, bottom]
    def __init__(self, bbox):
        self.left = bbox[0]
        self.right = bbox[1]
        self.top = bbox[2]
        self.bottom = bbox[3]
        self.x = bbox[0]
        self.y = bbox[2]
        self.w = bbox[1] - bbox[0]
        self.h = bbox[3] - bbox[2]

    # scale to [0,1]
    def projectLandmark(self, landmark):
        landmark_ = np.asarray(np.zeros(landmark.shape))
        for i, point in enumerate(landmark):
            landmark_[i] = ((point[0]-self.x)/self.w, (point[1]-self.y)/self.h)
        return landmark_

    # landmark of (5L, 2L) from [0,1] to real range
    def reprojectLandmark(self, landmark):
        landmark_ = np.asarray(np.zeros(landmark.shape))
        for i, point in enumerate(landmark):
            x = point[0] * self.w + self.x
            y = point[1] * self.h + self.y
            landmark_[i] = (x, y)
        return landmark_


def drawLandmark(img, bbox, landmark):
    '''
    Input:
    - img: gray or RGB
    - bbox: type of BBox
    - landmark: reproject landmark of (5L, 2L)
    Output:
    - img marked with landmark and bbox
    '''
    img_ = img.copy()
    cv2.rectangle(img_, (bbox.left, bbox.top),
                  (bbox.right, bbox.bottom), (0, 0, 255), 2)
    for x, y in landmark:
        cv2.circle(img_, (int(x), int(y)), 3, (0, 255, 0), -1)
    return img_


def drawLandmark_multiple(img, bbox, landmark):
    '''
    Input:
    - img: gray or RGB
    - bbox: type of BBox
    - landmark: reproject landmark of (5L, 2L)
    Output:
    - img marked with landmark and bbox
    '''
    cv2.rectangle(img, (bbox.left, bbox.top),
                  (bbox.right, bbox.bottom), (0, 0, 255), 2)
    for x, y in landmark:
        cv2.circle(img, (int(x), int(y)), 2, (0, 255, 0), -1)
    return img


def drawLandmark_Attribute(img, bbox, landmark, gender, age):
    '''
    Input:
    - img: gray or RGB
    - bbox: type of BBox
    - landmark: reproject landmark of (5L, 2L)
    Output:
    - img marked with landmark and bbox
    '''
    cv2.rectangle(img, (bbox.left, bbox.top),
                  (bbox.right, bbox.bottom), (0, 0, 255), 2)
    for x, y in landmark:
        cv2.circle(img, (int(x), int(y)), 3, (0, 255, 0), -1)
        if gender.argmax() == 0:
            # -1->female, 1->male; -1->old, 1->young
            cv2.putText(img, 'female', (int(bbox.left), int(bbox.top)),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 3)
        else:
            cv2.putText(img, 'male', (int(bbox.left), int(bbox.top)),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 3)
        if age.argmax() == 0:
            cv2.putText(img, 'old', (int(bbox.right), int(bbox.bottom)),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 3)
        else:
            cv2.putText(img, 'young', (int(bbox.right), int(bbox.bottom)),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 0), 3)
    return img


def drawLandmark_only(img, landmark):
    '''
    Input:
    - img: gray or RGB
    - bbox: type of BBox
    - landmark: reproject landmark of (5L, 2L)
    Output:
    - img marked with landmark and bbox
    '''
    img_ = img.copy()
    # cv2.rectangle(img_, (bbox.left, bbox.top), (bbox.right, bbox.bottom), (0,0,255), 2)
    for x, y in landmark:
        cv2.circle(img_, (int(x), int(y)), 3, (0, 255, 0), -1)
    return img_


def processImage(imgs):
    '''
    Subtract mean and normalize, imgs [N, 1, W, H]
    '''
    imgs = imgs.astype(np.float32)
    for i, img in enumerate(imgs):
        m = img.mean()
        s = img.std()
        imgs[i] = (img-m)/s
    return imgs


def flip(face, landmark):
    '''
    flip a face and its landmark
    '''
    face_ = cv2.flip(face, 1)  # 1 means flip horizontal
    landmark_flip = np.asarray(np.zeros(landmark.shape))
    for i, point in enumerate(landmark):
        landmark_flip[i] = (1-point[0], point[1])
    # for 5-point flip
        landmark_flip[[0, 1]] = landmark_flip[[1, 0]]
    landmark_flip[[3, 4]] = landmark_flip[[4, 3]]
    # for 19-point flip
    # landmark_flip[[0,9]] = landmark_flip[[9,0]]
    # landmark_flip[[1,8]] = landmark_flip[[8,1]]
    # landmark_flip[[2,7]] = landmark_flip[[7,2]]
    # landmark_flip[[3,6]] = landmark_flip[[6,3]]
    # landmark_flip[[4,11]] = landmark_flip[[11,4]]
    # landmark_flip[[5,10]] = landmark_flip[[10,5]]
    # landmark_flip[[12,14]] = landmark_flip[[14,12]]
    # landmark_flip[[15,17]] = landmark_flip[[17,15]]
    return (face_, landmark_flip)


def scale(landmark):
    '''
    scale the landmark from [0,1] to [-1,1]
    '''
    landmark_ = np.asarray(np.zeros(landmark.shape))
    lanmark_ = (landmark-0.5)*2
    return landmark_


def check_bbox(img, bbox):
    '''
    Check whether bbox is out of the range of the image
    '''
    img_w, img_h = img.shape
    if bbox.x > 0 and bbox.y > 0 and bbox.right < img_w and bbox.bottom < img_h:
        return True
    else:
        return False


def rotate(img, bbox, landmark, alpha):
    """
        given a face with bbox and landmark, rotate with alpha
        and return rotated face with bbox, landmark (absolute position)
    """
    center = ((bbox.left+bbox.right)/2, (bbox.top+bbox.bottom)/2)
    rot_mat = cv2.getRotationMatrix2D(center, alpha, 1)
    img_rotated_by_alpha = cv2.warpAffine(img, rot_mat, img.shape)
    landmark_ = np.asarray([(rot_mat[0][0]*x+rot_mat[0][1]*y+rot_mat[0][2],
                             rot_mat[1][0]*x+rot_mat[1][1]*y+rot_mat[1][2]) for (x, y) in landmark])
    face = img_rotated_by_alpha[bbox.top:bbox.bottom+1, bbox.left:bbox.right+1]
    return (face, landmark_)