qc903113684 commited on
Commit
a3bb7c2
·
verified ·
1 Parent(s): 17d5449

Upload 23 files

Browse files
Files changed (24) hide show
  1. .gitattributes +10 -0
  2. model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/README.md +43 -0
  3. model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/models/cutoff_yolov10x_w8a8.qnn231.ctx.bin.aidem +3 -0
  4. model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/models/post_pro.onnx +3 -0
  5. model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/python/bus.jpg +3 -0
  6. model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/README.md +52 -0
  7. model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem +3 -0
  8. model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/models/post_pro.onnx +3 -0
  9. model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/python/bus.jpg +3 -0
  10. model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/python/run_test.py +265 -0
  11. model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/README.md +52 -0
  12. model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/models/cutoff_yolov10x_fp16.qnn231.ctx.bin.aidem +3 -0
  13. model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/models/post_pro.onnx +3 -0
  14. model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/python/bus.jpg +3 -0
  15. model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/python/run_test.py +265 -0
  16. model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/README.md +43 -0
  17. model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/models/cutoff_yolov10x_w8a8.qnn231.ctx.bin.aidem +3 -0
  18. model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/models/post_pro.onnx +3 -0
  19. model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/python/bus.jpg +3 -0
  20. model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/README.md +52 -0
  21. model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem +3 -0
  22. model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/models/post_pro.onnx +3 -0
  23. model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/python/bus.jpg +3 -0
  24. model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/python/run_test.py +265 -0
.gitattributes CHANGED
@@ -33,3 +33,13 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/models/cutoff_yolov10x_w8a8.qnn231.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
37
+ model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
38
+ model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
39
+ model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
40
+ model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/models/cutoff_yolov10x_fp16.qnn231.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
41
+ model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
42
+ model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/models/cutoff_yolov10x_w8a8.qnn231.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
43
+ model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
44
+ model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
45
+ model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/README.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+
3
+ ### Source model
4
+ - Input shape: [1,3,640,640]
5
+ - Number of parameters: 30.34M
6
+ - Model size: 112.73M
7
+ - Output shape: [1,300,6]
8
+
9
+ Source model repository: [YOLOV10-x](https://github.com/THU-MIG/yolov10)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: INT8
14
+ - Backend: QNN2.31
15
+ - Target Device: FV01 QCS6490
16
+
17
+ ## Model Conversion Reference
18
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/4ded1198-4d50-4258-9043-67f419a405c2)
19
+
20
+ ## Inference with AidLite SDK
21
+
22
+ ### SDK installation
23
+ Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
24
+
25
+ - Install AidLite SDK
26
+
27
+ ```bash
28
+ # Install the appropriate version of the aidlite sdk
29
+ sudo aid-pkg update
30
+ sudo aid-pkg install aidlite-sdk
31
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
32
+ sudo aid-pkg install aidlite-{QNN VERSION}
33
+ ```
34
+
35
+ - Verify AidLite SDK
36
+
37
+ ```bash
38
+ # aidlite sdk c++ check
39
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
40
+
41
+ # aidlite sdk python check
42
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
43
+ ```
model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/models/cutoff_yolov10x_w8a8.qnn231.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:523288f964653fc5c3a746ea1bcd53d413a5bfda4747a7ae98578cd3b7dfe252
3
+ size 39444112
model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/models/post_pro.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ec661775a0a2bc3fac35bf15917f59d991b5b5131db57d855aa57a2543be6ca4
3
+ size 6852
model_farm_yolov10x_qcs6490_qnn2.31_int8_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+
3
+ ### Source model
4
+ - Input shape: [1,3,640,640]
5
+ - Number of parameters: 30.34M
6
+ - Model size: 112.73M
7
+ - Output shape: [1,300,6]
8
+
9
+ Source model repository: [YOLOV10-x](https://github.com/THU-MIG/yolov10)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: W8A16
14
+ - Backend: QNN2.31
15
+ - Target Device: FV01 QCS6490
16
+
17
+ ## Model Conversion Reference
18
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/95d04959-5545-4b82-ade8-f2df6036c803)
19
+
20
+ ## Inference with AidLite SDK
21
+
22
+ ### SDK installation
23
+ Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
24
+
25
+ - Install AidLite SDK
26
+
27
+ ```bash
28
+ # Install the appropriate version of the aidlite sdk
29
+ sudo aid-pkg update
30
+ sudo aid-pkg install aidlite-sdk
31
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
32
+ sudo aid-pkg install aidlite-{QNN VERSION}
33
+ ```
34
+
35
+ - Verify AidLite SDK
36
+
37
+ ```bash
38
+ # aidlite sdk c++ check
39
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
40
+
41
+ # aidlite sdk python check
42
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
43
+ ```
44
+
45
+ ### Run Demo
46
+
47
+ #### python
48
+ > Note: The ONNX model is used in the post-processing stage, and users' own models can also reuse this ONNX model.
49
+ ```bash
50
+ cd model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite
51
+ python3 python/run_test.py --target_model ./models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem --imgs ./python/bus.jpg --invoke_nums 10
52
+ ```
model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ca08d81f2f22bc217127b3e63c1d172d8f9f32b1aa3aa7435411722ab8da4e2e
3
+ size 41758512
model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/models/post_pro.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ec661775a0a2bc3fac35bf15917f59d991b5b5131db57d855aa57a2543be6ca4
3
+ size 6852
model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov10x_qcs6490_qnn2.31_w8a16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import numpy as np
3
+ import cv2
4
+ import os
5
+ import aidlite
6
+ import argparse
7
+ import onnxruntime
8
+
9
+
10
+
11
+ """返回 COCO 数据集的类别名称(80 类)。"""
12
+ classes=[
13
+ "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat",
14
+ "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
15
+ "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack",
16
+ "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball",
17
+ "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket",
18
+ "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
19
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair",
20
+ "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse",
21
+ "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator",
22
+ "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"
23
+ ]
24
+
25
+
26
+ def letterbox(
27
+ im,
28
+ new_shape,
29
+ color=(114, 114, 114),
30
+ auto=False,
31
+ scaleFill=False,
32
+ scaleup=True,
33
+ stride=32,
34
+ ):
35
+ """
36
+ Resize and pad image while meeting stride-multiple constraints
37
+ Returns:
38
+ im (array): (height, width, 3)
39
+ ratio (array): [w_ratio, h_ratio]
40
+ (dw, dh) (array): [w_padding h_padding]
41
+ """
42
+ shape = im.shape[:2] # current shape [height, width]
43
+ if isinstance(new_shape, int): # [h_rect, w_rect]
44
+ new_shape = (new_shape, new_shape)
45
+
46
+ # Scale ratio (new / old)
47
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
48
+ if not scaleup: # only scale down, do not scale up (for better val mAP)
49
+ r = min(r, 1.0)
50
+
51
+ # Compute padding
52
+ ratio = r, r # wh ratios
53
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) # w h
54
+ dw, dh = (
55
+ new_shape[1] - new_unpad[0],
56
+ new_shape[0] - new_unpad[1],
57
+ ) # wh padding
58
+
59
+ if auto: # minimum rectangle
60
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
61
+ elif scaleFill: # stretch
62
+ dw, dh = 0.0, 0.0
63
+ new_unpad = (new_shape[1], new_shape[0]) # [w h]
64
+ ratio = (
65
+ new_shape[1] / shape[1],
66
+ new_shape[0] / shape[0],
67
+ ) # [w_ratio, h_ratio]
68
+
69
+ dw /= 2 # divide padding into 2 sides
70
+ dh /= 2
71
+ if shape[::-1] != new_unpad: # resize
72
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
73
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
74
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
75
+ im = cv2.copyMakeBorder(
76
+ im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color
77
+ )
78
+ return im, ratio, (dw, dh)
79
+
80
+
81
+ class Colors:
82
+
83
+ def __init__(self):
84
+ hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
85
+ '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
86
+ self.palette = [self.hex2rgb(f'#{c}') for c in hexs]
87
+ self.n = len(self.palette)
88
+
89
+ def __call__(self, i, bgr=False):
90
+ c = self.palette[int(i) % self.n]
91
+ return (c[2], c[1], c[0]) if bgr else c
92
+
93
+ @staticmethod
94
+ def hex2rgb(h):
95
+ return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
96
+
97
+
98
+ def rescale_coords(boxes, image_shape, input_shape):
99
+ image_height, image_width = image_shape
100
+ input_height, input_width = input_shape
101
+ scale = min(input_width / image_width, input_height / image_height)
102
+ pad_w = (input_width - image_width * scale) / 2
103
+ pad_h = (input_height - image_height * scale) / 2
104
+ boxes[:, [0, 2]] = (boxes[:, [0, 2]] - pad_w) / scale
105
+ boxes[:, [1, 3]] = (boxes[:, [1, 3]] - pad_h) / scale
106
+ boxes[:, [0, 2]] = np.clip(boxes[:, [0, 2]], 0, image_width)
107
+ boxes[:, [1, 3]] = np.clip(boxes[:, [1, 3]], 0, image_height)
108
+ return boxes.astype(int)
109
+
110
+ def preprocess(image, input_shape):
111
+ # Resize
112
+ input_img = letterbox(image, input_shape)[0]
113
+ # Transpose
114
+ # input_img = input_img[..., ::-1].transpose(2, 0, 1)
115
+ input_img = input_img[..., ::-1]
116
+ # Expand
117
+ input_img = input_img[np.newaxis, :, :, :].astype(np.float32)
118
+ # Contiguous
119
+ input_img = np.ascontiguousarray(input_img)
120
+ # Norm
121
+ blob = input_img / 255.0
122
+ return blob
123
+
124
+ def postprocess(output_data, conf_thres, image_shape, input_shape):
125
+ outs = output_data # test.py 中 output_data 已经是 (8400, 84)
126
+ outs = outs[outs[:, 4] >= conf_thres]
127
+ boxes = outs[:, :4]
128
+ scores = outs[:, -2]
129
+ labels = outs[:, -1].astype(int)
130
+ boxes = rescale_coords(boxes, image_shape, input_shape)
131
+ return boxes, scores, labels
132
+
133
+ class qnn_yolov10:
134
+ def __init__(self,model_path,sdk="qnn",backend="npu"):
135
+ self.config = aidlite.Config.create_instance()
136
+ if self.config is None:
137
+ print("Create config failed !")
138
+ return False
139
+
140
+ self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
141
+ if sdk.lower()=="qnn":
142
+ self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
143
+ else :
144
+ self.config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
145
+
146
+
147
+ if backend.lower() =="npu":
148
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
149
+ elif backend.lower() =="gpu":
150
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_GPU
151
+ else:
152
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
153
+ self.config.is_quantify_model = 1
154
+
155
+ self.model = aidlite.Model.create_instance(model_path)
156
+ if self.model is None:
157
+ print("Create model failed !")
158
+ return False
159
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
160
+ if self.interpreter is None:
161
+ print("build_interpretper_from_model_and_config failed !")
162
+ return None
163
+ result = self.interpreter.init()
164
+ if result != 0:
165
+ print(f"interpreter init failed !")
166
+ return False
167
+ result = self.interpreter.load_model()
168
+ if result != 0:
169
+ print("interpreter load model failed !")
170
+ return False
171
+ print("detect model load success!")
172
+
173
+ def __del__(self):
174
+ self.interpreter.destory()
175
+
176
+ def __call__(self, img_input,invoke_nums):
177
+ result = self.interpreter.set_input_tensor(0, img_input.data)
178
+ if result != 0:
179
+ print("interpreter set_input_tensor() failed")
180
+ invoke_time=[]
181
+ for i in range(invoke_nums):
182
+ t1=time.time()
183
+ result = self.interpreter.invoke()
184
+ if result != 0:
185
+ print("interpreter set_input_tensor() failed")
186
+ cost_time = (time.time()-t1)*1000
187
+ invoke_time.append(cost_time)
188
+
189
+ max_invoke_time = max(invoke_time)
190
+ min_invoke_time = min(invoke_time)
191
+ mean_invoke_time = sum(invoke_time)/invoke_nums
192
+ var_invoketime=np.var(invoke_time)
193
+ print("====================================")
194
+ print(f"QNN invoke {invoke_nums} times:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
195
+ print("====================================")
196
+
197
+ output1 = self.interpreter.get_output_tensor(0)
198
+ return output1
199
+
200
+
201
+ class onnx_yolov10:
202
+ def __init__(self,model_path):
203
+ self.sess_options = onnxruntime.SessionOptions()
204
+ self.sess_options.intra_op_num_threads = 1
205
+ self.sess = onnxruntime.InferenceSession(model_path,sess_options=self.sess_options)
206
+ self.outname = [i.name for i in self.sess.get_outputs()]
207
+ self.inname = [i.name for i in self.sess.get_inputs()]
208
+ def __call__(self,img_input):
209
+ inp = {self.inname[0]:img_input}
210
+ t1=time.time()
211
+ out_put = self.sess.run(self.outname,inp)[0]
212
+ cost_time = (time.time()-t1)*1000
213
+ return out_put
214
+
215
+
216
+ def main(args):
217
+ input_shape = (640, 640)
218
+ conf_thres = 0.25
219
+ img_path = args.imgs
220
+ invoke_nums = args.invoke_nums
221
+ qnn_path = args.target_model
222
+
223
+ # qnn +onnx推理
224
+ qnn_model1 = qnn_yolov10(qnn_path)
225
+
226
+ onnx_model_path = 'models/post_pro.onnx'
227
+ onnx_model = onnx_yolov10(onnx_model_path)
228
+
229
+ print("Begin to run qnn...")
230
+ im0 = cv2.imread(img_path)
231
+ image_shape = im0.shape[:2]
232
+ img_qnn = preprocess(im0, input_shape)
233
+ qnn_out_shape = (1,8400,84)
234
+ out1 = qnn_model1(img_qnn,invoke_nums)
235
+ out1 = out1.reshape(*qnn_out_shape)
236
+ out2 = onnx_model(out1)[0]
237
+
238
+ boxes, scores, labels = postprocess(out2, conf_thres, image_shape, input_shape)
239
+ print(f"Detect {len(boxes)} targets")
240
+
241
+ colors = Colors()
242
+ for label, score, box in zip(labels, scores, boxes):
243
+ label_text = f'{classes[label]}: {score:.2f}'
244
+ color = colors(label, True)
245
+ cv2.rectangle(im0, (box[0], box[1]), (box[2], box[3]), color, 2, lineType=cv2.LINE_AA)
246
+ cv2.putText(im0, label_text, (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
247
+
248
+ output_image_path = "python/detected_results.jpg"
249
+ cv2.imwrite(output_image_path, im0)
250
+ print(f"Saved detected result to {output_image_path}")
251
+
252
+
253
+
254
+ def parser_args():
255
+ parser = argparse.ArgumentParser(description="Inferrence yolov10 model")
256
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem',help="Predict images path")
257
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
258
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
259
+ args = parser.parse_args()
260
+ return args
261
+
262
+
263
+ if __name__ == "__main__":
264
+ args = parser_args()
265
+ main(args)
model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+
3
+ ### Source model
4
+ - Input shape: [1,3,640,640]
5
+ - Number of parameters: 30.34M
6
+ - Model size: 112.73M
7
+ - Output shape: [1,300,6]
8
+
9
+ Source model repository: [YOLOV10-x](https://github.com/THU-MIG/yolov10)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: FP16
14
+ - Backend: QNN2.31
15
+ - Target Device: SNM972 QCS8550
16
+
17
+ ## Model Conversion Reference
18
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/47ed290a-394b-4b75-8d25-5fa2058c6c48)
19
+
20
+ ## Inference with AidLite SDK
21
+
22
+ ### SDK installation
23
+ Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
24
+
25
+ - Install AidLite SDK
26
+
27
+ ```bash
28
+ # Install the appropriate version of the aidlite sdk
29
+ sudo aid-pkg update
30
+ sudo aid-pkg install aidlite-sdk
31
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
32
+ sudo aid-pkg install aidlite-{QNN VERSION}
33
+ ```
34
+
35
+ - Verify AidLite SDK
36
+
37
+ ```bash
38
+ # aidlite sdk c++ check
39
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
40
+
41
+ # aidlite sdk python check
42
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
43
+ ```
44
+
45
+ ### Run Demo
46
+
47
+ #### python
48
+ > Note: The ONNX model is used in the post-processing stage, and users' own models can also reuse this ONNX model.
49
+ ```bash
50
+ cd model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite
51
+ python3 python/run_test.py --target_model ./models/cutoff_yolov10x_fp16.qnn231.ctx.bin.aidem --imgs ./python/bus.jpg --invoke_nums 10
52
+ ```
model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/models/cutoff_yolov10x_fp16.qnn231.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8836d18c61f2cab14af28101c2f94ce24d992d54e65a731fdc61320c85bdd6fa
3
+ size 66702968
model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/models/post_pro.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ec661775a0a2bc3fac35bf15917f59d991b5b5131db57d855aa57a2543be6ca4
3
+ size 6852
model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov10x_qcs8550_qnn2.31_fp16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import numpy as np
3
+ import cv2
4
+ import os
5
+ import aidlite
6
+ import argparse
7
+ import onnxruntime
8
+
9
+
10
+
11
+ """返回 COCO 数据集的类别名称(80 类)。"""
12
+ classes=[
13
+ "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat",
14
+ "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
15
+ "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack",
16
+ "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball",
17
+ "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket",
18
+ "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
19
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair",
20
+ "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse",
21
+ "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator",
22
+ "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"
23
+ ]
24
+
25
+
26
+ def letterbox(
27
+ im,
28
+ new_shape,
29
+ color=(114, 114, 114),
30
+ auto=False,
31
+ scaleFill=False,
32
+ scaleup=True,
33
+ stride=32,
34
+ ):
35
+ """
36
+ Resize and pad image while meeting stride-multiple constraints
37
+ Returns:
38
+ im (array): (height, width, 3)
39
+ ratio (array): [w_ratio, h_ratio]
40
+ (dw, dh) (array): [w_padding h_padding]
41
+ """
42
+ shape = im.shape[:2] # current shape [height, width]
43
+ if isinstance(new_shape, int): # [h_rect, w_rect]
44
+ new_shape = (new_shape, new_shape)
45
+
46
+ # Scale ratio (new / old)
47
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
48
+ if not scaleup: # only scale down, do not scale up (for better val mAP)
49
+ r = min(r, 1.0)
50
+
51
+ # Compute padding
52
+ ratio = r, r # wh ratios
53
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) # w h
54
+ dw, dh = (
55
+ new_shape[1] - new_unpad[0],
56
+ new_shape[0] - new_unpad[1],
57
+ ) # wh padding
58
+
59
+ if auto: # minimum rectangle
60
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
61
+ elif scaleFill: # stretch
62
+ dw, dh = 0.0, 0.0
63
+ new_unpad = (new_shape[1], new_shape[0]) # [w h]
64
+ ratio = (
65
+ new_shape[1] / shape[1],
66
+ new_shape[0] / shape[0],
67
+ ) # [w_ratio, h_ratio]
68
+
69
+ dw /= 2 # divide padding into 2 sides
70
+ dh /= 2
71
+ if shape[::-1] != new_unpad: # resize
72
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
73
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
74
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
75
+ im = cv2.copyMakeBorder(
76
+ im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color
77
+ )
78
+ return im, ratio, (dw, dh)
79
+
80
+
81
+ class Colors:
82
+
83
+ def __init__(self):
84
+ hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
85
+ '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
86
+ self.palette = [self.hex2rgb(f'#{c}') for c in hexs]
87
+ self.n = len(self.palette)
88
+
89
+ def __call__(self, i, bgr=False):
90
+ c = self.palette[int(i) % self.n]
91
+ return (c[2], c[1], c[0]) if bgr else c
92
+
93
+ @staticmethod
94
+ def hex2rgb(h):
95
+ return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
96
+
97
+
98
+ def rescale_coords(boxes, image_shape, input_shape):
99
+ image_height, image_width = image_shape
100
+ input_height, input_width = input_shape
101
+ scale = min(input_width / image_width, input_height / image_height)
102
+ pad_w = (input_width - image_width * scale) / 2
103
+ pad_h = (input_height - image_height * scale) / 2
104
+ boxes[:, [0, 2]] = (boxes[:, [0, 2]] - pad_w) / scale
105
+ boxes[:, [1, 3]] = (boxes[:, [1, 3]] - pad_h) / scale
106
+ boxes[:, [0, 2]] = np.clip(boxes[:, [0, 2]], 0, image_width)
107
+ boxes[:, [1, 3]] = np.clip(boxes[:, [1, 3]], 0, image_height)
108
+ return boxes.astype(int)
109
+
110
+ def preprocess(image, input_shape):
111
+ # Resize
112
+ input_img = letterbox(image, input_shape)[0]
113
+ # Transpose
114
+ # input_img = input_img[..., ::-1].transpose(2, 0, 1)
115
+ input_img = input_img[..., ::-1]
116
+ # Expand
117
+ input_img = input_img[np.newaxis, :, :, :].astype(np.float32)
118
+ # Contiguous
119
+ input_img = np.ascontiguousarray(input_img)
120
+ # Norm
121
+ blob = input_img / 255.0
122
+ return blob
123
+
124
+ def postprocess(output_data, conf_thres, image_shape, input_shape):
125
+ outs = output_data # test.py 中 output_data 已经是 (8400, 84)
126
+ outs = outs[outs[:, 4] >= conf_thres]
127
+ boxes = outs[:, :4]
128
+ scores = outs[:, -2]
129
+ labels = outs[:, -1].astype(int)
130
+ boxes = rescale_coords(boxes, image_shape, input_shape)
131
+ return boxes, scores, labels
132
+
133
+ class qnn_yolov10:
134
+ def __init__(self,model_path,sdk="qnn",backend="npu"):
135
+ self.config = aidlite.Config.create_instance()
136
+ if self.config is None:
137
+ print("Create config failed !")
138
+ return False
139
+
140
+ self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
141
+ if sdk.lower()=="qnn":
142
+ self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
143
+ else :
144
+ self.config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
145
+
146
+
147
+ if backend.lower() =="npu":
148
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
149
+ elif backend.lower() =="gpu":
150
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_GPU
151
+ else:
152
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
153
+ self.config.is_quantify_model = 1
154
+
155
+ self.model = aidlite.Model.create_instance(model_path)
156
+ if self.model is None:
157
+ print("Create model failed !")
158
+ return False
159
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
160
+ if self.interpreter is None:
161
+ print("build_interpretper_from_model_and_config failed !")
162
+ return None
163
+ result = self.interpreter.init()
164
+ if result != 0:
165
+ print(f"interpreter init failed !")
166
+ return False
167
+ result = self.interpreter.load_model()
168
+ if result != 0:
169
+ print("interpreter load model failed !")
170
+ return False
171
+ print("detect model load success!")
172
+
173
+ def __del__(self):
174
+ self.interpreter.destory()
175
+
176
+ def __call__(self, img_input,invoke_nums):
177
+ result = self.interpreter.set_input_tensor(0, img_input.data)
178
+ if result != 0:
179
+ print("interpreter set_input_tensor() failed")
180
+ invoke_time=[]
181
+ for i in range(invoke_nums):
182
+ t1=time.time()
183
+ result = self.interpreter.invoke()
184
+ if result != 0:
185
+ print("interpreter set_input_tensor() failed")
186
+ cost_time = (time.time()-t1)*1000
187
+ invoke_time.append(cost_time)
188
+
189
+ max_invoke_time = max(invoke_time)
190
+ min_invoke_time = min(invoke_time)
191
+ mean_invoke_time = sum(invoke_time)/invoke_nums
192
+ var_invoketime=np.var(invoke_time)
193
+ print("====================================")
194
+ print(f"QNN invoke {invoke_nums} times:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
195
+ print("====================================")
196
+
197
+ output1 = self.interpreter.get_output_tensor(0)
198
+ return output1
199
+
200
+
201
+ class onnx_yolov10:
202
+ def __init__(self,model_path):
203
+ self.sess_options = onnxruntime.SessionOptions()
204
+ self.sess_options.intra_op_num_threads = 1
205
+ self.sess = onnxruntime.InferenceSession(model_path,sess_options=self.sess_options)
206
+ self.outname = [i.name for i in self.sess.get_outputs()]
207
+ self.inname = [i.name for i in self.sess.get_inputs()]
208
+ def __call__(self,img_input):
209
+ inp = {self.inname[0]:img_input}
210
+ t1=time.time()
211
+ out_put = self.sess.run(self.outname,inp)[0]
212
+ cost_time = (time.time()-t1)*1000
213
+ return out_put
214
+
215
+
216
+ def main(args):
217
+ input_shape = (640, 640)
218
+ conf_thres = 0.25
219
+ img_path = args.imgs
220
+ invoke_nums = args.invoke_nums
221
+ qnn_path = args.target_model
222
+
223
+ # qnn +onnx推理
224
+ qnn_model1 = qnn_yolov10(qnn_path)
225
+
226
+ onnx_model_path = 'models/post_pro.onnx'
227
+ onnx_model = onnx_yolov10(onnx_model_path)
228
+
229
+ print("Begin to run qnn...")
230
+ im0 = cv2.imread(img_path)
231
+ image_shape = im0.shape[:2]
232
+ img_qnn = preprocess(im0, input_shape)
233
+ qnn_out_shape = (1,8400,84)
234
+ out1 = qnn_model1(img_qnn,invoke_nums)
235
+ out1 = out1.reshape(*qnn_out_shape)
236
+ out2 = onnx_model(out1)[0]
237
+
238
+ boxes, scores, labels = postprocess(out2, conf_thres, image_shape, input_shape)
239
+ print(f"Detect {len(boxes)} targets")
240
+
241
+ colors = Colors()
242
+ for label, score, box in zip(labels, scores, boxes):
243
+ label_text = f'{classes[label]}: {score:.2f}'
244
+ color = colors(label, True)
245
+ cv2.rectangle(im0, (box[0], box[1]), (box[2], box[3]), color, 2, lineType=cv2.LINE_AA)
246
+ cv2.putText(im0, label_text, (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
247
+
248
+ output_image_path = "python/detected_results.jpg"
249
+ cv2.imwrite(output_image_path, im0)
250
+ print(f"Saved detected result to {output_image_path}")
251
+
252
+
253
+
254
+ def parser_args():
255
+ parser = argparse.ArgumentParser(description="Inferrence yolov10 model")
256
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov10x_fp16.qnn231.ctx.bin.aidem',help="Predict images path")
257
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
258
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
259
+ args = parser.parse_args()
260
+ return args
261
+
262
+
263
+ if __name__ == "__main__":
264
+ args = parser_args()
265
+ main(args)
model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/README.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+
3
+ ### Source model
4
+ - Input shape: [1,3,640,640]
5
+ - Number of parameters: 30.34M
6
+ - Model size: 112.73M
7
+ - Output shape: [1,300,6]
8
+
9
+ Source model repository: [YOLOV10-x](https://github.com/THU-MIG/yolov10)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: INT8
14
+ - Backend: QNN2.31
15
+ - Target Device: SNM972 QCS8550
16
+
17
+ ## Model Conversion Reference
18
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/7f3bee49-98bb-4d48-8635-3ed4c9c2bfc5)
19
+
20
+ ## Inference with AidLite SDK
21
+
22
+ ### SDK installation
23
+ Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
24
+
25
+ - Install AidLite SDK
26
+
27
+ ```bash
28
+ # Install the appropriate version of the aidlite sdk
29
+ sudo aid-pkg update
30
+ sudo aid-pkg install aidlite-sdk
31
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
32
+ sudo aid-pkg install aidlite-{QNN VERSION}
33
+ ```
34
+
35
+ - Verify AidLite SDK
36
+
37
+ ```bash
38
+ # aidlite sdk c++ check
39
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
40
+
41
+ # aidlite sdk python check
42
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
43
+ ```
model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/models/cutoff_yolov10x_w8a8.qnn231.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fc0fa58b00cb3a30938da11fc333d22919725cb9e610d697f69a14f512448788
3
+ size 32595600
model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/models/post_pro.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ec661775a0a2bc3fac35bf15917f59d991b5b5131db57d855aa57a2543be6ca4
3
+ size 6852
model_farm_yolov10x_qcs8550_qnn2.31_int8_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+
3
+ ### Source model
4
+ - Input shape: [1,3,640,640]
5
+ - Number of parameters: 30.34M
6
+ - Model size: 112.73M
7
+ - Output shape: [1,300,6]
8
+
9
+ Source model repository: [YOLOV10-x](https://github.com/THU-MIG/yolov10)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: W8A16
14
+ - Backend: QNN2.31
15
+ - Target Device: SNM972 QCS8550
16
+
17
+ ## Model Conversion Reference
18
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/bde0409b-1fed-4ea8-8019-104ccfbb511a)
19
+
20
+ ## Inference with AidLite SDK
21
+
22
+ ### SDK installation
23
+ Model Farm uses AidLite SDK as the model inference SDK. For details, please refer to the [AidLite Developer Documentation](https://v2.docs.aidlux.com/en/sdk-api/aidlite-sdk/)
24
+
25
+ - Install AidLite SDK
26
+
27
+ ```bash
28
+ # Install the appropriate version of the aidlite sdk
29
+ sudo aid-pkg update
30
+ sudo aid-pkg install aidlite-sdk
31
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
32
+ sudo aid-pkg install aidlite-{QNN VERSION}
33
+ ```
34
+
35
+ - Verify AidLite SDK
36
+
37
+ ```bash
38
+ # aidlite sdk c++ check
39
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
40
+
41
+ # aidlite sdk python check
42
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
43
+ ```
44
+
45
+ ### Run Demo
46
+
47
+ #### python
48
+ > Note: The ONNX model is used in the post-processing stage, and users' own models can also reuse this ONNX model.
49
+ ```bash
50
+ cd model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite
51
+ python3 python/run_test.py --target_model ./models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem --imgs ./python/bus.jpg --invoke_nums 10
52
+ ```
model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a002623e82d54abbd1a80627fd96104aa4e487548785bc2f46676ee910932ff3
3
+ size 34209584
model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/models/post_pro.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ec661775a0a2bc3fac35bf15917f59d991b5b5131db57d855aa57a2543be6ca4
3
+ size 6852
model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov10x_qcs8550_qnn2.31_w8a16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import numpy as np
3
+ import cv2
4
+ import os
5
+ import aidlite
6
+ import argparse
7
+ import onnxruntime
8
+
9
+
10
+
11
+ """返回 COCO 数据集的类别名称(80 类)。"""
12
+ classes=[
13
+ "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", "boat",
14
+ "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
15
+ "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack",
16
+ "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball",
17
+ "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket",
18
+ "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
19
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair",
20
+ "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse",
21
+ "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator",
22
+ "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"
23
+ ]
24
+
25
+
26
+ def letterbox(
27
+ im,
28
+ new_shape,
29
+ color=(114, 114, 114),
30
+ auto=False,
31
+ scaleFill=False,
32
+ scaleup=True,
33
+ stride=32,
34
+ ):
35
+ """
36
+ Resize and pad image while meeting stride-multiple constraints
37
+ Returns:
38
+ im (array): (height, width, 3)
39
+ ratio (array): [w_ratio, h_ratio]
40
+ (dw, dh) (array): [w_padding h_padding]
41
+ """
42
+ shape = im.shape[:2] # current shape [height, width]
43
+ if isinstance(new_shape, int): # [h_rect, w_rect]
44
+ new_shape = (new_shape, new_shape)
45
+
46
+ # Scale ratio (new / old)
47
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
48
+ if not scaleup: # only scale down, do not scale up (for better val mAP)
49
+ r = min(r, 1.0)
50
+
51
+ # Compute padding
52
+ ratio = r, r # wh ratios
53
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) # w h
54
+ dw, dh = (
55
+ new_shape[1] - new_unpad[0],
56
+ new_shape[0] - new_unpad[1],
57
+ ) # wh padding
58
+
59
+ if auto: # minimum rectangle
60
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
61
+ elif scaleFill: # stretch
62
+ dw, dh = 0.0, 0.0
63
+ new_unpad = (new_shape[1], new_shape[0]) # [w h]
64
+ ratio = (
65
+ new_shape[1] / shape[1],
66
+ new_shape[0] / shape[0],
67
+ ) # [w_ratio, h_ratio]
68
+
69
+ dw /= 2 # divide padding into 2 sides
70
+ dh /= 2
71
+ if shape[::-1] != new_unpad: # resize
72
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
73
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
74
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
75
+ im = cv2.copyMakeBorder(
76
+ im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color
77
+ )
78
+ return im, ratio, (dw, dh)
79
+
80
+
81
+ class Colors:
82
+
83
+ def __init__(self):
84
+ hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
85
+ '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
86
+ self.palette = [self.hex2rgb(f'#{c}') for c in hexs]
87
+ self.n = len(self.palette)
88
+
89
+ def __call__(self, i, bgr=False):
90
+ c = self.palette[int(i) % self.n]
91
+ return (c[2], c[1], c[0]) if bgr else c
92
+
93
+ @staticmethod
94
+ def hex2rgb(h):
95
+ return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
96
+
97
+
98
+ def rescale_coords(boxes, image_shape, input_shape):
99
+ image_height, image_width = image_shape
100
+ input_height, input_width = input_shape
101
+ scale = min(input_width / image_width, input_height / image_height)
102
+ pad_w = (input_width - image_width * scale) / 2
103
+ pad_h = (input_height - image_height * scale) / 2
104
+ boxes[:, [0, 2]] = (boxes[:, [0, 2]] - pad_w) / scale
105
+ boxes[:, [1, 3]] = (boxes[:, [1, 3]] - pad_h) / scale
106
+ boxes[:, [0, 2]] = np.clip(boxes[:, [0, 2]], 0, image_width)
107
+ boxes[:, [1, 3]] = np.clip(boxes[:, [1, 3]], 0, image_height)
108
+ return boxes.astype(int)
109
+
110
+ def preprocess(image, input_shape):
111
+ # Resize
112
+ input_img = letterbox(image, input_shape)[0]
113
+ # Transpose
114
+ # input_img = input_img[..., ::-1].transpose(2, 0, 1)
115
+ input_img = input_img[..., ::-1]
116
+ # Expand
117
+ input_img = input_img[np.newaxis, :, :, :].astype(np.float32)
118
+ # Contiguous
119
+ input_img = np.ascontiguousarray(input_img)
120
+ # Norm
121
+ blob = input_img / 255.0
122
+ return blob
123
+
124
+ def postprocess(output_data, conf_thres, image_shape, input_shape):
125
+ outs = output_data # test.py 中 output_data 已经是 (8400, 84)
126
+ outs = outs[outs[:, 4] >= conf_thres]
127
+ boxes = outs[:, :4]
128
+ scores = outs[:, -2]
129
+ labels = outs[:, -1].astype(int)
130
+ boxes = rescale_coords(boxes, image_shape, input_shape)
131
+ return boxes, scores, labels
132
+
133
+ class qnn_yolov10:
134
+ def __init__(self,model_path,sdk="qnn",backend="npu"):
135
+ self.config = aidlite.Config.create_instance()
136
+ if self.config is None:
137
+ print("Create config failed !")
138
+ return False
139
+
140
+ self.config.implement_type = aidlite.ImplementType.TYPE_LOCAL
141
+ if sdk.lower()=="qnn":
142
+ self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
143
+ else :
144
+ self.config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
145
+
146
+
147
+ if backend.lower() =="npu":
148
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
149
+ elif backend.lower() =="gpu":
150
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_GPU
151
+ else:
152
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_CPU
153
+ self.config.is_quantify_model = 1
154
+
155
+ self.model = aidlite.Model.create_instance(model_path)
156
+ if self.model is None:
157
+ print("Create model failed !")
158
+ return False
159
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
160
+ if self.interpreter is None:
161
+ print("build_interpretper_from_model_and_config failed !")
162
+ return None
163
+ result = self.interpreter.init()
164
+ if result != 0:
165
+ print(f"interpreter init failed !")
166
+ return False
167
+ result = self.interpreter.load_model()
168
+ if result != 0:
169
+ print("interpreter load model failed !")
170
+ return False
171
+ print("detect model load success!")
172
+
173
+ def __del__(self):
174
+ self.interpreter.destory()
175
+
176
+ def __call__(self, img_input,invoke_nums):
177
+ result = self.interpreter.set_input_tensor(0, img_input.data)
178
+ if result != 0:
179
+ print("interpreter set_input_tensor() failed")
180
+ invoke_time=[]
181
+ for i in range(invoke_nums):
182
+ t1=time.time()
183
+ result = self.interpreter.invoke()
184
+ if result != 0:
185
+ print("interpreter set_input_tensor() failed")
186
+ cost_time = (time.time()-t1)*1000
187
+ invoke_time.append(cost_time)
188
+
189
+ max_invoke_time = max(invoke_time)
190
+ min_invoke_time = min(invoke_time)
191
+ mean_invoke_time = sum(invoke_time)/invoke_nums
192
+ var_invoketime=np.var(invoke_time)
193
+ print("====================================")
194
+ print(f"QNN invoke {invoke_nums} times:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
195
+ print("====================================")
196
+
197
+ output1 = self.interpreter.get_output_tensor(0)
198
+ return output1
199
+
200
+
201
+ class onnx_yolov10:
202
+ def __init__(self,model_path):
203
+ self.sess_options = onnxruntime.SessionOptions()
204
+ self.sess_options.intra_op_num_threads = 1
205
+ self.sess = onnxruntime.InferenceSession(model_path,sess_options=self.sess_options)
206
+ self.outname = [i.name for i in self.sess.get_outputs()]
207
+ self.inname = [i.name for i in self.sess.get_inputs()]
208
+ def __call__(self,img_input):
209
+ inp = {self.inname[0]:img_input}
210
+ t1=time.time()
211
+ out_put = self.sess.run(self.outname,inp)[0]
212
+ cost_time = (time.time()-t1)*1000
213
+ return out_put
214
+
215
+
216
+ def main(args):
217
+ input_shape = (640, 640)
218
+ conf_thres = 0.25
219
+ img_path = args.imgs
220
+ invoke_nums = args.invoke_nums
221
+ qnn_path = args.target_model
222
+
223
+ # qnn +onnx推理
224
+ qnn_model1 = qnn_yolov10(qnn_path)
225
+
226
+ onnx_model_path = 'models/post_pro.onnx'
227
+ onnx_model = onnx_yolov10(onnx_model_path)
228
+
229
+ print("Begin to run qnn...")
230
+ im0 = cv2.imread(img_path)
231
+ image_shape = im0.shape[:2]
232
+ img_qnn = preprocess(im0, input_shape)
233
+ qnn_out_shape = (1,8400,84)
234
+ out1 = qnn_model1(img_qnn,invoke_nums)
235
+ out1 = out1.reshape(*qnn_out_shape)
236
+ out2 = onnx_model(out1)[0]
237
+
238
+ boxes, scores, labels = postprocess(out2, conf_thres, image_shape, input_shape)
239
+ print(f"Detect {len(boxes)} targets")
240
+
241
+ colors = Colors()
242
+ for label, score, box in zip(labels, scores, boxes):
243
+ label_text = f'{classes[label]}: {score:.2f}'
244
+ color = colors(label, True)
245
+ cv2.rectangle(im0, (box[0], box[1]), (box[2], box[3]), color, 2, lineType=cv2.LINE_AA)
246
+ cv2.putText(im0, label_text, (box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
247
+
248
+ output_image_path = "python/detected_results.jpg"
249
+ cv2.imwrite(output_image_path, im0)
250
+ print(f"Saved detected result to {output_image_path}")
251
+
252
+
253
+
254
+ def parser_args():
255
+ parser = argparse.ArgumentParser(description="Inferrence yolov10 model")
256
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov10x_w8a16.qnn231.ctx.bin.aidem',help="Predict images path")
257
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
258
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
259
+ args = parser.parse_args()
260
+ return args
261
+
262
+
263
+ if __name__ == "__main__":
264
+ args = parser_args()
265
+ main(args)