qc903113684 commited on
Commit
d6adcf8
·
verified ·
1 Parent(s): b3ed2d0

Delete examples

Browse files
examples/data/bus.jpg DELETED
Binary file (181 kB)
 
examples/python/qnn_yolov5_multi.py DELETED
@@ -1,350 +0,0 @@
1
- # import sys
2
- import os
3
- import time
4
-
5
- import aidlite
6
- import cv2
7
- import numpy as np
8
-
9
- OBJ_CLASS_NUM = 80
10
- NMS_THRESH = 0.45
11
- BOX_THRESH = 0.5
12
- MODEL_SIZE = 640
13
-
14
- OBJ_NUMB_MAX_SIZE = 64
15
- PROP_BOX_SIZE = (5 + OBJ_CLASS_NUM)
16
- STRIDE8_SIZE = (MODEL_SIZE / 8)
17
- STRIDE16_SIZE = (MODEL_SIZE / 16)
18
- STRIDE32_SIZE = (MODEL_SIZE / 32)
19
-
20
- anchors = [[10, 13, 16, 30, 33, 23],
21
- [30, 61, 62, 45, 59, 119],
22
- [116, 90, 156, 198, 373, 326]]
23
-
24
- coco_class = [
25
- 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
26
- 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant',
27
- 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
28
- 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle',
29
- 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli',
30
- 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet',
31
- 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator',
32
- 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']
33
-
34
-
35
- def eqprocess(image, size1, size2):
36
- h, w, _ = image.shape
37
- mask = np.zeros((size1, size2, 3), dtype=np.float32)
38
- scale1 = h / size1
39
- scale2 = w / size2
40
- if scale1 > scale2:
41
- scale = scale1
42
- else:
43
- scale = scale2
44
- img = cv2.resize(image, (int(w / scale), int(h / scale)))
45
- mask[:int(h / scale), :int(w / scale), :] = img
46
- return mask, scale
47
-
48
-
49
- def xywh2xyxy(x):
50
- '''
51
- Box (center x, center y, width, height) to (x1, y1, x2, y2)
52
- '''
53
- y = np.copy(x)
54
- y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
55
- y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
56
- y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
57
- y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
58
- return y
59
-
60
-
61
- def xyxy2xywh(box):
62
- '''
63
- Box (left_top x, left_top y, right_bottom x, right_bottom y) to (left_top x, left_top y, width, height)
64
- '''
65
- box[:, 2:] = box[:, 2:] - box[:, :2]
66
- return box
67
-
68
-
69
- def NMS(dets, scores, thresh):
70
- '''
71
- 单类NMS算法
72
- dets.shape = (N, 5), (left_top x, left_top y, right_bottom x, right_bottom y, Scores)
73
- '''
74
- x1 = dets[:, 0]
75
- y1 = dets[:, 1]
76
- x2 = dets[:, 2]
77
- y2 = dets[:, 3]
78
- areas = (y2 - y1 + 1) * (x2 - x1 + 1)
79
- keep = []
80
- index = scores.argsort()[::-1]
81
- while index.size > 0:
82
- i = index[0] # every time the first is the biggst, and add it directly
83
- keep.append(i)
84
- x11 = np.maximum(x1[i], x1[index[1:]]) # calculate the points of overlap
85
- y11 = np.maximum(y1[i], y1[index[1:]])
86
- x22 = np.minimum(x2[i], x2[index[1:]])
87
- y22 = np.minimum(y2[i], y2[index[1:]])
88
- w = np.maximum(0, x22 - x11 + 1) # the weights of overlap
89
- h = np.maximum(0, y22 - y11 + 1) # the height of overlap
90
- overlaps = w * h
91
- ious = overlaps / (areas[i] + areas[index[1:]] - overlaps)
92
- idx = np.where(ious <= thresh)[0]
93
- index = index[idx + 1] # because index start from 1
94
-
95
- return keep
96
-
97
-
98
- def clip_coords(boxes, img_shape):
99
- # Clip bounding xyxy bounding boxes to image shape (height, width)
100
- boxes[:, 0].clip(0, img_shape[1], out=boxes[:, 0]) # x1
101
- boxes[:, 1].clip(0, img_shape[0], out=boxes[:, 1]) # y1
102
- boxes[:, 2].clip(0, img_shape[1], out=boxes[:, 2]) # x2
103
- boxes[:, 3].clip(0, img_shape[0], out=boxes[:, 3]) # y2
104
-
105
-
106
- def detect_postprocess(prediction, img0shape, img1shape, conf_thres=0.25, iou_thres=0.45):
107
- '''
108
- 检测输出后处理
109
- prediction: aidlite模型预测输出
110
- img0shape: 原始图片shape
111
- img1shape: 输入图片shape
112
- conf_thres: 置信度阈值
113
- iou_thres: IOU阈值
114
- return: list[np.ndarray(N, 5)], 对应类别的坐标框信息, xywh、conf
115
- '''
116
- h, w, _ = img1shape
117
- valid_condidates = prediction[prediction[..., 4] > conf_thres]
118
- valid_condidates[:, 5:] *= valid_condidates[:, 4:5]
119
- valid_condidates[:, :4] = xywh2xyxy(valid_condidates[:, :4])
120
-
121
- max_det = 300
122
- max_wh = 7680
123
- max_nms = 30000
124
- valid_condidates[:, 4] = valid_condidates[:, 5:].max(1)
125
- valid_condidates[:, 5] = valid_condidates[:, 5:].argmax(1)
126
- sort_id = np.argsort(valid_condidates[:, 4])[::-1]
127
- valid_condidates = valid_condidates[sort_id[:max_nms]]
128
- boxes, scores = valid_condidates[:, :4] + valid_condidates[:, 5:6] * max_wh, valid_condidates[:, 4]
129
- index = NMS(boxes, scores, iou_thres)[:max_det]
130
- out_boxes = valid_condidates[index]
131
- clip_coords(out_boxes[:, :4], img0shape)
132
- out_boxes[:, :4] = xyxy2xywh(out_boxes[:, :4])
133
- print("检测到{}个区域".format(len(out_boxes)))
134
- return out_boxes
135
-
136
-
137
- def draw_detect_res(img, det_pred):
138
- '''
139
- 检测结果绘制
140
- '''
141
- img = img.astype(np.uint8)
142
- color_step = int(255 / len(coco_class))
143
- for i in range(len(det_pred)):
144
- x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
145
- score = det_pred[i][4]
146
- cls_id = int(det_pred[i][5])
147
-
148
- print(i + 1, [x1, y1, x2, y2], score, coco_class[cls_id])
149
-
150
- cv2.putText(img, f'{coco_class[cls_id]}', (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
151
- cv2.rectangle(img, (x1, y1), (x2 + x1, y2 + y1), (0, int(cls_id * color_step), int(255 - cls_id * color_step)),
152
- thickness=2)
153
-
154
- return img
155
-
156
-
157
- class Detect():
158
- # YOLOv5 Detect head for detection models
159
- def __init__(self, nc=80, anchors=(), stride=[], image_size=640): # detection layer
160
- super().__init__()
161
- self.nc = nc # number of classes
162
- self.no = nc + 5 # number of outputs per anchor
163
- self.stride = stride
164
- self.nl = len(anchors) # number of detection layers
165
- self.na = len(anchors[0]) // 2 # number of anchors
166
- self.grid, self.anchor_grid = [0] * self.nl, [0] * self.nl
167
- self.anchors = np.array(anchors, dtype=np.float32).reshape(self.nl, -1, 2)
168
-
169
- base_scale = image_size // 8
170
- for i in range(self.nl):
171
- self.grid[i], self.anchor_grid[i] = self._make_grid(base_scale // (2 ** i), base_scale // (2 ** i), i)
172
-
173
- def _make_grid(self, nx=20, ny=20, i=0):
174
- y, x = np.arange(ny, dtype=np.float32), np.arange(nx, dtype=np.float32)
175
- yv, xv = np.meshgrid(y, x)
176
- yv, xv = yv.T, xv.T
177
- # add grid offset, i.e. y = 2.0 * x - 0.5
178
- grid = np.stack((xv, yv), 2)
179
- grid = grid[np.newaxis, np.newaxis, ...]
180
- grid = np.repeat(grid, self.na, axis=1) - 0.5
181
- anchor_grid = self.anchors[i].reshape((1, self.na, 1, 1, 2))
182
- anchor_grid = np.repeat(anchor_grid, repeats=ny, axis=2)
183
- anchor_grid = np.repeat(anchor_grid, repeats=nx, axis=3)
184
- return grid, anchor_grid
185
-
186
- def sigmoid(self, arr):
187
- return 1 / (1 + np.exp(-arr))
188
-
189
- def __call__(self, x):
190
- z = [] # inference output
191
- for i in range(self.nl):
192
- bs, _, ny, nx = x[i].shape
193
- x[i] = x[i].reshape(bs, self.na, self.no, ny, nx).transpose(0, 1, 3, 4, 2)
194
- y = self.sigmoid(x[i])
195
- y[..., 0:2] = (y[..., 0:2] * 2. + self.grid[i]) * self.stride[i] # xy
196
- y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh
197
- z.append(y.reshape(bs, self.na * nx * ny, self.no))
198
-
199
- return np.concatenate(z, 1)
200
-
201
-
202
- def main():
203
- # argvs = len(sys.argv)
204
- # if argvs < 2:
205
- # print("python3 ./qnn_yolov5_multi.py 0 for use DSP")
206
- # print("python3 ./qnn_yolov5_multi.py 1 for use CPU")
207
- # print("python3 ./qnn_yolov5_multi.py 2 for use GPU")
208
- # return False
209
- # acc_type = int(sys.argv[1])
210
-
211
- print("Start main ... ...")
212
- aidlite.set_log_level(aidlite.LogLevel.INFO)
213
- aidlite.log_to_stderr()
214
- print(f"Aidlite library version : {aidlite.get_library_version()}")
215
- print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
216
-
217
- config = aidlite.Config.create_instance()
218
- if config is None:
219
- print("Create config failed !")
220
- return False
221
-
222
- # if acc_type == 1:
223
- # config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
224
- # elif acc_type == 2:
225
- # config.accelerate_type = aidlite.AccelerateType.TYPE_GPU
226
- # config.is_quantify_model = 0
227
- # elif acc_type == 0:
228
- # config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
229
- # config.is_quantify_model = 1
230
- # else:
231
- # print("python3 ./qnn_yolov5_multi.py 0 for use DSP")
232
- # print("python3 ./qnn_yolov5_multi.py 1 for use CPU")
233
- # print("python3 ./qnn_yolov5_multi.py 2 for use GPU")
234
- # return False
235
-
236
- config.implement_type = aidlite.ImplementType.TYPE_LOCAL
237
- config.framework_type = aidlite.FrameworkType.TYPE_QNN
238
- config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
239
- config.is_quantify_model = 1
240
-
241
- model_path = "/home/aidlux/modelzoo/examples/data/cutoff_yolov5s_int8_qnn/cutoff_yolov5s_int8.qnn.serialized.bin"
242
- model = aidlite.Model.create_instance(model_path)
243
- if model is None:
244
- print("Create model failed !")
245
- return False
246
- input_shapes = [[1, MODEL_SIZE, MODEL_SIZE, 3]]
247
- output_shapes = [[1, 20, 20, 255], [1, 40, 40, 255], [1, 80, 80, 255]]
248
- model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
249
- output_shapes, aidlite.DataType.TYPE_FLOAT32)
250
-
251
- interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
252
- if interpreter is None:
253
- print("build_interpretper_from_model_and_config failed !")
254
- return None
255
- result = interpreter.init()
256
- if result != 0:
257
- print(f"interpreter init failed !")
258
- return False
259
- result = interpreter.load_model()
260
- if result != 0:
261
- print("interpreter load model failed !")
262
- return False
263
- print("detect model load success!")
264
- stride8 = stride16 = stride32 = None
265
-
266
- image_path = os.path.join("../data/bus.jpg")
267
- frame = cv2.imread(image_path)
268
- frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
269
- img_input, scale = eqprocess(frame, MODEL_SIZE, MODEL_SIZE)
270
- img_input = img_input / 255
271
- img_input = img_input.astype(np.float32)
272
-
273
- sum_time_0 = 0.0
274
- sum_time_1 = 0.0
275
- sum_time_2 = 0.0
276
- _counter = 1
277
- for idx in range(_counter):
278
- st0 = time.time()
279
- input_tensor_data = img_input.data
280
- result = interpreter.set_input_tensor(0, input_tensor_data)
281
- if result != 0:
282
- print("interpreter set_input_tensor() failed")
283
- return False
284
- et0 = time.time()
285
- dur0 = (et0 - st0) * 1000
286
- sum_time_0 += dur0
287
- print(f"current [{idx}] set_input_tensor cost time :{dur0} ms")
288
-
289
- st1 = time.time()
290
- result = interpreter.invoke()
291
- if result != 0:
292
- print("interpreter set_input_tensor() failed")
293
- return False
294
- et1 = time.time()
295
- dur1 = (et1 - st1) * 1000
296
- sum_time_1 += dur1
297
- print(f"current [{idx}] invoke cost time :{dur1} ms")
298
-
299
- st2 = time.time()
300
-
301
- stride8 = interpreter.get_output_tensor(0)
302
- if stride8 is None:
303
- print("sample : interpreter->get_output_tensor() 0 failed !")
304
- return False
305
- print(f"len(stride8 {len(stride8)}")
306
-
307
- stride16 = interpreter.get_output_tensor(1)
308
- if stride16 is None:
309
- print("sample : interpreter->get_output_tensor() 2 failed !")
310
- return False
311
- print(f"len(stride16 {len(stride16)}")
312
-
313
- stride32 = interpreter.get_output_tensor(2)
314
- if stride32 is None:
315
- print("sample : interpreter->get_output_tensor() 1 failed !")
316
- return False
317
- print(f"len(stride32 {len(stride32)}")
318
- et2 = time.time()
319
- dur2 = (et2 - st2) * 1000
320
- sum_time_2 += dur2
321
- print(f"current [{idx}] get_output_tensor cost time :{dur2} ms")
322
-
323
- print(
324
- f"repeat [{_counter}] times , input[{sum_time_0 * 1000}]ms --- invoke[{sum_time_1 * 1000}]ms --- output[{sum_time_2 * 1000}]ms --- sum[{(sum_time_0 + sum_time_1 + sum_time_2) * 1000}]ms")
325
-
326
- stride = [8, 16, 32]
327
- yolo_head = Detect(OBJ_CLASS_NUM, anchors, stride, MODEL_SIZE)
328
- # 后处理部分reshape需要知道模型的output_shapes
329
- validCount0 = stride8.reshape(*output_shapes[2]).transpose(0, 3, 1, 2)
330
- validCount1 = stride16.reshape(*output_shapes[1]).transpose(0, 3, 1, 2)
331
- validCount2 = stride32.reshape(*output_shapes[0]).transpose(0, 3, 1, 2)
332
- pred = yolo_head([validCount0, validCount1, validCount2])
333
- det_pred = detect_postprocess(pred, frame.shape, [MODEL_SIZE, MODEL_SIZE, 3], conf_thres=0.5, iou_thres=0.45)
334
- det_pred[np.isnan(det_pred)] = 0.0
335
- det_pred[:, :4] = det_pred[:, :4] * scale
336
- res_img = draw_detect_res(frame, det_pred)
337
-
338
- result = interpreter.destory()
339
- if result != 0:
340
- print(f"interpreter set_input_tensor() failed")
341
- return False
342
- frame_bgr = cv2.cvtColor(res_img, cv2.COLOR_RGB2BGR)
343
- result_img_path = f"{os.path.splitext(os.path.abspath(__file__))[0]}.jpg"
344
- cv2.imwrite(result_img_path, frame_bgr)
345
- print(f"The result image has been saved to : {result_img_path}")
346
- return True
347
-
348
-
349
- if __name__ == "__main__":
350
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
examples/python/snpe2_yolov5_multi.py DELETED
@@ -1,338 +0,0 @@
1
- import os
2
- import struct
3
- import sys
4
- import time
5
-
6
- import aidlite
7
- import cv2
8
- import numpy as np
9
-
10
- FLOAT_SIZE = struct.calcsize('f')
11
- OBJ_CLASS_NUM = 80
12
- MODEL_SIZE = 640
13
- anchors = [[10, 13, 16, 30, 33, 23],
14
- [30, 61, 62, 45, 59, 119],
15
- [116, 90, 156, 198, 373, 326]]
16
-
17
- coco_class = [
18
- 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
19
- 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant',
20
- 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
21
- 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle',
22
- 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli',
23
- 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet',
24
- 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator',
25
- 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']
26
-
27
-
28
- def eqprocess(image, size1, size2):
29
- h, w, _ = image.shape
30
- mask = np.zeros((size1, size2, 3), dtype=np.float32)
31
- scale1 = h / size1
32
- scale2 = w / size2
33
- if scale1 > scale2:
34
- scale = scale1
35
- else:
36
- scale = scale2
37
- img = cv2.resize(image, (int(w / scale), int(h / scale)))
38
- mask[:int(h / scale), :int(w / scale), :] = img
39
- return mask, scale
40
-
41
-
42
- def xywh2xyxy(x):
43
- '''
44
- Box (center x, center y, width, height) to (x1, y1, x2, y2)
45
- '''
46
- y = np.copy(x)
47
- y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
48
- y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
49
- y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
50
- y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
51
- return y
52
-
53
-
54
- def xyxy2xywh(box):
55
- '''
56
- Box (left_top x, left_top y, right_bottom x, right_bottom y) to (left_top x, left_top y, width, height)
57
- '''
58
- box[:, 2:] = box[:, 2:] - box[:, :2]
59
- return box
60
-
61
-
62
- def NMS(dets, scores, thresh):
63
- '''
64
- 单类NMS算法
65
- dets.shape = (N, 5), (left_top x, left_top y, right_bottom x, right_bottom y, Scores)
66
- '''
67
- x1 = dets[:, 0]
68
- y1 = dets[:, 1]
69
- x2 = dets[:, 2]
70
- y2 = dets[:, 3]
71
- areas = (y2 - y1 + 1) * (x2 - x1 + 1)
72
- keep = []
73
- index = scores.argsort()[::-1]
74
- while index.size > 0:
75
- i = index[0] # every time the first is the biggst, and add it directly
76
- keep.append(i)
77
- x11 = np.maximum(x1[i], x1[index[1:]]) # calculate the points of overlap
78
- y11 = np.maximum(y1[i], y1[index[1:]])
79
- x22 = np.minimum(x2[i], x2[index[1:]])
80
- y22 = np.minimum(y2[i], y2[index[1:]])
81
- w = np.maximum(0, x22 - x11 + 1) # the weights of overlap
82
- h = np.maximum(0, y22 - y11 + 1) # the height of overlap
83
- overlaps = w * h
84
- ious = overlaps / (areas[i] + areas[index[1:]] - overlaps)
85
- idx = np.where(ious <= thresh)[0]
86
- index = index[idx + 1] # because index start from 1
87
-
88
- return keep
89
-
90
-
91
- def clip_coords(boxes, img_shape):
92
- # Clip bounding xyxy bounding boxes to image shape (height, width)
93
- boxes[:, 0].clip(0, img_shape[1], out=boxes[:, 0]) # x1
94
- boxes[:, 1].clip(0, img_shape[0], out=boxes[:, 1]) # y1
95
- boxes[:, 2].clip(0, img_shape[1], out=boxes[:, 2]) # x2
96
- boxes[:, 3].clip(0, img_shape[0], out=boxes[:, 3]) # y2
97
-
98
-
99
- def detect_postprocess(prediction, img0shape, img1shape, conf_thres=0.25, iou_thres=0.45):
100
- '''
101
- 检测输出后处理
102
- prediction: aidlite模型预测输出
103
- img0shape: 原始图片shape
104
- img1shape: 输入图片shape
105
- conf_thres: 置信度阈值
106
- iou_thres: IOU阈值
107
- return: list[np.ndarray(N, 5)], 对应类别的坐标框信息, xywh、conf
108
- '''
109
- h, w, _ = img1shape
110
- valid_condidates = prediction[prediction[..., 4] > conf_thres]
111
- valid_condidates[:, 5:] *= valid_condidates[:, 4:5]
112
- valid_condidates[:, :4] = xywh2xyxy(valid_condidates[:, :4])
113
-
114
- max_det = 300
115
- max_wh = 7680
116
- max_nms = 30000
117
- valid_condidates[:, 4] = valid_condidates[:, 5:].max(1)
118
- valid_condidates[:, 5] = valid_condidates[:, 5:].argmax(1)
119
- sort_id = np.argsort(valid_condidates[:, 4])[::-1]
120
- valid_condidates = valid_condidates[sort_id[:max_nms]]
121
- boxes, scores = valid_condidates[:, :4] + valid_condidates[:, 5:6] * max_wh, valid_condidates[:, 4]
122
- index = NMS(boxes, scores, iou_thres)[:max_det]
123
- out_boxes = valid_condidates[index]
124
- clip_coords(out_boxes[:, :4], img0shape)
125
- out_boxes[:, :4] = xyxy2xywh(out_boxes[:, :4])
126
- print("检测到{}个区域".format(len(out_boxes)))
127
- return out_boxes
128
-
129
-
130
- def draw_detect_res(img, det_pred):
131
- '''
132
- 检测结果绘制
133
- '''
134
- img = img.astype(np.uint8)
135
- color_step = int(255 / len(coco_class))
136
- for i in range(len(det_pred)):
137
- x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
138
- score = det_pred[i][4]
139
- cls_id = int(det_pred[i][5])
140
-
141
- print(i + 1, [x1, y1, x2, y2], score, coco_class[cls_id])
142
-
143
- cv2.putText(img, f'{coco_class[cls_id]}', (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
144
- cv2.rectangle(img, (x1, y1), (x2 + x1, y2 + y1), (0, int(cls_id * color_step), int(255 - cls_id * color_step)),
145
- thickness=2)
146
-
147
- return img
148
-
149
-
150
- class Detect():
151
- # YOLOv5 Detect head for detection models
152
- def __init__(self, nc=80, anchors=(), stride=[], image_size=640): # detection layer
153
- super().__init__()
154
- self.nc = nc # number of classes
155
- self.no = nc + 5 # number of outputs per anchor
156
- self.stride = stride
157
- self.nl = len(anchors) # number of detection layers
158
- self.na = len(anchors[0]) // 2 # number of anchors
159
- self.grid, self.anchor_grid = [0] * self.nl, [0] * self.nl
160
- self.anchors = np.array(anchors, dtype=np.float32).reshape(self.nl, -1, 2)
161
-
162
- base_scale = image_size // 8
163
- for i in range(self.nl):
164
- self.grid[i], self.anchor_grid[i] = self._make_grid(base_scale // (2 ** i), base_scale // (2 ** i), i)
165
-
166
- def _make_grid(self, nx=20, ny=20, i=0):
167
- y, x = np.arange(ny, dtype=np.float32), np.arange(nx, dtype=np.float32)
168
- yv, xv = np.meshgrid(y, x)
169
- yv, xv = yv.T, xv.T
170
- # add grid offset, i.e. y = 2.0 * x - 0.5
171
- grid = np.stack((xv, yv), 2)
172
- grid = grid[np.newaxis, np.newaxis, ...]
173
- grid = np.repeat(grid, self.na, axis=1) - 0.5
174
- anchor_grid = self.anchors[i].reshape((1, self.na, 1, 1, 2))
175
- anchor_grid = np.repeat(anchor_grid, repeats=ny, axis=2)
176
- anchor_grid = np.repeat(anchor_grid, repeats=nx, axis=3)
177
- return grid, anchor_grid
178
-
179
- def sigmoid(self, arr):
180
- return 1 / (1 + np.exp(-arr))
181
-
182
- def __call__(self, x):
183
- z = [] # inference output
184
- for i in range(self.nl):
185
- bs, _, ny, nx = x[i].shape
186
- x[i] = x[i].reshape(bs, self.na, self.no, ny, nx).transpose(0, 1, 3, 4, 2)
187
- y = self.sigmoid(x[i])
188
- y[..., 0:2] = (y[..., 0:2] * 2. + self.grid[i]) * self.stride[i] # xy
189
- y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i] # wh
190
- z.append(y.reshape(bs, self.na * nx * ny, self.no))
191
-
192
- return np.concatenate(z, 1)
193
-
194
-
195
- def main():
196
- acc_type = 0
197
- aidlite.set_log_level(aidlite.LogLevel.INFO)
198
- aidlite.log_to_stderr()
199
-
200
- # image process
201
- image_path = r"../data/bus.jpg"
202
- frame = cv2.imread(image_path)
203
- if frame is None:
204
- print(f"{image_path} not exists")
205
- return False
206
- frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
207
- img_input, scale = eqprocess(frame, MODEL_SIZE, MODEL_SIZE)
208
- img_input = img_input / 255
209
- img_input = img_input.astype(np.float32)
210
-
211
- config = aidlite.Config.create_instance()
212
- if config is None:
213
- print("build_interpretper_from_model_and_config failed !")
214
- return False
215
-
216
- # model init
217
- acc_type_dsp = True
218
- model_path = r"../data/cutoff_yolov5s_int8_htp_snpe2/cutoff_yolov5s_int8_htp_snpe2.dlc"
219
- outNode_names = "/model.24/m.1/Conv,/model.24/m.2/Conv,/model.24/m.0/Conv"
220
- config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
221
- config.is_quantify_model = 1
222
-
223
-
224
- config.implement_type = aidlite.ImplementType.TYPE_LOCAL
225
- config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
226
- config.snpe_out_names = outNode_names.split(',')
227
- print("---------------------------")
228
- print(config.snpe_out_names)
229
-
230
- model = aidlite.Model.create_instance(model_path)
231
- if model is None:
232
- print("Create model failed !")
233
- return False
234
-
235
- input_shapes = [[1, MODEL_SIZE, MODEL_SIZE, 3]]
236
- output_shapes = [[1, 40, 40, 255], [1, 20, 20, 255], [1, 80, 80, 255]]
237
- model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32, output_shapes,
238
- aidlite.DataType.TYPE_FLOAT32)
239
-
240
- snpe2_interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
241
- if snpe2_interpreter is None:
242
- print("build_interpretper_from_model_and_config failed !")
243
- return None
244
- result = snpe2_interpreter.init()
245
- if result != 0:
246
- print(f"interpreter init failed !")
247
- return False
248
- result = snpe2_interpreter.load_model()
249
- if result != 0:
250
- print("interpreter load model failed !")
251
- return False
252
- print("detect model load success!")
253
-
254
- stride8 = stride16 = stride32 = None
255
- sum_time_0 = 0.0
256
- sum_time_1 = 0.0
257
- sum_time_2 = 0.0
258
- _counter = 1
259
- for idx in range(_counter):
260
- st0 = time.time()
261
-
262
- if acc_type_dsp:
263
- time.sleep(0.04) # 40milliseconds
264
-
265
- input_tensor_data = img_input.data
266
- result = snpe2_interpreter.set_input_tensor(0, input_tensor_data)
267
- if result != 0:
268
- print("interpreter set_input_tensor() failed")
269
- return False
270
- et0 = time.time()
271
- dur0 = (et0 - st0) * 1000
272
- sum_time_0 += dur0
273
- print(f"current [{idx}] set_input_tensor cost time :{dur0} ms")
274
-
275
- st1 = time.time()
276
- result = snpe2_interpreter.invoke()
277
- if result != 0:
278
- print("interpreter set_input_tensor() failed")
279
- return False
280
- et1 = time.time()
281
- dur1 = (et1 - st1) * 1000
282
- sum_time_1 += dur1
283
- print(f"current [{idx}] invoke cost time :{dur1} ms")
284
-
285
- st2 = time.time()
286
-
287
- if acc_type_dsp:
288
- time.sleep(0.02) # 40milliseconds
289
-
290
- stride8 = snpe2_interpreter.get_output_tensor(0)
291
- if stride8 is None:
292
- print("sample : interpreter->get_output_tensor() 0 failed !")
293
- return False
294
- print(f"len(stride8 {len(stride8)}")
295
-
296
- stride16 = snpe2_interpreter.get_output_tensor(1)
297
- if stride16 is None:
298
- print("sample : interpreter->get_output_tensor() 2 failed !")
299
- return False
300
- print(f"len(stride16 {len(stride16)}")
301
-
302
- stride32 = snpe2_interpreter.get_output_tensor(2)
303
- if stride32 is None:
304
- print("sample : interpreter->get_output_tensor() 1 failed !")
305
- return False
306
- print(f"len(stride32 {len(stride32)}")
307
- et2 = time.time()
308
- dur2 = (et2 - st2) * 1000
309
- sum_time_2 += dur2
310
- print(f"current [{idx}] get_output_tensor cost time :{dur2} ms")
311
-
312
- print(
313
- f"repeat [{_counter}] time , input[{sum_time_0}]ms --- invoke[{sum_time_1}]ms --- output[{sum_time_2}]ms --- sum[{sum_time_0 + sum_time_1 + sum_time_2}]ms")
314
-
315
- stride = [8, 16, 32]
316
- yolo_head = Detect(OBJ_CLASS_NUM, anchors, stride, MODEL_SIZE)
317
- validCount0 = stride8.reshape(*output_shapes[2]).transpose(0, 3, 1, 2)
318
- validCount1 = stride16.reshape(*output_shapes[0]).transpose(0, 3, 1, 2)
319
- validCount2 = stride32.reshape(*output_shapes[1]).transpose(0, 3, 1, 2)
320
- pred = yolo_head([validCount0, validCount1, validCount2])
321
- det_pred = detect_postprocess(pred, frame.shape, [MODEL_SIZE, MODEL_SIZE, 3], conf_thres=0.5, iou_thres=0.45)
322
- det_pred[np.isnan(det_pred)] = 0.0
323
- det_pred[:, :4] = det_pred[:, :4] * scale
324
- res_img = draw_detect_res(frame, det_pred)
325
-
326
- result = snpe2_interpreter.destory()
327
- if result != 0:
328
- print(f"interpreter set_input_tensor() failed")
329
- return False
330
- frame_bgr = cv2.cvtColor(res_img, cv2.COLOR_RGB2BGR)
331
- result_img_path = f"{os.path.splitext(os.path.abspath(__file__))[0]}.jpg"
332
- cv2.imwrite(result_img_path, frame_bgr)
333
- print(f"The result image has been saved to : {result_img_path}")
334
- return True
335
-
336
-
337
- if __name__ == "__main__":
338
- main()