conciomith commited on
Commit
f8112c8
1 Parent(s): 9e6296d

Upload postprocess.py

Browse files
Files changed (1) hide show
  1. postprocess.py +178 -0
postprocess.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from PIL import Image
3
+ import math
4
+
5
+ def findEuclideanDistance(source_representation, test_representation):
6
+ euclidean_distance = source_representation - test_representation
7
+ euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
8
+ euclidean_distance = np.sqrt(euclidean_distance)
9
+ return euclidean_distance
10
+
11
+ #this function copied from the deepface repository: https://github.com/serengil/deepface/blob/master/deepface/commons/functions.py
12
+ def alignment_procedure(img, left_eye, right_eye, nose):
13
+
14
+ #this function aligns given face in img based on left and right eye coordinates
15
+
16
+ left_eye_x, left_eye_y = left_eye
17
+ right_eye_x, right_eye_y = right_eye
18
+
19
+ #-----------------------
20
+ upside_down = False
21
+ if nose[1] < left_eye[1] or nose[1] < right_eye[1]:
22
+ upside_down = True
23
+
24
+ #-----------------------
25
+ #find rotation direction
26
+
27
+ if left_eye_y > right_eye_y:
28
+ point_3rd = (right_eye_x, left_eye_y)
29
+ direction = -1 #rotate same direction to clock
30
+ else:
31
+ point_3rd = (left_eye_x, right_eye_y)
32
+ direction = 1 #rotate inverse direction of clock
33
+
34
+ #-----------------------
35
+ #find length of triangle edges
36
+
37
+ a = findEuclideanDistance(np.array(left_eye), np.array(point_3rd))
38
+ b = findEuclideanDistance(np.array(right_eye), np.array(point_3rd))
39
+ c = findEuclideanDistance(np.array(right_eye), np.array(left_eye))
40
+
41
+ #-----------------------
42
+
43
+ #apply cosine rule
44
+
45
+ if b != 0 and c != 0: #this multiplication causes division by zero in cos_a calculation
46
+
47
+ cos_a = (b*b + c*c - a*a)/(2*b*c)
48
+
49
+ #PR15: While mathematically cos_a must be within the closed range [-1.0, 1.0], floating point errors would produce cases violating this
50
+ #In fact, we did come across a case where cos_a took the value 1.0000000169176173, which lead to a NaN from the following np.arccos step
51
+ cos_a = min(1.0, max(-1.0, cos_a))
52
+
53
+
54
+ angle = np.arccos(cos_a) #angle in radian
55
+ angle = (angle * 180) / math.pi #radian to degree
56
+
57
+ #-----------------------
58
+ #rotate base image
59
+
60
+ if direction == -1:
61
+ angle = 90 - angle
62
+
63
+ if upside_down == True:
64
+ angle = angle + 90
65
+
66
+ img = Image.fromarray(img)
67
+ img = np.array(img.rotate(direction * angle))
68
+
69
+ #-----------------------
70
+
71
+ return img #return img anyway
72
+
73
+ #this function is copied from the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/retinaface.py
74
+ def bbox_pred(boxes, box_deltas):
75
+ if boxes.shape[0] == 0:
76
+ return np.zeros((0, box_deltas.shape[1]))
77
+
78
+ boxes = boxes.astype(np.float, copy=False)
79
+ widths = boxes[:, 2] - boxes[:, 0] + 1.0
80
+ heights = boxes[:, 3] - boxes[:, 1] + 1.0
81
+ ctr_x = boxes[:, 0] + 0.5 * (widths - 1.0)
82
+ ctr_y = boxes[:, 1] + 0.5 * (heights - 1.0)
83
+
84
+ dx = box_deltas[:, 0:1]
85
+ dy = box_deltas[:, 1:2]
86
+ dw = box_deltas[:, 2:3]
87
+ dh = box_deltas[:, 3:4]
88
+
89
+ pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis]
90
+ pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis]
91
+ pred_w = np.exp(dw) * widths[:, np.newaxis]
92
+ pred_h = np.exp(dh) * heights[:, np.newaxis]
93
+
94
+ pred_boxes = np.zeros(box_deltas.shape)
95
+ # x1
96
+ pred_boxes[:, 0:1] = pred_ctr_x - 0.5 * (pred_w - 1.0)
97
+ # y1
98
+ pred_boxes[:, 1:2] = pred_ctr_y - 0.5 * (pred_h - 1.0)
99
+ # x2
100
+ pred_boxes[:, 2:3] = pred_ctr_x + 0.5 * (pred_w - 1.0)
101
+ # y2
102
+ pred_boxes[:, 3:4] = pred_ctr_y + 0.5 * (pred_h - 1.0)
103
+
104
+ if box_deltas.shape[1]>4:
105
+ pred_boxes[:,4:] = box_deltas[:,4:]
106
+
107
+ return pred_boxes
108
+
109
+ # This function copied from the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/retinaface.py
110
+ def landmark_pred(boxes, landmark_deltas):
111
+ if boxes.shape[0] == 0:
112
+ return np.zeros((0, landmark_deltas.shape[1]))
113
+ boxes = boxes.astype(np.float, copy=False)
114
+ widths = boxes[:, 2] - boxes[:, 0] + 1.0
115
+ heights = boxes[:, 3] - boxes[:, 1] + 1.0
116
+ ctr_x = boxes[:, 0] + 0.5 * (widths - 1.0)
117
+ ctr_y = boxes[:, 1] + 0.5 * (heights - 1.0)
118
+ pred = landmark_deltas.copy()
119
+ for i in range(5):
120
+ pred[:,i,0] = landmark_deltas[:,i,0]*widths + ctr_x
121
+ pred[:,i,1] = landmark_deltas[:,i,1]*heights + ctr_y
122
+ return pred
123
+
124
+ # This function copied from rcnn module of retinaface-tf2 project: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/rcnn/processing/bbox_transform.py
125
+ def clip_boxes(boxes, im_shape):
126
+ # x1 >= 0
127
+ boxes[:, 0::4] = np.maximum(np.minimum(boxes[:, 0::4], im_shape[1] - 1), 0)
128
+ # y1 >= 0
129
+ boxes[:, 1::4] = np.maximum(np.minimum(boxes[:, 1::4], im_shape[0] - 1), 0)
130
+ # x2 < im_shape[1]
131
+ boxes[:, 2::4] = np.maximum(np.minimum(boxes[:, 2::4], im_shape[1] - 1), 0)
132
+ # y2 < im_shape[0]
133
+ boxes[:, 3::4] = np.maximum(np.minimum(boxes[:, 3::4], im_shape[0] - 1), 0)
134
+ return boxes
135
+
136
+ #this function is mainly based on the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/rcnn/cython/anchors.pyx
137
+ def anchors_plane(height, width, stride, base_anchors):
138
+ A = base_anchors.shape[0]
139
+ c_0_2 = np.tile(np.arange(0, width)[np.newaxis, :, np.newaxis, np.newaxis], (height, 1, A, 1))
140
+ c_1_3 = np.tile(np.arange(0, height)[:, np.newaxis, np.newaxis, np.newaxis], (1, width, A, 1))
141
+ all_anchors = np.concatenate([c_0_2, c_1_3, c_0_2, c_1_3], axis=-1) * stride + np.tile(base_anchors[np.newaxis, np.newaxis, :, :], (height, width, 1, 1))
142
+ return all_anchors
143
+
144
+ #this function is mainly based on the following code snippet: https://github.com/StanislasBertrand/RetinaFace-tf2/blob/master/rcnn/cython/cpu_nms.pyx
145
+ #Fast R-CNN by Ross Girshick
146
+ def cpu_nms(dets, threshold):
147
+ x1 = dets[:, 0]
148
+ y1 = dets[:, 1]
149
+ x2 = dets[:, 2]
150
+ y2 = dets[:, 3]
151
+ scores = dets[:, 4]
152
+
153
+ areas = (x2 - x1 + 1) * (y2 - y1 + 1)
154
+ order = scores.argsort()[::-1]
155
+
156
+ ndets = dets.shape[0]
157
+ suppressed = np.zeros((ndets), dtype=np.int)
158
+
159
+ keep = []
160
+ for _i in range(ndets):
161
+ i = order[_i]
162
+ if suppressed[i] == 1:
163
+ continue
164
+ keep.append(i)
165
+ ix1 = x1[i]; iy1 = y1[i]; ix2 = x2[i]; iy2 = y2[i]
166
+ iarea = areas[i]
167
+ for _j in range(_i + 1, ndets):
168
+ j = order[_j]
169
+ if suppressed[j] == 1:
170
+ continue
171
+ xx1 = max(ix1, x1[j]); yy1 = max(iy1, y1[j]); xx2 = min(ix2, x2[j]); yy2 = min(iy2, y2[j])
172
+ w = max(0.0, xx2 - xx1 + 1); h = max(0.0, yy2 - yy1 + 1)
173
+ inter = w * h
174
+ ovr = inter / (iarea + areas[j] - inter)
175
+ if ovr >= threshold:
176
+ suppressed[j] = 1
177
+
178
+ return keep