akhaliq HF staff commited on
Commit
b81df6d
1 Parent(s): c003417

Create helper.py

Browse files
Files changed (1) hide show
  1. helper.py +167 -0
helper.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ # coding: utf-8
4
+ # YuanYang
5
+ import math
6
+ import cv2
7
+ import numpy as np
8
+
9
+
10
+ def nms(boxes, overlap_threshold, mode='Union'):
11
+ """
12
+ non max suppression
13
+ Parameters:
14
+ ----------
15
+ box: numpy array n x 5
16
+ input bbox array
17
+ overlap_threshold: float number
18
+ threshold of overlap
19
+ mode: float number
20
+ how to compute overlap ratio, 'Union' or 'Min'
21
+ Returns:
22
+ -------
23
+ index array of the selected bbox
24
+ """
25
+ # if there are no boxes, return an empty list
26
+ if len(boxes) == 0:
27
+ return []
28
+
29
+ # if the bounding boxes integers, convert them to floats
30
+ if boxes.dtype.kind == "i":
31
+ boxes = boxes.astype("float")
32
+
33
+ # initialize the list of picked indexes
34
+ pick = []
35
+
36
+ # grab the coordinates of the bounding boxes
37
+ x1, y1, x2, y2, score = [boxes[:, i] for i in range(5)]
38
+
39
+ area = (x2 - x1 + 1) * (y2 - y1 + 1)
40
+ idxs = np.argsort(score)
41
+
42
+ # keep looping while some indexes still remain in the indexes list
43
+ while len(idxs) > 0:
44
+ # grab the last index in the indexes list and add the index value to the list of picked indexes
45
+ last = len(idxs) - 1
46
+ i = idxs[last]
47
+ pick.append(i)
48
+
49
+ xx1 = np.maximum(x1[i], x1[idxs[:last]])
50
+ yy1 = np.maximum(y1[i], y1[idxs[:last]])
51
+ xx2 = np.minimum(x2[i], x2[idxs[:last]])
52
+ yy2 = np.minimum(y2[i], y2[idxs[:last]])
53
+
54
+ # compute the width and height of the bounding box
55
+ w = np.maximum(0, xx2 - xx1 + 1)
56
+ h = np.maximum(0, yy2 - yy1 + 1)
57
+
58
+ inter = w * h
59
+ if mode == 'Min':
60
+ overlap = inter / np.minimum(area[i], area[idxs[:last]])
61
+ else:
62
+ overlap = inter / (area[i] + area[idxs[:last]] - inter)
63
+
64
+ # delete all indexes from the index list that have
65
+ idxs = np.delete(idxs, np.concatenate(([last],
66
+ np.where(overlap > overlap_threshold)[0])))
67
+
68
+ return pick
69
+
70
+ def adjust_input(in_data):
71
+ """
72
+ adjust the input from (h, w, c) to ( 1, c, h, w) for network input
73
+ Parameters:
74
+ ----------
75
+ in_data: numpy array of shape (h, w, c)
76
+ input data
77
+ Returns:
78
+ -------
79
+ out_data: numpy array of shape (1, c, h, w)
80
+ reshaped array
81
+ """
82
+ if in_data.dtype is not np.dtype('float32'):
83
+ out_data = in_data.astype(np.float32)
84
+ else:
85
+ out_data = in_data
86
+
87
+ out_data = out_data.transpose((2,0,1))
88
+ out_data = np.expand_dims(out_data, 0)
89
+ out_data = (out_data - 127.5)*0.0078125
90
+ return out_data
91
+
92
+ def generate_bbox(map, reg, scale, threshold):
93
+ """
94
+ generate bbox from feature map
95
+ Parameters:
96
+ ----------
97
+ map: numpy array , n x m x 1
98
+ detect score for each position
99
+ reg: numpy array , n x m x 4
100
+ bbox
101
+ scale: float number
102
+ scale of this detection
103
+ threshold: float number
104
+ detect threshold
105
+ Returns:
106
+ -------
107
+ bbox array
108
+ """
109
+ stride = 2
110
+ cellsize = 12
111
+
112
+ t_index = np.where(map>threshold)
113
+
114
+ # find nothing
115
+ if t_index[0].size == 0:
116
+ return np.array([])
117
+
118
+ dx1, dy1, dx2, dy2 = [reg[0, i, t_index[0], t_index[1]] for i in range(4)]
119
+
120
+ reg = np.array([dx1, dy1, dx2, dy2])
121
+ score = map[t_index[0], t_index[1]]
122
+ boundingbox = np.vstack([np.round((stride*t_index[1]+1)/scale),
123
+ np.round((stride*t_index[0]+1)/scale),
124
+ np.round((stride*t_index[1]+1+cellsize)/scale),
125
+ np.round((stride*t_index[0]+1+cellsize)/scale),
126
+ score,
127
+ reg])
128
+
129
+ return boundingbox.T
130
+
131
+
132
+ def detect_first_stage(img, net, scale, threshold):
133
+ """
134
+ run PNet for first stage
135
+ Parameters:
136
+ ----------
137
+ img: numpy array, bgr order
138
+ input image
139
+ scale: float number
140
+ how much should the input image scale
141
+ net: PNet
142
+ worker
143
+ Returns:
144
+ -------
145
+ total_boxes : bboxes
146
+ """
147
+ height, width, _ = img.shape
148
+ hs = int(math.ceil(height * scale))
149
+ ws = int(math.ceil(width * scale))
150
+
151
+ im_data = cv2.resize(img, (ws,hs))
152
+
153
+ # adjust for the network input
154
+ input_buf = adjust_input(im_data)
155
+ output = net.predict(input_buf)
156
+ boxes = generate_bbox(output[1][0,1,:,:], output[0], scale, threshold)
157
+
158
+ if boxes.size == 0:
159
+ return None
160
+
161
+ # nms
162
+ pick = nms(boxes[:,0:5], 0.5, mode='Union')
163
+ boxes = boxes[pick]
164
+ return boxes
165
+
166
+ def detect_first_stage_warpper( args ):
167
+ return detect_first_stage(*args)