qc903113684 commited on
Commit
806da53
·
verified ·
1 Parent(s): e2f17fd

Upload 32 files

Browse files
Files changed (33) hide show
  1. .gitattributes +12 -0
  2. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/README.md +58 -0
  3. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp/CMakeLists.txt +30 -0
  4. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp/main.cpp +370 -0
  5. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp/test.png +3 -0
  6. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem +3 -0
  7. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/python/run_test.py +147 -0
  8. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/python/test.png +3 -0
  9. model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/python/utils.py +160 -0
  10. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/README.md +58 -0
  11. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp/CMakeLists.txt +30 -0
  12. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp/main.cpp +370 -0
  13. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp/test.png +3 -0
  14. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/models/cutoff_yolov6m_fp16.qnn223.ctx.bin.aidem +3 -0
  15. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/python/run_test.py +147 -0
  16. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/python/test.png +3 -0
  17. model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/python/utils.py +160 -0
  18. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/README.md +58 -0
  19. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp/CMakeLists.txt +30 -0
  20. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp/main.cpp +370 -0
  21. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp/test.png +3 -0
  22. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem +3 -0
  23. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/python/run_test.py +147 -0
  24. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/python/test.png +3 -0
  25. model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/python/utils.py +160 -0
  26. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/README.md +58 -0
  27. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp/CMakeLists.txt +30 -0
  28. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp/main.cpp +370 -0
  29. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp/test.png +3 -0
  30. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/models/cutoff_yolov6m_w8a16.qnn223.ctx.bin.aidem +3 -0
  31. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/python/run_test.py +147 -0
  32. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/python/test.png +3 -0
  33. model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/python/utils.py +160 -0
.gitattributes CHANGED
@@ -33,3 +33,15 @@ 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_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp/test.png filter=lfs diff=lfs merge=lfs -text
37
+ model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
38
+ model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/python/test.png filter=lfs diff=lfs merge=lfs -text
39
+ model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp/test.png filter=lfs diff=lfs merge=lfs -text
40
+ model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/models/cutoff_yolov6m_fp16.qnn223.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
41
+ model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/python/test.png filter=lfs diff=lfs merge=lfs -text
42
+ model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp/test.png filter=lfs diff=lfs merge=lfs -text
43
+ model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
44
+ model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/python/test.png filter=lfs diff=lfs merge=lfs -text
45
+ model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp/test.png filter=lfs diff=lfs merge=lfs -text
46
+ model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/models/cutoff_yolov6m_w8a16.qnn223.ctx.bin.aidem filter=lfs diff=lfs merge=lfs -text
47
+ model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/python/test.png filter=lfs diff=lfs merge=lfs -text
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ### Source model
3
+
4
+ - Input shape: 1x3x640x640
5
+ - Number of parameters: 33.24M
6
+ - Model size: 133.20MB
7
+ - Output shape: 1x8400x85
8
+
9
+ Source model repository: [yolov6](https://github.com/meituan/YOLOv6/tree/main)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: INT8
14
+ - Backend: QNN2.23
15
+ - Target Device: FV01 QCS6490
16
+
17
+ ## Inference with AidLite SDK
18
+
19
+ ### SDK installation
20
+ 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/)
21
+
22
+ - install AidLite SDK
23
+
24
+ ```bash
25
+ # Install the appropriate version of the aidlite sdk
26
+ sudo aid-pkg update
27
+ sudo aid-pkg install aidlite-sdk
28
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
29
+ sudo aid-pkg install aidlite-{QNN VERSION}
30
+ # eg: Install QNN 2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
31
+ ```
32
+
33
+ - Verify AidLite SDK
34
+
35
+ ```bash
36
+ # aidlite sdk c++ check
37
+ python3 -c "import aidlite; print(aidlite.get_library_version())"
38
+
39
+ # aidlite sdk python check
40
+ python3 -c "import aidlite; print(aidlite.get_py_library_version())"
41
+ ```
42
+
43
+ ### Run demo
44
+
45
+ #### python
46
+ ```bash
47
+ cd yolov6m/model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite
48
+ python3 python/run_test.py --target_model ./models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem --imgs ./python/test.png --invoke_nums 10
49
+
50
+ ```
51
+
52
+ #### cpp
53
+ ```bash
54
+ cd yolov6m/model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp
55
+ mkdir build && cd build
56
+ cmake .. && make
57
+ ./run_test --target_model ../../models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem --imgs ../test.png --invoke_nums 10
58
+ ```
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required (VERSION 3.5)
2
+ project("run_test")
3
+
4
+ find_package(OpenCV REQUIRED)
5
+
6
+ message(STATUS "oPENCV Library status:")
7
+ message(STATUS ">version:${OpenCV_VERSION}")
8
+ message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
9
+
10
+ set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
11
+
12
+ include_directories(
13
+ /usr/local/include
14
+ /usr/include/opencv4
15
+ )
16
+
17
+ link_directories(
18
+ /usr/local/lib/
19
+ )
20
+
21
+ file(GLOB SRC_LISTS
22
+ ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ )
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp/main.cpp ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <opencv2/opencv.hpp>
6
+ #include <aidlux/aidlite/aidlite.hpp>
7
+ #include <vector>
8
+ #include <numeric>
9
+
10
+ const float INPUT_WIDTH = 640.0;
11
+ const float INPUT_HEIGHT = 640.0;
12
+ const float SCORE_THRESHOLD = 0.25;
13
+ const float NMS_THRESHOLD = 0.45;
14
+ const float CONFIDENCE_THRESHOLD = 0.25;
15
+ const uint32_t size = 640;
16
+ const uint32_t out_size = 8400;
17
+
18
+ const int FONT_FACE = cv::FONT_HERSHEY_SIMPLEX;
19
+ cv::Scalar WHITE = cv::Scalar(255,255,255);
20
+
21
+ const float FONT_SCALE = 1;
22
+ const int THICKNESS = 2;
23
+ using namespace Aidlux::Aidlite;
24
+
25
+ struct Args {
26
+ std::string target_model = "../../models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem";
27
+ std::string imgs = "../test.png";
28
+ int invoke_nums = 10;
29
+ std::string model_type = "QNN";
30
+ };
31
+
32
+ Args parse_args(int argc, char* argv[]) {
33
+ Args args;
34
+ for (int i = 1; i < argc; ++i) {
35
+ std::string arg = argv[i];
36
+ if (arg == "--target_model" && i + 1 < argc) {
37
+ args.target_model = argv[++i];
38
+ } else if (arg == "--imgs" && i + 1 < argc) {
39
+ args.imgs = argv[++i];
40
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
41
+ args.invoke_nums = std::stoi(argv[++i]);
42
+ } else if (arg == "--model_type" && i + 1 < argc) {
43
+ args.model_type = argv[++i];
44
+ }
45
+ }
46
+ return args;
47
+ }
48
+
49
+ std::string to_lower(const std::string& str) {
50
+ std::string lower_str = str;
51
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
52
+ return std::tolower(c);
53
+ });
54
+ return lower_str;
55
+ }
56
+
57
+
58
+ void concatenate(float* qnn_trans_data, float* qnn_mul_data, int batch, int num_elements, int trans_dim, int mul_dim, std::vector<float>& output) {
59
+ int out_dim = trans_dim + mul_dim + 1;
60
+ output.resize(batch * num_elements * out_dim);
61
+ for (int i = 0; i < batch * num_elements; ++i) {
62
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
63
+ float max_val = *std::max_element(&qnn_trans_data[i * trans_dim], &qnn_trans_data[i * trans_dim + trans_dim]);
64
+ output[i * out_dim + 4] = max_val;
65
+ std::memcpy(&output[i * out_dim + 5], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
66
+ }
67
+ }
68
+
69
+ cv::Mat letterbox(cv::Mat im, cv::Size new_shape = cv::Size(640, 640),
70
+ cv::Scalar color = cv::Scalar(114, 114, 114),
71
+ bool auto_pad = true, bool scaleup = true, int stride = 32) {
72
+ // current shape [height, width]
73
+ cv::Size shape = im.size();
74
+ int height = shape.height;
75
+ int width = shape.width;
76
+
77
+ if (new_shape.width == 0) {
78
+ new_shape = cv::Size(new_shape.height, new_shape.height);
79
+ }
80
+
81
+ // Scale ratio (new / old)
82
+ float r = std::min((float)new_shape.height / height, (float)new_shape.width / width);
83
+ if (!scaleup) {
84
+ // only scale down, do not scale up (for better val mAP)
85
+ r = std::min(r, 1.0f);
86
+ }
87
+
88
+ // Compute padding
89
+ cv::Size new_unpad(round(width * r), round(height * r));
90
+ int dw = new_shape.width - new_unpad.width;
91
+ int dh = new_shape.height - new_unpad.height;
92
+
93
+ // minimum rectangle
94
+ if (auto_pad) {
95
+ dw = dw % stride;
96
+ dh = dh % stride;
97
+ }
98
+
99
+ dw /= 2; // divide padding into 2 sides
100
+ dh /= 2;
101
+
102
+ // resize
103
+ if (cv::Size(width, height) != new_unpad) {
104
+ cv::resize(im, im, new_unpad, 0, 0, cv::INTER_LINEAR);
105
+ }
106
+
107
+ int top = round(dh - 0.1);
108
+ int bottom = round(dh + 0.1);
109
+ int left = round(dw - 0.1);
110
+ int right = round(dw + 0.1);
111
+
112
+ cv::copyMakeBorder(im, im, top, bottom, left, right, cv::BORDER_CONSTANT, color);
113
+ return im;
114
+ }
115
+ cv::Scalar generate_colors(int i, bool bgr = false) {
116
+ static const std::vector<std::string> hex_colors = {
117
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
118
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
119
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
120
+ "FF95C8", "FF37C7"
121
+ };
122
+
123
+ int num = hex_colors.size();
124
+ std::string hex = hex_colors[i % num];
125
+
126
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
127
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
128
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
129
+
130
+ if (bgr)
131
+ return cv::Scalar(b, g, r);
132
+ else
133
+ return cv::Scalar(r, g, b);
134
+ }
135
+
136
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
137
+ {
138
+ int baseLine;
139
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
140
+ int y = top - label_size.height - baseLine;
141
+ if (y < 0) {
142
+ y = top + label_size.height + baseLine;
143
+ }
144
+ cv::Point tlc(left, y);
145
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
146
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
147
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
148
+ }
149
+
150
+
151
+ cv::Mat post_process(cv::Mat &input_image, std::vector<float> &outputs, const std::vector<std::string> &class_name)
152
+ {
153
+ // Initialize vectors to hold respective outputs while unwrapping detections.
154
+ std::vector<int> class_ids;
155
+ std::vector<float> confidences;
156
+ std::vector<cv::Rect> boxes;
157
+
158
+ // Resizing factor.
159
+ float r = std::min(INPUT_WIDTH / (float)input_image.cols, INPUT_HEIGHT / (float)input_image.rows);
160
+ int new_unpad_w = round(input_image.cols * r);
161
+ int new_unpad_h = round(input_image.rows * r);
162
+ int dw = (int)INPUT_WIDTH - new_unpad_w;
163
+ int dh = (int)INPUT_HEIGHT - new_unpad_h;
164
+ dw /= 24;
165
+ dh /= 24;
166
+
167
+ // Iterate through outputs for each box prediction
168
+ for (int i = 0; i < outputs.size(); i+=85)
169
+ {
170
+ float confidence = outputs[i+4];
171
+ if (confidence >= CONFIDENCE_THRESHOLD)
172
+ {
173
+ // Create a 1x80 Mat and store class scores of 80 classes.
174
+ cv::Mat scores(1, class_name.size(), CV_32FC1, outputs.data() + i + 5);
175
+ cv::Point class_id;
176
+ double max_class_score;
177
+
178
+ // For multi-label, check each class score
179
+ for (int c = 0; c < class_name.size(); c++) {
180
+ float class_score = scores.at<float>(0, c);
181
+
182
+ // If class score is above threshold, consider this class for the box
183
+ if (class_score > SCORE_THRESHOLD) {
184
+ // Store class ID and confidence in the pre-defined respective vectors.
185
+ confidences.push_back(confidence * class_score); // Multiply with confidence
186
+ class_ids.push_back(c); // class index
187
+ // Center and box dimension.
188
+ float cx = outputs[i];
189
+ float cy = outputs[i+1];
190
+ float w = outputs[i+2];
191
+ float h = outputs[i+3];
192
+
193
+ float x0 = (cx - 0.5f * w - dw) / r;
194
+ float y0 = (cy - 0.5f * h - dh) / r;
195
+ float x1 = (cx + 0.5f * w - dw) / r;
196
+ float y1 = (cy + 0.5f * h - dh) / r;
197
+
198
+ int left = int(x0);
199
+ int top = int(y0);
200
+ int width = int(x1 - x0);
201
+ int height = int(y1 - y0);
202
+
203
+ // Store good detections in the boxes vector.
204
+ boxes.push_back(cv::Rect(left, top, width, height));
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ // Perform Non Maximum Suppression and draw predictions.
211
+ std::vector<int> indices;
212
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
213
+ printf("Detected {%ld} targets.\n", indices.size());
214
+
215
+ // Loop over NMS results and draw bounding boxes
216
+ for (int i = 0; i < indices.size(); i++)
217
+ {
218
+ int idx = indices[i];
219
+ cv::Rect box = boxes[idx];
220
+
221
+ int left = box.x;
222
+ int top = box.y;
223
+ int width = box.width;
224
+ int height = box.height;
225
+ cv::Scalar color = generate_colors(class_ids[idx]);
226
+ // Draw bounding box.
227
+ rectangle(input_image, cv::Point(left, top), cv::Point(left + width, top + height), color, 3*THICKNESS);
228
+
229
+ // Get the label for the class name and its confidence.
230
+ std::string label = cv::format("%.2f", confidences[idx]);
231
+ label = class_name[class_ids[idx]] + ":" + label;
232
+ // Draw class labels.
233
+ draw_label(input_image, label, left, top, color);
234
+ }
235
+ printf("Processing finished.\n");
236
+ return input_image;
237
+ }
238
+
239
+
240
+ int invoke(const Args& args) {
241
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
242
+ << "Image Path: " << args.imgs << "\n"
243
+ << "Inference Nums: " << args.invoke_nums << "\n"
244
+ << "Model Type: " << args.model_type << "\n";
245
+ Model* model = Model::create_instance(args.target_model);
246
+ if(model == nullptr){
247
+ printf("Create model failed !\n");
248
+ return EXIT_FAILURE;
249
+ }
250
+ Config* config = Config::create_instance();
251
+ if(config == nullptr){
252
+ printf("Create config failed !\n");
253
+ return EXIT_FAILURE;
254
+ }
255
+ config->implement_type = ImplementType::TYPE_LOCAL;
256
+ std::string model_type_lower = to_lower(args.model_type);
257
+ if (model_type_lower == "qnn"){
258
+ config->framework_type = FrameworkType::TYPE_QNN223;
259
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
260
+ config->framework_type = FrameworkType::TYPE_SNPE2;
261
+ }
262
+ config->accelerate_type = AccelerateType::TYPE_DSP;
263
+ config->is_quantify_model = 1;
264
+
265
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
266
+ std::vector<std::vector<uint32_t>> output_shapes = {{1, out_size, 80}, {1, out_size, 4}};
267
+ model->set_model_properties(input_shapes, DataType::TYPE_FLOAT32, output_shapes, DataType::TYPE_FLOAT32);
268
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
269
+ if(fast_interpreter == nullptr){
270
+ printf("build_interpretper_from_model_and_config failed !\n");
271
+ return EXIT_FAILURE;
272
+ }
273
+ int result = fast_interpreter->init();
274
+ if(result != EXIT_SUCCESS){
275
+ printf("interpreter->init() failed !\n");
276
+ return EXIT_FAILURE;
277
+ }
278
+ // load model
279
+ fast_interpreter->load_model();
280
+ if(result != EXIT_SUCCESS){
281
+ printf("interpreter->load_model() failed !\n");
282
+ return EXIT_FAILURE;
283
+ }
284
+ printf("detect model load success!\n");
285
+ cv::Size img_size(size, size);
286
+
287
+ cv::Mat img_src = cv::imread(args.imgs);
288
+ printf("img_src cols: %d, img_src rows: %d\n", img_src.cols, img_src.rows);
289
+ cv::Mat img_ori = img_src.clone();
290
+ cv::cvtColor(img_ori, img_ori, cv::COLOR_BGR2RGB);
291
+ cv::Mat resized_img = letterbox(img_ori, img_size);
292
+ cv::Mat input_img = cv::Mat::zeros(img_size, CV_32FC3);
293
+ resized_img.convertTo(resized_img, CV_32FC3, 1.0 / 255.0);
294
+ resized_img.copyTo(input_img(cv::Rect(0, 0, resized_img.cols, resized_img.rows)));
295
+ float *qnn_trans_data = nullptr;
296
+ float *qnn_mul_data = nullptr;
297
+
298
+ std::vector<float> invoke_time;
299
+ for (int i = 0; i < args.invoke_nums; ++i) {
300
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
301
+ if(result != EXIT_SUCCESS){
302
+ printf("interpreter->set_input_tensor() failed !\n");
303
+ return EXIT_FAILURE;
304
+ }
305
+ // 开始计时
306
+ auto t1 = std::chrono::high_resolution_clock::now();
307
+ result = fast_interpreter->invoke();
308
+ auto t2 = std::chrono::high_resolution_clock::now();
309
+ std::chrono::duration<double> cost_time = t2 - t1;
310
+ invoke_time.push_back(cost_time.count() * 1000);
311
+ if(result != EXIT_SUCCESS){
312
+ printf("interpreter->invoke() failed !\n");
313
+ return EXIT_FAILURE;
314
+ }
315
+ uint32_t out_data_1 = 0;
316
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_trans_data, &out_data_1);
317
+ if(result != EXIT_SUCCESS){
318
+ printf("interpreter->get_output_tensor() 1 failed !\n");
319
+ return EXIT_FAILURE;
320
+ }
321
+ uint32_t out_data_2 = 0;
322
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_mul_data, &out_data_2);
323
+ if(result != EXIT_SUCCESS){
324
+ printf("interpreter->get_output_tensor() 2 failed !\n");
325
+ return EXIT_FAILURE;
326
+ }
327
+ }
328
+
329
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
330
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
331
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
332
+ float var_invoketime = 0.0f;
333
+ for (auto time : invoke_time) {
334
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
335
+ }
336
+ var_invoketime /= args.invoke_nums;
337
+ printf("=======================================\n");
338
+ printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
339
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
340
+ printf("=======================================\n");
341
+
342
+ std::vector<std::string> class_list = {
343
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
344
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
345
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
346
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
347
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
348
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
349
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
350
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
351
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
352
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
353
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
354
+ "scissors", "teddy bear", "hair drier", "toothbrush"
355
+ };
356
+
357
+ // post process
358
+ std::vector<float> qnn_concat;
359
+ concatenate(qnn_trans_data, qnn_mul_data, 1, out_size, 80, 4, qnn_concat);
360
+ cv::Mat img = post_process(img_src, qnn_concat, class_list);
361
+ cv::imwrite("./results.png", img);
362
+ fast_interpreter->destory();
363
+ return 0;
364
+ }
365
+
366
+
367
+ int main(int argc, char* argv[]) {
368
+ Args args = parse_args(argc, argv);
369
+ return invoke(args);
370
+ }
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/cpp/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2b5f70de77d86203135bf45778bb7448565566682bf659a418155d6148b19a13
3
+ size 38488656
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/python/run_test.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, torch, cv2
2
+ import numpy as np
3
+ import time
4
+ import aidlite
5
+ import argparse
6
+ from utils import letterbox,plot_box_and_label,rescale,generate_colors,non_max_suppression
7
+ import torch
8
+
9
+
10
+ def process_image(path, img_size):
11
+ img_src = cv2.imread(path)
12
+ img_src = cv2.cvtColor(img_src,cv2.COLOR_BGR2RGB)
13
+ image = letterbox(img_src, img_size)[0]
14
+ new_h,new_w,_=image.shape
15
+ input_img = np.zeros((img_size[0], img_size[1], 3), np.uint8)
16
+ input_img[0:new_h, 0:new_w] = image
17
+ input_img = input_img.astype(np.float32)
18
+ input_img /= 255 # 0 - 255 to 0.0 - 1.0
19
+ input_img = np.expand_dims(input_img,0)
20
+ return image,input_img, img_src
21
+
22
+ def main(args):
23
+ print("Start main ... ...")
24
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
25
+ # aidlite.log_to_stderr()
26
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
27
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
28
+
29
+ size=640
30
+ out_size=8400
31
+ config = aidlite.Config.create_instance()
32
+ if config is None:
33
+ print("Create config failed !")
34
+ return False
35
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
36
+ if args.model_type.lower()=="qnn":
37
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN223
38
+ elif args.model_type.lower()=="snpe2" or args.model_type.lower()=="snpe":
39
+ config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
40
+
41
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
42
+ config.is_quantify_model = 1
43
+
44
+
45
+ model = aidlite.Model.create_instance(args.target_model)
46
+ if model is None:
47
+ print("Create model failed !")
48
+ return False
49
+ input_shapes = [[1, size, size, 3]]
50
+ output_shapes = [[1, out_size,80],[1, out_size,4]]
51
+ model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
52
+ output_shapes, aidlite.DataType.TYPE_FLOAT32)
53
+
54
+ interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
55
+ if interpreter is None:
56
+ print("build_interpretper_from_model_and_config failed !")
57
+ return None
58
+ result = interpreter.init()
59
+ if result != 0:
60
+ print(f"interpreter init failed !")
61
+ return False
62
+ result = interpreter.load_model()
63
+ if result != 0:
64
+ print("interpreter load model failed !")
65
+ return False
66
+ print("detect model load success!")
67
+
68
+ # image process
69
+ img_size=[size,size]
70
+ resize_img,input_img, img_src = process_image(args.imgs, img_size)
71
+
72
+ # qnn run
73
+ invoke_time=[]
74
+ for i in range(args.invoke_nums):
75
+ result = interpreter.set_input_tensor(0, input_img.data)
76
+ if result != 0:
77
+ print("interpreter set_input_tensor() failed")
78
+
79
+ t1=time.time()
80
+ result = interpreter.invoke()
81
+ cost_time = (time.time()-t1)*1000
82
+ invoke_time.append(cost_time)
83
+
84
+ if result != 0:
85
+ print("interpreter set_input_tensor() failed")
86
+
87
+ qnn_trans = interpreter.get_output_tensor(0).reshape(1,out_size,80)
88
+ qnn_mul = interpreter.get_output_tensor(1).reshape(1,out_size,4)
89
+
90
+ result = interpreter.destory()
91
+
92
+ ## time 统计
93
+ max_invoke_time = max(invoke_time)
94
+ min_invoke_time = min(invoke_time)
95
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
96
+ var_invoketime=np.var(invoke_time)
97
+ print("=======================================")
98
+ print(f"QNN inference {args.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}")
99
+ print("=======================================")
100
+
101
+ # 后处理
102
+ conf_thres =0.25 #@param {type:"number"}
103
+ iou_thres =0.45 #@param {type:"number"}
104
+ max_det= 1000#@param {type:"integer"}
105
+ agnostic_nms= False #@param {type:"boolean"}
106
+ classes =None
107
+ hide_labels = False #@param {type:"boolean"}
108
+ hide_conf= False #@param {type:"boolean"}
109
+
110
+ qnn_conf = np.ones((1,out_size,1))
111
+ qnn_predict=np.concatenate((qnn_mul,qnn_conf,qnn_trans), axis=2)
112
+ pred_results =torch.from_numpy(qnn_predict.copy())
113
+ det = non_max_suppression(pred_results, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)[0]
114
+
115
+ class_names=[ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
116
+ 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
117
+ 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
118
+ 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
119
+ 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
120
+ 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
121
+ 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
122
+ 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
123
+ 'hair drier', 'toothbrush' ]
124
+
125
+ img_ori = img_src.copy()
126
+ print(f"Detected {len(det)} targets.")
127
+ if len(det):
128
+ det[:, :4] = rescale(resize_img.shape[:2], det[:, :4], img_src.shape).round()
129
+ for *xyxy, conf, cls in reversed(det):
130
+ class_num = int(cls)
131
+ label = None if hide_labels else (class_names[class_num] if hide_conf else f'{class_names[class_num]} {conf:.2f}')
132
+ plot_box_and_label(img_ori, max(round(sum(img_ori.shape) / 2 * 0.003), 2), xyxy, label, color=generate_colors(class_num, True))
133
+
134
+ cv2.imwrite("./python/results.png",cv2.cvtColor(img_ori,cv2.COLOR_RGB2BGR))
135
+
136
+ def parser_args():
137
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
138
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem',help="inference model path")
139
+ parser.add_argument('--imgs',type=str,default='./python/test.png',help="Predict images path")
140
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
141
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
142
+ args = parser.parse_args()
143
+ return args
144
+
145
+ if __name__ == "__main__":
146
+ args = parser_args()
147
+ main(args)
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/python/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs6490_qnn2.23_int8_aidlite/python/utils.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import torch
4
+ import torchvision
5
+
6
+ def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleup=True, stride=32):
7
+ '''Resize and pad image while meeting stride-multiple constraints.'''
8
+ shape = im.shape[:2] # current shape [height, width]
9
+ if isinstance(new_shape, int):
10
+ new_shape = (new_shape, new_shape)
11
+ elif isinstance(new_shape, list) and len(new_shape) == 1:
12
+ new_shape = (new_shape[0], new_shape[0])
13
+
14
+ # Scale ratio (new / old)
15
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
16
+ if not scaleup: # only scale down, do not scale up (for better val mAP)
17
+ r = min(r, 1.0)
18
+
19
+ # Compute padding
20
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
21
+ dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
22
+
23
+ if auto: # minimum rectangle
24
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
25
+
26
+ dw /= 2 # divide padding into 2 sides
27
+ dh /= 2
28
+
29
+ if shape[::-1] != new_unpad: # resize
30
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
31
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
32
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
33
+ im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
34
+
35
+ return im, r, (left, top)
36
+
37
+
38
+
39
+
40
+ def xywh2xyxy(x):
41
+ '''Convert boxes with shape [n, 4] from [x, y, w, h] to [x1, y1, x2, y2] where x1y1 is top-left, x2y2=bottom-right.'''
42
+ y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
43
+ y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
44
+ y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
45
+ y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
46
+ y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
47
+ return y
48
+
49
+ def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=False, max_det=300):
50
+ """Runs Non-Maximum Suppression (NMS) on inference results.
51
+ This code is borrowed from: https://github.com/ultralytics/yolov5/blob/47233e1698b89fc437a4fb9463c815e9171be955/utils/general.py#L775
52
+ Args:
53
+ prediction: (tensor), with shape [N, 5 + num_classes], N is the number of bboxes.
54
+ conf_thres: (float) confidence threshold.
55
+ iou_thres: (float) iou threshold.
56
+ classes: (None or list[int]), if a list is provided, nms only keep the classes you provide.
57
+ agnostic: (bool), when it is set to True, we do class-independent nms, otherwise, different class would do nms respectively.
58
+ multi_label: (bool), when it is set to True, one box can have multi labels, otherwise, one box only huave one label.
59
+ max_det:(int), max number of output bboxes.
60
+
61
+ Returns:
62
+ list of detections, echo item is one tensor with shape (num_boxes, 6), 6 is for [xyxy, conf, cls].
63
+ """
64
+
65
+ num_classes = prediction.shape[2] - 5 # number of classes
66
+ pred_candidates = torch.logical_and(prediction[..., 4] > conf_thres, torch.max(prediction[..., 5:], axis=-1)[0] > conf_thres) # candidates
67
+ # Check the parameters.
68
+ assert 0 <= conf_thres <= 1, f'conf_thresh must be in 0.0 to 1.0, however {conf_thres} is provided.'
69
+ assert 0 <= iou_thres <= 1, f'iou_thres must be in 0.0 to 1.0, however {iou_thres} is provided.'
70
+
71
+ # Function settings.
72
+ max_wh = 4096 # maximum box width and height
73
+ max_nms = 30000 # maximum number of boxes put into torchvision.ops.nms()
74
+ time_limit = 10.0 # quit the function when nms cost time exceed the limit time.
75
+ multi_label &= num_classes > 1 # multiple labels per box
76
+
77
+ output = [torch.zeros((0, 6), device=prediction.device)] * prediction.shape[0]
78
+ for img_idx, x in enumerate(prediction): # image index, image inference
79
+ x = x[pred_candidates[img_idx]] # confidence
80
+
81
+ # If no box remains, skip the next process.
82
+ if not x.shape[0]:
83
+ continue
84
+
85
+ # confidence multiply the objectness
86
+ x[:, 5:] *= x[:, 4:5] # conf = obj_conf * cls_conf
87
+
88
+ # (center x, center y, width, height) to (x1, y1, x2, y2)
89
+ box = xywh2xyxy(x[:, :4])
90
+
91
+ # Detections matrix's shape is (n,6), each row represents (xyxy, conf, cls)
92
+ if multi_label:
93
+ box_idx, class_idx = (x[:, 5:] > conf_thres).nonzero(as_tuple=False).T
94
+ x = torch.cat((box[box_idx], x[box_idx, class_idx + 5, None], class_idx[:, None].float()), 1)
95
+ else: # Only keep the class with highest scores.
96
+ conf, class_idx = x[:, 5:].max(1, keepdim=True)
97
+ x = torch.cat((box, conf, class_idx.float()), 1)[conf.view(-1) > conf_thres]
98
+
99
+ # Filter by class, only keep boxes whose category is in classes.
100
+ if classes is not None:
101
+ x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]
102
+
103
+ # Check shape
104
+ num_box = x.shape[0] # number of boxes
105
+ if not num_box: # no boxes kept.
106
+ continue
107
+ elif num_box > max_nms: # excess max boxes' number.
108
+ x = x[x[:, 4].argsort(descending=True)[:max_nms]] # sort by confidence
109
+
110
+ # Batched NMS
111
+ class_offset = x[:, 5:6] * (0 if agnostic else max_wh) # classes
112
+ boxes, scores = x[:, :4] + class_offset, x[:, 4] # boxes (offset by class), scores
113
+ keep_box_idx = torchvision.ops.nms(boxes, scores, iou_thres) # NMS
114
+ if keep_box_idx.shape[0] > max_det: # limit detections
115
+ keep_box_idx = keep_box_idx[:max_det]
116
+
117
+ output[img_idx] = x[keep_box_idx]
118
+
119
+ return output
120
+
121
+ def plot_box_and_label(image, lw, box, label='', color=(128, 128, 128), txt_color=(255, 255, 255), font=cv2.FONT_HERSHEY_COMPLEX):
122
+ # Add one xyxy box to image with label
123
+ p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
124
+ cv2.rectangle(image, p1, p2, color, thickness=lw, lineType=cv2.LINE_AA)
125
+ if label:
126
+ tf = max(lw - 1, 1) # font thickness
127
+ w, h = cv2.getTextSize(label, 0, fontScale=lw / 3, thickness=tf)[0] # text width, height
128
+ outside = p1[1] - h - 3 >= 0 # label fits outside box
129
+ p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3
130
+ cv2.rectangle(image, p1, p2, color, -1, cv2.LINE_AA) # filled
131
+ cv2.putText(image, label, (p1[0], p1[1] - 2 if outside else p1[1] + h + 2), font, lw / 3, txt_color,
132
+ thickness=tf, lineType=cv2.LINE_AA)
133
+
134
+ def generate_colors(i, bgr=False):
135
+ hex = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
136
+ '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
137
+ palette = []
138
+ for iter in hex:
139
+ h = '#' + iter
140
+ palette.append(tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4)))
141
+ num = len(palette)
142
+ color = palette[int(i) % num]
143
+ return (color[2], color[1], color[0]) if bgr else color
144
+
145
+ def rescale(ori_shape, boxes, target_shape):
146
+ '''Rescale the output to the original image shape'''
147
+ ratio = min(ori_shape[0] / target_shape[0], ori_shape[1] / target_shape[1])
148
+ padding = (ori_shape[1] - target_shape[1] * ratio) / 2, (ori_shape[0] - target_shape[0] * ratio) / 2
149
+
150
+ boxes[:, [0, 2]] -= padding[0]
151
+ boxes[:, [1, 3]] -= padding[1]
152
+ boxes[:, :4] /= ratio
153
+
154
+ boxes[:, 0].clamp_(0, target_shape[1]) # x1
155
+ boxes[:, 1].clamp_(0, target_shape[0]) # y1
156
+ boxes[:, 2].clamp_(0, target_shape[1]) # x2
157
+ boxes[:, 3].clamp_(0, target_shape[0]) # y2
158
+
159
+ return boxes
160
+
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ### Source model
3
+
4
+ - Input shape: 1x3x640x640
5
+ - Number of parameters: 33.24M
6
+ - Model size: 133.20MB
7
+ - Output shape: 1x8400x85
8
+
9
+ Source model repository: [yolov6](https://github.com/meituan/YOLOv6/tree/main)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: FP16
14
+ - Backend: QNN2.23
15
+ - Target Device: SNM972 QCS8550
16
+
17
+ ## Inference with AidLite SDK
18
+
19
+ ### SDK installation
20
+ 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/)
21
+
22
+ - install AidLite SDK
23
+
24
+ ```bash
25
+ # Install the appropriate version of the aidlite sdk
26
+ sudo aid-pkg update
27
+ sudo aid-pkg install aidlite-sdk
28
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
29
+ sudo aid-pkg install aidlite-{QNN VERSION}
30
+ # eg: Install QNN 2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
31
+ ```
32
+
33
+ - Verify AidLite SDK
34
+
35
+ ```bash
36
+ # aidlite sdk c++ check
37
+ python3 -c "import aidlite; print(aidlite.get_library_version())"
38
+
39
+ # aidlite sdk python check
40
+ python3 -c "import aidlite; print(aidlite.get_py_library_version())"
41
+ ```
42
+
43
+ ### Run demo
44
+
45
+ #### python
46
+ ```bash
47
+ cd yolov6m/model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite
48
+ python3 python/run_test.py --target_model ./models/cutoff_yolov6m_fp16.qnn223.ctx.bin.aidem --imgs ./python/test.png --invoke_nums 10
49
+
50
+ ```
51
+
52
+ #### cpp
53
+ ```bash
54
+ cd yolov6m/model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp
55
+ mkdir build && cd build
56
+ cmake .. && make
57
+ ./run_test --target_model ../../models/cutoff_yolov6m_fp16.qnn223.ctx.bin.aidem --imgs ../test.png --invoke_nums 10
58
+ ```
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required (VERSION 3.5)
2
+ project("run_test")
3
+
4
+ find_package(OpenCV REQUIRED)
5
+
6
+ message(STATUS "oPENCV Library status:")
7
+ message(STATUS ">version:${OpenCV_VERSION}")
8
+ message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
9
+
10
+ set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
11
+
12
+ include_directories(
13
+ /usr/local/include
14
+ /usr/include/opencv4
15
+ )
16
+
17
+ link_directories(
18
+ /usr/local/lib/
19
+ )
20
+
21
+ file(GLOB SRC_LISTS
22
+ ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ )
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp/main.cpp ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <opencv2/opencv.hpp>
6
+ #include <aidlux/aidlite/aidlite.hpp>
7
+ #include <vector>
8
+ #include <numeric>
9
+
10
+ const float INPUT_WIDTH = 640.0;
11
+ const float INPUT_HEIGHT = 640.0;
12
+ const float SCORE_THRESHOLD = 0.25;
13
+ const float NMS_THRESHOLD = 0.45;
14
+ const float CONFIDENCE_THRESHOLD = 0.25;
15
+ const uint32_t size = 640;
16
+ const uint32_t out_size = 8400;
17
+
18
+ const int FONT_FACE = cv::FONT_HERSHEY_SIMPLEX;
19
+ cv::Scalar WHITE = cv::Scalar(255,255,255);
20
+
21
+ const float FONT_SCALE = 1;
22
+ const int THICKNESS = 2;
23
+ using namespace Aidlux::Aidlite;
24
+
25
+ struct Args {
26
+ std::string target_model = "../../models/cutoff_yolov6m_fp16.qnn223.ctx.bin.aidem";
27
+ std::string imgs = "../test.png";
28
+ int invoke_nums = 10;
29
+ std::string model_type = "QNN";
30
+ };
31
+
32
+ Args parse_args(int argc, char* argv[]) {
33
+ Args args;
34
+ for (int i = 1; i < argc; ++i) {
35
+ std::string arg = argv[i];
36
+ if (arg == "--target_model" && i + 1 < argc) {
37
+ args.target_model = argv[++i];
38
+ } else if (arg == "--imgs" && i + 1 < argc) {
39
+ args.imgs = argv[++i];
40
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
41
+ args.invoke_nums = std::stoi(argv[++i]);
42
+ } else if (arg == "--model_type" && i + 1 < argc) {
43
+ args.model_type = argv[++i];
44
+ }
45
+ }
46
+ return args;
47
+ }
48
+
49
+ std::string to_lower(const std::string& str) {
50
+ std::string lower_str = str;
51
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
52
+ return std::tolower(c);
53
+ });
54
+ return lower_str;
55
+ }
56
+
57
+
58
+ void concatenate(float* qnn_trans_data, float* qnn_mul_data, int batch, int num_elements, int trans_dim, int mul_dim, std::vector<float>& output) {
59
+ int out_dim = trans_dim + mul_dim + 1;
60
+ output.resize(batch * num_elements * out_dim);
61
+ for (int i = 0; i < batch * num_elements; ++i) {
62
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
63
+ float max_val = *std::max_element(&qnn_trans_data[i * trans_dim], &qnn_trans_data[i * trans_dim + trans_dim]);
64
+ output[i * out_dim + 4] = max_val;
65
+ std::memcpy(&output[i * out_dim + 5], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
66
+ }
67
+ }
68
+
69
+ cv::Mat letterbox(cv::Mat im, cv::Size new_shape = cv::Size(640, 640),
70
+ cv::Scalar color = cv::Scalar(114, 114, 114),
71
+ bool auto_pad = true, bool scaleup = true, int stride = 32) {
72
+ // current shape [height, width]
73
+ cv::Size shape = im.size();
74
+ int height = shape.height;
75
+ int width = shape.width;
76
+
77
+ if (new_shape.width == 0) {
78
+ new_shape = cv::Size(new_shape.height, new_shape.height);
79
+ }
80
+
81
+ // Scale ratio (new / old)
82
+ float r = std::min((float)new_shape.height / height, (float)new_shape.width / width);
83
+ if (!scaleup) {
84
+ // only scale down, do not scale up (for better val mAP)
85
+ r = std::min(r, 1.0f);
86
+ }
87
+
88
+ // Compute padding
89
+ cv::Size new_unpad(round(width * r), round(height * r));
90
+ int dw = new_shape.width - new_unpad.width;
91
+ int dh = new_shape.height - new_unpad.height;
92
+
93
+ // minimum rectangle
94
+ if (auto_pad) {
95
+ dw = dw % stride;
96
+ dh = dh % stride;
97
+ }
98
+
99
+ dw /= 2; // divide padding into 2 sides
100
+ dh /= 2;
101
+
102
+ // resize
103
+ if (cv::Size(width, height) != new_unpad) {
104
+ cv::resize(im, im, new_unpad, 0, 0, cv::INTER_LINEAR);
105
+ }
106
+
107
+ int top = round(dh - 0.1);
108
+ int bottom = round(dh + 0.1);
109
+ int left = round(dw - 0.1);
110
+ int right = round(dw + 0.1);
111
+
112
+ cv::copyMakeBorder(im, im, top, bottom, left, right, cv::BORDER_CONSTANT, color);
113
+ return im;
114
+ }
115
+ cv::Scalar generate_colors(int i, bool bgr = false) {
116
+ static const std::vector<std::string> hex_colors = {
117
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
118
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
119
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
120
+ "FF95C8", "FF37C7"
121
+ };
122
+
123
+ int num = hex_colors.size();
124
+ std::string hex = hex_colors[i % num];
125
+
126
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
127
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
128
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
129
+
130
+ if (bgr)
131
+ return cv::Scalar(b, g, r);
132
+ else
133
+ return cv::Scalar(r, g, b);
134
+ }
135
+
136
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
137
+ {
138
+ int baseLine;
139
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
140
+ int y = top - label_size.height - baseLine;
141
+ if (y < 0) {
142
+ y = top + label_size.height + baseLine;
143
+ }
144
+ cv::Point tlc(left, y);
145
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
146
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
147
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
148
+ }
149
+
150
+
151
+ cv::Mat post_process(cv::Mat &input_image, std::vector<float> &outputs, const std::vector<std::string> &class_name)
152
+ {
153
+ // Initialize vectors to hold respective outputs while unwrapping detections.
154
+ std::vector<int> class_ids;
155
+ std::vector<float> confidences;
156
+ std::vector<cv::Rect> boxes;
157
+
158
+ // Resizing factor.
159
+ float r = std::min(INPUT_WIDTH / (float)input_image.cols, INPUT_HEIGHT / (float)input_image.rows);
160
+ int new_unpad_w = round(input_image.cols * r);
161
+ int new_unpad_h = round(input_image.rows * r);
162
+ int dw = (int)INPUT_WIDTH - new_unpad_w;
163
+ int dh = (int)INPUT_HEIGHT - new_unpad_h;
164
+ dw /= 24;
165
+ dh /= 24;
166
+
167
+ // Iterate through outputs for each box prediction
168
+ for (int i = 0; i < outputs.size(); i+=85)
169
+ {
170
+ float confidence = outputs[i+4];
171
+ if (confidence >= CONFIDENCE_THRESHOLD)
172
+ {
173
+ // Create a 1x80 Mat and store class scores of 80 classes.
174
+ cv::Mat scores(1, class_name.size(), CV_32FC1, outputs.data() + i + 5);
175
+ cv::Point class_id;
176
+ double max_class_score;
177
+
178
+ // For multi-label, check each class score
179
+ for (int c = 0; c < class_name.size(); c++) {
180
+ float class_score = scores.at<float>(0, c);
181
+
182
+ // If class score is above threshold, consider this class for the box
183
+ if (class_score > SCORE_THRESHOLD) {
184
+ // Store class ID and confidence in the pre-defined respective vectors.
185
+ confidences.push_back(confidence * class_score); // Multiply with confidence
186
+ class_ids.push_back(c); // class index
187
+ // Center and box dimension.
188
+ float cx = outputs[i];
189
+ float cy = outputs[i+1];
190
+ float w = outputs[i+2];
191
+ float h = outputs[i+3];
192
+
193
+ float x0 = (cx - 0.5f * w - dw) / r;
194
+ float y0 = (cy - 0.5f * h - dh) / r;
195
+ float x1 = (cx + 0.5f * w - dw) / r;
196
+ float y1 = (cy + 0.5f * h - dh) / r;
197
+
198
+ int left = int(x0);
199
+ int top = int(y0);
200
+ int width = int(x1 - x0);
201
+ int height = int(y1 - y0);
202
+
203
+ // Store good detections in the boxes vector.
204
+ boxes.push_back(cv::Rect(left, top, width, height));
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ // Perform Non Maximum Suppression and draw predictions.
211
+ std::vector<int> indices;
212
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
213
+ printf("Detected {%ld} targets.\n", indices.size());
214
+
215
+ // Loop over NMS results and draw bounding boxes
216
+ for (int i = 0; i < indices.size(); i++)
217
+ {
218
+ int idx = indices[i];
219
+ cv::Rect box = boxes[idx];
220
+
221
+ int left = box.x;
222
+ int top = box.y;
223
+ int width = box.width;
224
+ int height = box.height;
225
+ cv::Scalar color = generate_colors(class_ids[idx]);
226
+ // Draw bounding box.
227
+ rectangle(input_image, cv::Point(left, top), cv::Point(left + width, top + height), color, 3*THICKNESS);
228
+
229
+ // Get the label for the class name and its confidence.
230
+ std::string label = cv::format("%.2f", confidences[idx]);
231
+ label = class_name[class_ids[idx]] + ":" + label;
232
+ // Draw class labels.
233
+ draw_label(input_image, label, left, top, color);
234
+ }
235
+ printf("Processing finished.\n");
236
+ return input_image;
237
+ }
238
+
239
+
240
+ int invoke(const Args& args) {
241
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
242
+ << "Image Path: " << args.imgs << "\n"
243
+ << "Inference Nums: " << args.invoke_nums << "\n"
244
+ << "Model Type: " << args.model_type << "\n";
245
+ Model* model = Model::create_instance(args.target_model);
246
+ if(model == nullptr){
247
+ printf("Create model failed !\n");
248
+ return EXIT_FAILURE;
249
+ }
250
+ Config* config = Config::create_instance();
251
+ if(config == nullptr){
252
+ printf("Create config failed !\n");
253
+ return EXIT_FAILURE;
254
+ }
255
+ config->implement_type = ImplementType::TYPE_LOCAL;
256
+ std::string model_type_lower = to_lower(args.model_type);
257
+ if (model_type_lower == "qnn"){
258
+ config->framework_type = FrameworkType::TYPE_QNN223;
259
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
260
+ config->framework_type = FrameworkType::TYPE_SNPE2;
261
+ }
262
+ config->accelerate_type = AccelerateType::TYPE_DSP;
263
+ config->is_quantify_model = 1;
264
+
265
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
266
+ std::vector<std::vector<uint32_t>> output_shapes = {{1, out_size, 80}, {1, out_size, 4}};
267
+ model->set_model_properties(input_shapes, DataType::TYPE_FLOAT32, output_shapes, DataType::TYPE_FLOAT32);
268
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
269
+ if(fast_interpreter == nullptr){
270
+ printf("build_interpretper_from_model_and_config failed !\n");
271
+ return EXIT_FAILURE;
272
+ }
273
+ int result = fast_interpreter->init();
274
+ if(result != EXIT_SUCCESS){
275
+ printf("interpreter->init() failed !\n");
276
+ return EXIT_FAILURE;
277
+ }
278
+ // load model
279
+ fast_interpreter->load_model();
280
+ if(result != EXIT_SUCCESS){
281
+ printf("interpreter->load_model() failed !\n");
282
+ return EXIT_FAILURE;
283
+ }
284
+ printf("detect model load success!\n");
285
+ cv::Size img_size(size, size);
286
+
287
+ cv::Mat img_src = cv::imread(args.imgs);
288
+ printf("img_src cols: %d, img_src rows: %d\n", img_src.cols, img_src.rows);
289
+ cv::Mat img_ori = img_src.clone();
290
+ cv::cvtColor(img_ori, img_ori, cv::COLOR_BGR2RGB);
291
+ cv::Mat resized_img = letterbox(img_ori, img_size);
292
+ cv::Mat input_img = cv::Mat::zeros(img_size, CV_32FC3);
293
+ resized_img.convertTo(resized_img, CV_32FC3, 1.0 / 255.0);
294
+ resized_img.copyTo(input_img(cv::Rect(0, 0, resized_img.cols, resized_img.rows)));
295
+ float *qnn_trans_data = nullptr;
296
+ float *qnn_mul_data = nullptr;
297
+
298
+ std::vector<float> invoke_time;
299
+ for (int i = 0; i < args.invoke_nums; ++i) {
300
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
301
+ if(result != EXIT_SUCCESS){
302
+ printf("interpreter->set_input_tensor() failed !\n");
303
+ return EXIT_FAILURE;
304
+ }
305
+ // 开始计时
306
+ auto t1 = std::chrono::high_resolution_clock::now();
307
+ result = fast_interpreter->invoke();
308
+ auto t2 = std::chrono::high_resolution_clock::now();
309
+ std::chrono::duration<double> cost_time = t2 - t1;
310
+ invoke_time.push_back(cost_time.count() * 1000);
311
+ if(result != EXIT_SUCCESS){
312
+ printf("interpreter->invoke() failed !\n");
313
+ return EXIT_FAILURE;
314
+ }
315
+ uint32_t out_data_1 = 0;
316
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_trans_data, &out_data_1);
317
+ if(result != EXIT_SUCCESS){
318
+ printf("interpreter->get_output_tensor() 1 failed !\n");
319
+ return EXIT_FAILURE;
320
+ }
321
+ uint32_t out_data_2 = 0;
322
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_mul_data, &out_data_2);
323
+ if(result != EXIT_SUCCESS){
324
+ printf("interpreter->get_output_tensor() 2 failed !\n");
325
+ return EXIT_FAILURE;
326
+ }
327
+ }
328
+
329
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
330
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
331
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
332
+ float var_invoketime = 0.0f;
333
+ for (auto time : invoke_time) {
334
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
335
+ }
336
+ var_invoketime /= args.invoke_nums;
337
+ printf("=======================================\n");
338
+ printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
339
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
340
+ printf("=======================================\n");
341
+
342
+ std::vector<std::string> class_list = {
343
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
344
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
345
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
346
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
347
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
348
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
349
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
350
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
351
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
352
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
353
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
354
+ "scissors", "teddy bear", "hair drier", "toothbrush"
355
+ };
356
+
357
+ // post process
358
+ std::vector<float> qnn_concat;
359
+ concatenate(qnn_trans_data, qnn_mul_data, 1, out_size, 80, 4, qnn_concat);
360
+ cv::Mat img = post_process(img_src, qnn_concat, class_list);
361
+ cv::imwrite("./results.png", img);
362
+ fast_interpreter->destory();
363
+ return 0;
364
+ }
365
+
366
+
367
+ int main(int argc, char* argv[]) {
368
+ Args args = parse_args(argc, argv);
369
+ return invoke(args);
370
+ }
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/cpp/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/models/cutoff_yolov6m_fp16.qnn223.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b687e374d65441b8677cab88cb92a146fdd30b7369d7c186d2c4143be99d37f5
3
+ size 70849520
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, torch, cv2
2
+ import numpy as np
3
+ import time
4
+ import aidlite
5
+ import argparse
6
+ from utils import letterbox,plot_box_and_label,rescale,generate_colors,non_max_suppression
7
+ import torch
8
+
9
+
10
+ def process_image(path, img_size):
11
+ img_src = cv2.imread(path)
12
+ img_src = cv2.cvtColor(img_src,cv2.COLOR_BGR2RGB)
13
+ image = letterbox(img_src, img_size)[0]
14
+ new_h,new_w,_=image.shape
15
+ input_img = np.zeros((img_size[0], img_size[1], 3), np.uint8)
16
+ input_img[0:new_h, 0:new_w] = image
17
+ input_img = input_img.astype(np.float32)
18
+ input_img /= 255 # 0 - 255 to 0.0 - 1.0
19
+ input_img = np.expand_dims(input_img,0)
20
+ return image,input_img, img_src
21
+
22
+ def main(args):
23
+ print("Start main ... ...")
24
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
25
+ # aidlite.log_to_stderr()
26
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
27
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
28
+
29
+ size=640
30
+ out_size=8400
31
+ config = aidlite.Config.create_instance()
32
+ if config is None:
33
+ print("Create config failed !")
34
+ return False
35
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
36
+ if args.model_type.lower()=="qnn":
37
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN223
38
+ elif args.model_type.lower()=="snpe2" or args.model_type.lower()=="snpe":
39
+ config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
40
+
41
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
42
+ config.is_quantify_model = 1
43
+
44
+
45
+ model = aidlite.Model.create_instance(args.target_model)
46
+ if model is None:
47
+ print("Create model failed !")
48
+ return False
49
+ input_shapes = [[1, size, size, 3]]
50
+ output_shapes = [[1, out_size,80],[1, out_size,4]]
51
+ model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
52
+ output_shapes, aidlite.DataType.TYPE_FLOAT32)
53
+
54
+ interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
55
+ if interpreter is None:
56
+ print("build_interpretper_from_model_and_config failed !")
57
+ return None
58
+ result = interpreter.init()
59
+ if result != 0:
60
+ print(f"interpreter init failed !")
61
+ return False
62
+ result = interpreter.load_model()
63
+ if result != 0:
64
+ print("interpreter load model failed !")
65
+ return False
66
+ print("detect model load success!")
67
+
68
+ # image process
69
+ img_size=[size,size]
70
+ resize_img,input_img, img_src = process_image(args.imgs, img_size)
71
+
72
+ # qnn run
73
+ invoke_time=[]
74
+ for i in range(args.invoke_nums):
75
+ result = interpreter.set_input_tensor(0, input_img.data)
76
+ if result != 0:
77
+ print("interpreter set_input_tensor() failed")
78
+
79
+ t1=time.time()
80
+ result = interpreter.invoke()
81
+ cost_time = (time.time()-t1)*1000
82
+ invoke_time.append(cost_time)
83
+
84
+ if result != 0:
85
+ print("interpreter set_input_tensor() failed")
86
+
87
+ qnn_trans = interpreter.get_output_tensor(0).reshape(1,out_size,80)
88
+ qnn_mul = interpreter.get_output_tensor(1).reshape(1,out_size,4)
89
+
90
+ result = interpreter.destory()
91
+
92
+ ## time 统计
93
+ max_invoke_time = max(invoke_time)
94
+ min_invoke_time = min(invoke_time)
95
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
96
+ var_invoketime=np.var(invoke_time)
97
+ print("=======================================")
98
+ print(f"QNN inference {args.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}")
99
+ print("=======================================")
100
+
101
+ # 后处理
102
+ conf_thres =0.25 #@param {type:"number"}
103
+ iou_thres =0.45 #@param {type:"number"}
104
+ max_det= 1000#@param {type:"integer"}
105
+ agnostic_nms= False #@param {type:"boolean"}
106
+ classes =None
107
+ hide_labels = False #@param {type:"boolean"}
108
+ hide_conf= False #@param {type:"boolean"}
109
+
110
+ qnn_conf = np.ones((1,out_size,1))
111
+ qnn_predict=np.concatenate((qnn_mul,qnn_conf,qnn_trans), axis=2)
112
+ pred_results =torch.from_numpy(qnn_predict.copy())
113
+ det = non_max_suppression(pred_results, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)[0]
114
+
115
+ class_names=[ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
116
+ 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
117
+ 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
118
+ 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
119
+ 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
120
+ 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
121
+ 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
122
+ 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
123
+ 'hair drier', 'toothbrush' ]
124
+
125
+ img_ori = img_src.copy()
126
+ print(f"Detected {len(det)} targets.")
127
+ if len(det):
128
+ det[:, :4] = rescale(resize_img.shape[:2], det[:, :4], img_src.shape).round()
129
+ for *xyxy, conf, cls in reversed(det):
130
+ class_num = int(cls)
131
+ label = None if hide_labels else (class_names[class_num] if hide_conf else f'{class_names[class_num]} {conf:.2f}')
132
+ plot_box_and_label(img_ori, max(round(sum(img_ori.shape) / 2 * 0.003), 2), xyxy, label, color=generate_colors(class_num, True))
133
+
134
+ cv2.imwrite("./python/results.png",cv2.cvtColor(img_ori,cv2.COLOR_RGB2BGR))
135
+
136
+ def parser_args():
137
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
138
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov6m_fp16.qnn223.ctx.bin',help="inference model path")
139
+ parser.add_argument('--imgs',type=str,default='./python/test.png',help="Predict images path")
140
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
141
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
142
+ args = parser.parse_args()
143
+ return args
144
+
145
+ if __name__ == "__main__":
146
+ args = parser_args()
147
+ main(args)
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/python/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs8550_qnn2.23_fp16_aidlite/python/utils.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import torch
4
+ import torchvision
5
+
6
+ def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleup=True, stride=32):
7
+ '''Resize and pad image while meeting stride-multiple constraints.'''
8
+ shape = im.shape[:2] # current shape [height, width]
9
+ if isinstance(new_shape, int):
10
+ new_shape = (new_shape, new_shape)
11
+ elif isinstance(new_shape, list) and len(new_shape) == 1:
12
+ new_shape = (new_shape[0], new_shape[0])
13
+
14
+ # Scale ratio (new / old)
15
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
16
+ if not scaleup: # only scale down, do not scale up (for better val mAP)
17
+ r = min(r, 1.0)
18
+
19
+ # Compute padding
20
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
21
+ dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
22
+
23
+ if auto: # minimum rectangle
24
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
25
+
26
+ dw /= 2 # divide padding into 2 sides
27
+ dh /= 2
28
+
29
+ if shape[::-1] != new_unpad: # resize
30
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
31
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
32
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
33
+ im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
34
+
35
+ return im, r, (left, top)
36
+
37
+
38
+
39
+
40
+ def xywh2xyxy(x):
41
+ '''Convert boxes with shape [n, 4] from [x, y, w, h] to [x1, y1, x2, y2] where x1y1 is top-left, x2y2=bottom-right.'''
42
+ y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
43
+ y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
44
+ y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
45
+ y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
46
+ y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
47
+ return y
48
+
49
+ def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=False, max_det=300):
50
+ """Runs Non-Maximum Suppression (NMS) on inference results.
51
+ This code is borrowed from: https://github.com/ultralytics/yolov5/blob/47233e1698b89fc437a4fb9463c815e9171be955/utils/general.py#L775
52
+ Args:
53
+ prediction: (tensor), with shape [N, 5 + num_classes], N is the number of bboxes.
54
+ conf_thres: (float) confidence threshold.
55
+ iou_thres: (float) iou threshold.
56
+ classes: (None or list[int]), if a list is provided, nms only keep the classes you provide.
57
+ agnostic: (bool), when it is set to True, we do class-independent nms, otherwise, different class would do nms respectively.
58
+ multi_label: (bool), when it is set to True, one box can have multi labels, otherwise, one box only huave one label.
59
+ max_det:(int), max number of output bboxes.
60
+
61
+ Returns:
62
+ list of detections, echo item is one tensor with shape (num_boxes, 6), 6 is for [xyxy, conf, cls].
63
+ """
64
+
65
+ num_classes = prediction.shape[2] - 5 # number of classes
66
+ pred_candidates = torch.logical_and(prediction[..., 4] > conf_thres, torch.max(prediction[..., 5:], axis=-1)[0] > conf_thres) # candidates
67
+ # Check the parameters.
68
+ assert 0 <= conf_thres <= 1, f'conf_thresh must be in 0.0 to 1.0, however {conf_thres} is provided.'
69
+ assert 0 <= iou_thres <= 1, f'iou_thres must be in 0.0 to 1.0, however {iou_thres} is provided.'
70
+
71
+ # Function settings.
72
+ max_wh = 4096 # maximum box width and height
73
+ max_nms = 30000 # maximum number of boxes put into torchvision.ops.nms()
74
+ time_limit = 10.0 # quit the function when nms cost time exceed the limit time.
75
+ multi_label &= num_classes > 1 # multiple labels per box
76
+
77
+ output = [torch.zeros((0, 6), device=prediction.device)] * prediction.shape[0]
78
+ for img_idx, x in enumerate(prediction): # image index, image inference
79
+ x = x[pred_candidates[img_idx]] # confidence
80
+
81
+ # If no box remains, skip the next process.
82
+ if not x.shape[0]:
83
+ continue
84
+
85
+ # confidence multiply the objectness
86
+ x[:, 5:] *= x[:, 4:5] # conf = obj_conf * cls_conf
87
+
88
+ # (center x, center y, width, height) to (x1, y1, x2, y2)
89
+ box = xywh2xyxy(x[:, :4])
90
+
91
+ # Detections matrix's shape is (n,6), each row represents (xyxy, conf, cls)
92
+ if multi_label:
93
+ box_idx, class_idx = (x[:, 5:] > conf_thres).nonzero(as_tuple=False).T
94
+ x = torch.cat((box[box_idx], x[box_idx, class_idx + 5, None], class_idx[:, None].float()), 1)
95
+ else: # Only keep the class with highest scores.
96
+ conf, class_idx = x[:, 5:].max(1, keepdim=True)
97
+ x = torch.cat((box, conf, class_idx.float()), 1)[conf.view(-1) > conf_thres]
98
+
99
+ # Filter by class, only keep boxes whose category is in classes.
100
+ if classes is not None:
101
+ x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]
102
+
103
+ # Check shape
104
+ num_box = x.shape[0] # number of boxes
105
+ if not num_box: # no boxes kept.
106
+ continue
107
+ elif num_box > max_nms: # excess max boxes' number.
108
+ x = x[x[:, 4].argsort(descending=True)[:max_nms]] # sort by confidence
109
+
110
+ # Batched NMS
111
+ class_offset = x[:, 5:6] * (0 if agnostic else max_wh) # classes
112
+ boxes, scores = x[:, :4] + class_offset, x[:, 4] # boxes (offset by class), scores
113
+ keep_box_idx = torchvision.ops.nms(boxes, scores, iou_thres) # NMS
114
+ if keep_box_idx.shape[0] > max_det: # limit detections
115
+ keep_box_idx = keep_box_idx[:max_det]
116
+
117
+ output[img_idx] = x[keep_box_idx]
118
+
119
+ return output
120
+
121
+ def plot_box_and_label(image, lw, box, label='', color=(128, 128, 128), txt_color=(255, 255, 255), font=cv2.FONT_HERSHEY_COMPLEX):
122
+ # Add one xyxy box to image with label
123
+ p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
124
+ cv2.rectangle(image, p1, p2, color, thickness=lw, lineType=cv2.LINE_AA)
125
+ if label:
126
+ tf = max(lw - 1, 1) # font thickness
127
+ w, h = cv2.getTextSize(label, 0, fontScale=lw / 3, thickness=tf)[0] # text width, height
128
+ outside = p1[1] - h - 3 >= 0 # label fits outside box
129
+ p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3
130
+ cv2.rectangle(image, p1, p2, color, -1, cv2.LINE_AA) # filled
131
+ cv2.putText(image, label, (p1[0], p1[1] - 2 if outside else p1[1] + h + 2), font, lw / 3, txt_color,
132
+ thickness=tf, lineType=cv2.LINE_AA)
133
+
134
+ def generate_colors(i, bgr=False):
135
+ hex = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
136
+ '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
137
+ palette = []
138
+ for iter in hex:
139
+ h = '#' + iter
140
+ palette.append(tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4)))
141
+ num = len(palette)
142
+ color = palette[int(i) % num]
143
+ return (color[2], color[1], color[0]) if bgr else color
144
+
145
+ def rescale(ori_shape, boxes, target_shape):
146
+ '''Rescale the output to the original image shape'''
147
+ ratio = min(ori_shape[0] / target_shape[0], ori_shape[1] / target_shape[1])
148
+ padding = (ori_shape[1] - target_shape[1] * ratio) / 2, (ori_shape[0] - target_shape[0] * ratio) / 2
149
+
150
+ boxes[:, [0, 2]] -= padding[0]
151
+ boxes[:, [1, 3]] -= padding[1]
152
+ boxes[:, :4] /= ratio
153
+
154
+ boxes[:, 0].clamp_(0, target_shape[1]) # x1
155
+ boxes[:, 1].clamp_(0, target_shape[0]) # y1
156
+ boxes[:, 2].clamp_(0, target_shape[1]) # x2
157
+ boxes[:, 3].clamp_(0, target_shape[0]) # y2
158
+
159
+ return boxes
160
+
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ### Source model
3
+
4
+ - Input shape: 1x3x640x640
5
+ - Number of parameters: 33.24M
6
+ - Model size: 133.20MB
7
+ - Output shape: 1x8400x85
8
+
9
+ Source model repository: [yolov6](https://github.com/meituan/YOLOv6/tree/main)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: INT8
14
+ - Backend: QNN2.23
15
+ - Target Device: SNM972 QCS8550
16
+
17
+ ## Inference with AidLite SDK
18
+
19
+ ### SDK installation
20
+ 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/)
21
+
22
+ - install AidLite SDK
23
+
24
+ ```bash
25
+ # Install the appropriate version of the aidlite sdk
26
+ sudo aid-pkg update
27
+ sudo aid-pkg install aidlite-sdk
28
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
29
+ sudo aid-pkg install aidlite-{QNN VERSION}
30
+ # eg: Install QNN 2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
31
+ ```
32
+
33
+ - Verify AidLite SDK
34
+
35
+ ```bash
36
+ # aidlite sdk c++ check
37
+ python3 -c "import aidlite; print(aidlite.get_library_version())"
38
+
39
+ # aidlite sdk python check
40
+ python3 -c "import aidlite; print(aidlite.get_py_library_version())"
41
+ ```
42
+
43
+ ### Run demo
44
+
45
+ #### python
46
+ ```bash
47
+ cd yolov6m/model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite
48
+ python3 python/run_test.py --target_model ./models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem --imgs ./python/test.png --invoke_nums 10
49
+
50
+ ```
51
+
52
+ #### cpp
53
+ ```bash
54
+ cd yolov6m/model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp
55
+ mkdir build && cd build
56
+ cmake .. && make
57
+ ./run_test --target_model ../../models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem --imgs ../test.png --invoke_nums 10
58
+ ```
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required (VERSION 3.5)
2
+ project("run_test")
3
+
4
+ find_package(OpenCV REQUIRED)
5
+
6
+ message(STATUS "oPENCV Library status:")
7
+ message(STATUS ">version:${OpenCV_VERSION}")
8
+ message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
9
+
10
+ set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
11
+
12
+ include_directories(
13
+ /usr/local/include
14
+ /usr/include/opencv4
15
+ )
16
+
17
+ link_directories(
18
+ /usr/local/lib/
19
+ )
20
+
21
+ file(GLOB SRC_LISTS
22
+ ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ )
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp/main.cpp ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <opencv2/opencv.hpp>
6
+ #include <aidlux/aidlite/aidlite.hpp>
7
+ #include <vector>
8
+ #include <numeric>
9
+
10
+ const float INPUT_WIDTH = 640.0;
11
+ const float INPUT_HEIGHT = 640.0;
12
+ const float SCORE_THRESHOLD = 0.25;
13
+ const float NMS_THRESHOLD = 0.45;
14
+ const float CONFIDENCE_THRESHOLD = 0.25;
15
+ const uint32_t size = 640;
16
+ const uint32_t out_size = 8400;
17
+
18
+ const int FONT_FACE = cv::FONT_HERSHEY_SIMPLEX;
19
+ cv::Scalar WHITE = cv::Scalar(255,255,255);
20
+
21
+ const float FONT_SCALE = 1;
22
+ const int THICKNESS = 2;
23
+ using namespace Aidlux::Aidlite;
24
+
25
+ struct Args {
26
+ std::string target_model = "../../models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem";
27
+ std::string imgs = "../test.png";
28
+ int invoke_nums = 10;
29
+ std::string model_type = "QNN";
30
+ };
31
+
32
+ Args parse_args(int argc, char* argv[]) {
33
+ Args args;
34
+ for (int i = 1; i < argc; ++i) {
35
+ std::string arg = argv[i];
36
+ if (arg == "--target_model" && i + 1 < argc) {
37
+ args.target_model = argv[++i];
38
+ } else if (arg == "--imgs" && i + 1 < argc) {
39
+ args.imgs = argv[++i];
40
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
41
+ args.invoke_nums = std::stoi(argv[++i]);
42
+ } else if (arg == "--model_type" && i + 1 < argc) {
43
+ args.model_type = argv[++i];
44
+ }
45
+ }
46
+ return args;
47
+ }
48
+
49
+ std::string to_lower(const std::string& str) {
50
+ std::string lower_str = str;
51
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
52
+ return std::tolower(c);
53
+ });
54
+ return lower_str;
55
+ }
56
+
57
+
58
+ void concatenate(float* qnn_trans_data, float* qnn_mul_data, int batch, int num_elements, int trans_dim, int mul_dim, std::vector<float>& output) {
59
+ int out_dim = trans_dim + mul_dim + 1;
60
+ output.resize(batch * num_elements * out_dim);
61
+ for (int i = 0; i < batch * num_elements; ++i) {
62
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
63
+ float max_val = *std::max_element(&qnn_trans_data[i * trans_dim], &qnn_trans_data[i * trans_dim + trans_dim]);
64
+ output[i * out_dim + 4] = max_val;
65
+ std::memcpy(&output[i * out_dim + 5], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
66
+ }
67
+ }
68
+
69
+ cv::Mat letterbox(cv::Mat im, cv::Size new_shape = cv::Size(640, 640),
70
+ cv::Scalar color = cv::Scalar(114, 114, 114),
71
+ bool auto_pad = true, bool scaleup = true, int stride = 32) {
72
+ // current shape [height, width]
73
+ cv::Size shape = im.size();
74
+ int height = shape.height;
75
+ int width = shape.width;
76
+
77
+ if (new_shape.width == 0) {
78
+ new_shape = cv::Size(new_shape.height, new_shape.height);
79
+ }
80
+
81
+ // Scale ratio (new / old)
82
+ float r = std::min((float)new_shape.height / height, (float)new_shape.width / width);
83
+ if (!scaleup) {
84
+ // only scale down, do not scale up (for better val mAP)
85
+ r = std::min(r, 1.0f);
86
+ }
87
+
88
+ // Compute padding
89
+ cv::Size new_unpad(round(width * r), round(height * r));
90
+ int dw = new_shape.width - new_unpad.width;
91
+ int dh = new_shape.height - new_unpad.height;
92
+
93
+ // minimum rectangle
94
+ if (auto_pad) {
95
+ dw = dw % stride;
96
+ dh = dh % stride;
97
+ }
98
+
99
+ dw /= 2; // divide padding into 2 sides
100
+ dh /= 2;
101
+
102
+ // resize
103
+ if (cv::Size(width, height) != new_unpad) {
104
+ cv::resize(im, im, new_unpad, 0, 0, cv::INTER_LINEAR);
105
+ }
106
+
107
+ int top = round(dh - 0.1);
108
+ int bottom = round(dh + 0.1);
109
+ int left = round(dw - 0.1);
110
+ int right = round(dw + 0.1);
111
+
112
+ cv::copyMakeBorder(im, im, top, bottom, left, right, cv::BORDER_CONSTANT, color);
113
+ return im;
114
+ }
115
+ cv::Scalar generate_colors(int i, bool bgr = false) {
116
+ static const std::vector<std::string> hex_colors = {
117
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
118
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
119
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
120
+ "FF95C8", "FF37C7"
121
+ };
122
+
123
+ int num = hex_colors.size();
124
+ std::string hex = hex_colors[i % num];
125
+
126
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
127
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
128
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
129
+
130
+ if (bgr)
131
+ return cv::Scalar(b, g, r);
132
+ else
133
+ return cv::Scalar(r, g, b);
134
+ }
135
+
136
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
137
+ {
138
+ int baseLine;
139
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
140
+ int y = top - label_size.height - baseLine;
141
+ if (y < 0) {
142
+ y = top + label_size.height + baseLine;
143
+ }
144
+ cv::Point tlc(left, y);
145
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
146
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
147
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
148
+ }
149
+
150
+
151
+ cv::Mat post_process(cv::Mat &input_image, std::vector<float> &outputs, const std::vector<std::string> &class_name)
152
+ {
153
+ // Initialize vectors to hold respective outputs while unwrapping detections.
154
+ std::vector<int> class_ids;
155
+ std::vector<float> confidences;
156
+ std::vector<cv::Rect> boxes;
157
+
158
+ // Resizing factor.
159
+ float r = std::min(INPUT_WIDTH / (float)input_image.cols, INPUT_HEIGHT / (float)input_image.rows);
160
+ int new_unpad_w = round(input_image.cols * r);
161
+ int new_unpad_h = round(input_image.rows * r);
162
+ int dw = (int)INPUT_WIDTH - new_unpad_w;
163
+ int dh = (int)INPUT_HEIGHT - new_unpad_h;
164
+ dw /= 24;
165
+ dh /= 24;
166
+
167
+ // Iterate through outputs for each box prediction
168
+ for (int i = 0; i < outputs.size(); i+=85)
169
+ {
170
+ float confidence = outputs[i+4];
171
+ if (confidence >= CONFIDENCE_THRESHOLD)
172
+ {
173
+ // Create a 1x80 Mat and store class scores of 80 classes.
174
+ cv::Mat scores(1, class_name.size(), CV_32FC1, outputs.data() + i + 5);
175
+ cv::Point class_id;
176
+ double max_class_score;
177
+
178
+ // For multi-label, check each class score
179
+ for (int c = 0; c < class_name.size(); c++) {
180
+ float class_score = scores.at<float>(0, c);
181
+
182
+ // If class score is above threshold, consider this class for the box
183
+ if (class_score > SCORE_THRESHOLD) {
184
+ // Store class ID and confidence in the pre-defined respective vectors.
185
+ confidences.push_back(confidence * class_score); // Multiply with confidence
186
+ class_ids.push_back(c); // class index
187
+ // Center and box dimension.
188
+ float cx = outputs[i];
189
+ float cy = outputs[i+1];
190
+ float w = outputs[i+2];
191
+ float h = outputs[i+3];
192
+
193
+ float x0 = (cx - 0.5f * w - dw) / r;
194
+ float y0 = (cy - 0.5f * h - dh) / r;
195
+ float x1 = (cx + 0.5f * w - dw) / r;
196
+ float y1 = (cy + 0.5f * h - dh) / r;
197
+
198
+ int left = int(x0);
199
+ int top = int(y0);
200
+ int width = int(x1 - x0);
201
+ int height = int(y1 - y0);
202
+
203
+ // Store good detections in the boxes vector.
204
+ boxes.push_back(cv::Rect(left, top, width, height));
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ // Perform Non Maximum Suppression and draw predictions.
211
+ std::vector<int> indices;
212
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
213
+ printf("Detected {%ld} targets.\n", indices.size());
214
+
215
+ // Loop over NMS results and draw bounding boxes
216
+ for (int i = 0; i < indices.size(); i++)
217
+ {
218
+ int idx = indices[i];
219
+ cv::Rect box = boxes[idx];
220
+
221
+ int left = box.x;
222
+ int top = box.y;
223
+ int width = box.width;
224
+ int height = box.height;
225
+ cv::Scalar color = generate_colors(class_ids[idx]);
226
+ // Draw bounding box.
227
+ rectangle(input_image, cv::Point(left, top), cv::Point(left + width, top + height), color, 3*THICKNESS);
228
+
229
+ // Get the label for the class name and its confidence.
230
+ std::string label = cv::format("%.2f", confidences[idx]);
231
+ label = class_name[class_ids[idx]] + ":" + label;
232
+ // Draw class labels.
233
+ draw_label(input_image, label, left, top, color);
234
+ }
235
+ printf("Processing finished.\n");
236
+ return input_image;
237
+ }
238
+
239
+
240
+ int invoke(const Args& args) {
241
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
242
+ << "Image Path: " << args.imgs << "\n"
243
+ << "Inference Nums: " << args.invoke_nums << "\n"
244
+ << "Model Type: " << args.model_type << "\n";
245
+ Model* model = Model::create_instance(args.target_model);
246
+ if(model == nullptr){
247
+ printf("Create model failed !\n");
248
+ return EXIT_FAILURE;
249
+ }
250
+ Config* config = Config::create_instance();
251
+ if(config == nullptr){
252
+ printf("Create config failed !\n");
253
+ return EXIT_FAILURE;
254
+ }
255
+ config->implement_type = ImplementType::TYPE_LOCAL;
256
+ std::string model_type_lower = to_lower(args.model_type);
257
+ if (model_type_lower == "qnn"){
258
+ config->framework_type = FrameworkType::TYPE_QNN223;
259
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
260
+ config->framework_type = FrameworkType::TYPE_SNPE2;
261
+ }
262
+ config->accelerate_type = AccelerateType::TYPE_DSP;
263
+ config->is_quantify_model = 1;
264
+
265
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
266
+ std::vector<std::vector<uint32_t>> output_shapes = {{1, out_size, 80}, {1, out_size, 4}};
267
+ model->set_model_properties(input_shapes, DataType::TYPE_FLOAT32, output_shapes, DataType::TYPE_FLOAT32);
268
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
269
+ if(fast_interpreter == nullptr){
270
+ printf("build_interpretper_from_model_and_config failed !\n");
271
+ return EXIT_FAILURE;
272
+ }
273
+ int result = fast_interpreter->init();
274
+ if(result != EXIT_SUCCESS){
275
+ printf("interpreter->init() failed !\n");
276
+ return EXIT_FAILURE;
277
+ }
278
+ // load model
279
+ fast_interpreter->load_model();
280
+ if(result != EXIT_SUCCESS){
281
+ printf("interpreter->load_model() failed !\n");
282
+ return EXIT_FAILURE;
283
+ }
284
+ printf("detect model load success!\n");
285
+ cv::Size img_size(size, size);
286
+
287
+ cv::Mat img_src = cv::imread(args.imgs);
288
+ printf("img_src cols: %d, img_src rows: %d\n", img_src.cols, img_src.rows);
289
+ cv::Mat img_ori = img_src.clone();
290
+ cv::cvtColor(img_ori, img_ori, cv::COLOR_BGR2RGB);
291
+ cv::Mat resized_img = letterbox(img_ori, img_size);
292
+ cv::Mat input_img = cv::Mat::zeros(img_size, CV_32FC3);
293
+ resized_img.convertTo(resized_img, CV_32FC3, 1.0 / 255.0);
294
+ resized_img.copyTo(input_img(cv::Rect(0, 0, resized_img.cols, resized_img.rows)));
295
+ float *qnn_trans_data = nullptr;
296
+ float *qnn_mul_data = nullptr;
297
+
298
+ std::vector<float> invoke_time;
299
+ for (int i = 0; i < args.invoke_nums; ++i) {
300
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
301
+ if(result != EXIT_SUCCESS){
302
+ printf("interpreter->set_input_tensor() failed !\n");
303
+ return EXIT_FAILURE;
304
+ }
305
+ // 开始计时
306
+ auto t1 = std::chrono::high_resolution_clock::now();
307
+ result = fast_interpreter->invoke();
308
+ auto t2 = std::chrono::high_resolution_clock::now();
309
+ std::chrono::duration<double> cost_time = t2 - t1;
310
+ invoke_time.push_back(cost_time.count() * 1000);
311
+ if(result != EXIT_SUCCESS){
312
+ printf("interpreter->invoke() failed !\n");
313
+ return EXIT_FAILURE;
314
+ }
315
+ uint32_t out_data_1 = 0;
316
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_trans_data, &out_data_1);
317
+ if(result != EXIT_SUCCESS){
318
+ printf("interpreter->get_output_tensor() 1 failed !\n");
319
+ return EXIT_FAILURE;
320
+ }
321
+ uint32_t out_data_2 = 0;
322
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_mul_data, &out_data_2);
323
+ if(result != EXIT_SUCCESS){
324
+ printf("interpreter->get_output_tensor() 2 failed !\n");
325
+ return EXIT_FAILURE;
326
+ }
327
+ }
328
+
329
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
330
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
331
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
332
+ float var_invoketime = 0.0f;
333
+ for (auto time : invoke_time) {
334
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
335
+ }
336
+ var_invoketime /= args.invoke_nums;
337
+ printf("=======================================\n");
338
+ printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
339
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
340
+ printf("=======================================\n");
341
+
342
+ std::vector<std::string> class_list = {
343
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
344
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
345
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
346
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
347
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
348
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
349
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
350
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
351
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
352
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
353
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
354
+ "scissors", "teddy bear", "hair drier", "toothbrush"
355
+ };
356
+
357
+ // post process
358
+ std::vector<float> qnn_concat;
359
+ concatenate(qnn_trans_data, qnn_mul_data, 1, out_size, 80, 4, qnn_concat);
360
+ cv::Mat img = post_process(img_src, qnn_concat, class_list);
361
+ cv::imwrite("./results.png", img);
362
+ fast_interpreter->destory();
363
+ return 0;
364
+ }
365
+
366
+
367
+ int main(int argc, char* argv[]) {
368
+ Args args = parse_args(argc, argv);
369
+ return invoke(args);
370
+ }
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/cpp/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/models/cutoff_yolov6m_w8a8.qnn223.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8f0bb56df2017a4e7fcd2423204a7f15a4a596964e6cd5609f469d3bab8104c1
3
+ size 35596880
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/python/run_test.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, torch, cv2
2
+ import numpy as np
3
+ import time
4
+ import aidlite
5
+ import argparse
6
+ from utils import letterbox,plot_box_and_label,rescale,generate_colors,non_max_suppression
7
+ import torch
8
+
9
+
10
+ def process_image(path, img_size):
11
+ img_src = cv2.imread(path)
12
+ img_src = cv2.cvtColor(img_src,cv2.COLOR_BGR2RGB)
13
+ image = letterbox(img_src, img_size)[0]
14
+ new_h,new_w,_=image.shape
15
+ input_img = np.zeros((img_size[0], img_size[1], 3), np.uint8)
16
+ input_img[0:new_h, 0:new_w] = image
17
+ input_img = input_img.astype(np.float32)
18
+ input_img /= 255 # 0 - 255 to 0.0 - 1.0
19
+ input_img = np.expand_dims(input_img,0)
20
+ return image,input_img, img_src
21
+
22
+ def main(args):
23
+ print("Start main ... ...")
24
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
25
+ # aidlite.log_to_stderr()
26
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
27
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
28
+
29
+ size=640
30
+ out_size=8400
31
+ config = aidlite.Config.create_instance()
32
+ if config is None:
33
+ print("Create config failed !")
34
+ return False
35
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
36
+ if args.model_type.lower()=="qnn":
37
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN223
38
+ elif args.model_type.lower()=="snpe2" or args.model_type.lower()=="snpe":
39
+ config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
40
+
41
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
42
+ config.is_quantify_model = 1
43
+
44
+
45
+ model = aidlite.Model.create_instance(args.target_model)
46
+ if model is None:
47
+ print("Create model failed !")
48
+ return False
49
+ input_shapes = [[1, size, size, 3]]
50
+ output_shapes = [[1, out_size,80],[1, out_size,4]]
51
+ model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
52
+ output_shapes, aidlite.DataType.TYPE_FLOAT32)
53
+
54
+ interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
55
+ if interpreter is None:
56
+ print("build_interpretper_from_model_and_config failed !")
57
+ return None
58
+ result = interpreter.init()
59
+ if result != 0:
60
+ print(f"interpreter init failed !")
61
+ return False
62
+ result = interpreter.load_model()
63
+ if result != 0:
64
+ print("interpreter load model failed !")
65
+ return False
66
+ print("detect model load success!")
67
+
68
+ # image process
69
+ img_size=[size,size]
70
+ resize_img,input_img, img_src = process_image(args.imgs, img_size)
71
+
72
+ # qnn run
73
+ invoke_time=[]
74
+ for i in range(args.invoke_nums):
75
+ result = interpreter.set_input_tensor(0, input_img.data)
76
+ if result != 0:
77
+ print("interpreter set_input_tensor() failed")
78
+
79
+ t1=time.time()
80
+ result = interpreter.invoke()
81
+ cost_time = (time.time()-t1)*1000
82
+ invoke_time.append(cost_time)
83
+
84
+ if result != 0:
85
+ print("interpreter set_input_tensor() failed")
86
+
87
+ qnn_trans = interpreter.get_output_tensor(0).reshape(1,out_size,80)
88
+ qnn_mul = interpreter.get_output_tensor(1).reshape(1,out_size,4)
89
+
90
+ result = interpreter.destory()
91
+
92
+ ## time 统计
93
+ max_invoke_time = max(invoke_time)
94
+ min_invoke_time = min(invoke_time)
95
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
96
+ var_invoketime=np.var(invoke_time)
97
+ print("=======================================")
98
+ print(f"QNN inference {args.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}")
99
+ print("=======================================")
100
+
101
+ # 后处理
102
+ conf_thres =0.25 #@param {type:"number"}
103
+ iou_thres =0.45 #@param {type:"number"}
104
+ max_det= 1000#@param {type:"integer"}
105
+ agnostic_nms= False #@param {type:"boolean"}
106
+ classes =None
107
+ hide_labels = False #@param {type:"boolean"}
108
+ hide_conf= False #@param {type:"boolean"}
109
+
110
+ qnn_conf = np.ones((1,out_size,1))
111
+ qnn_predict=np.concatenate((qnn_mul,qnn_conf,qnn_trans), axis=2)
112
+ pred_results =torch.from_numpy(qnn_predict.copy())
113
+ det = non_max_suppression(pred_results, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)[0]
114
+
115
+ class_names=[ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
116
+ 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
117
+ 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
118
+ 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
119
+ 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
120
+ 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
121
+ 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
122
+ 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
123
+ 'hair drier', 'toothbrush' ]
124
+
125
+ img_ori = img_src.copy()
126
+ print(f"Detected {len(det)} targets.")
127
+ if len(det):
128
+ det[:, :4] = rescale(resize_img.shape[:2], det[:, :4], img_src.shape).round()
129
+ for *xyxy, conf, cls in reversed(det):
130
+ class_num = int(cls)
131
+ label = None if hide_labels else (class_names[class_num] if hide_conf else f'{class_names[class_num]} {conf:.2f}')
132
+ plot_box_and_label(img_ori, max(round(sum(img_ori.shape) / 2 * 0.003), 2), xyxy, label, color=generate_colors(class_num, True))
133
+
134
+ cv2.imwrite("./python/results.png",cv2.cvtColor(img_ori,cv2.COLOR_RGB2BGR))
135
+
136
+ def parser_args():
137
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
138
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov6m_w8a8.qnn223.ctx.bin',help="inference model path")
139
+ parser.add_argument('--imgs',type=str,default='./python/test.png',help="Predict images path")
140
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
141
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
142
+ args = parser.parse_args()
143
+ return args
144
+
145
+ if __name__ == "__main__":
146
+ args = parser_args()
147
+ main(args)
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/python/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs8550_qnn2.23_int8_aidlite/python/utils.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import torch
4
+ import torchvision
5
+
6
+ def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleup=True, stride=32):
7
+ '''Resize and pad image while meeting stride-multiple constraints.'''
8
+ shape = im.shape[:2] # current shape [height, width]
9
+ if isinstance(new_shape, int):
10
+ new_shape = (new_shape, new_shape)
11
+ elif isinstance(new_shape, list) and len(new_shape) == 1:
12
+ new_shape = (new_shape[0], new_shape[0])
13
+
14
+ # Scale ratio (new / old)
15
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
16
+ if not scaleup: # only scale down, do not scale up (for better val mAP)
17
+ r = min(r, 1.0)
18
+
19
+ # Compute padding
20
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
21
+ dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
22
+
23
+ if auto: # minimum rectangle
24
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
25
+
26
+ dw /= 2 # divide padding into 2 sides
27
+ dh /= 2
28
+
29
+ if shape[::-1] != new_unpad: # resize
30
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
31
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
32
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
33
+ im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
34
+
35
+ return im, r, (left, top)
36
+
37
+
38
+
39
+
40
+ def xywh2xyxy(x):
41
+ '''Convert boxes with shape [n, 4] from [x, y, w, h] to [x1, y1, x2, y2] where x1y1 is top-left, x2y2=bottom-right.'''
42
+ y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
43
+ y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
44
+ y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
45
+ y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
46
+ y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
47
+ return y
48
+
49
+ def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=False, max_det=300):
50
+ """Runs Non-Maximum Suppression (NMS) on inference results.
51
+ This code is borrowed from: https://github.com/ultralytics/yolov5/blob/47233e1698b89fc437a4fb9463c815e9171be955/utils/general.py#L775
52
+ Args:
53
+ prediction: (tensor), with shape [N, 5 + num_classes], N is the number of bboxes.
54
+ conf_thres: (float) confidence threshold.
55
+ iou_thres: (float) iou threshold.
56
+ classes: (None or list[int]), if a list is provided, nms only keep the classes you provide.
57
+ agnostic: (bool), when it is set to True, we do class-independent nms, otherwise, different class would do nms respectively.
58
+ multi_label: (bool), when it is set to True, one box can have multi labels, otherwise, one box only huave one label.
59
+ max_det:(int), max number of output bboxes.
60
+
61
+ Returns:
62
+ list of detections, echo item is one tensor with shape (num_boxes, 6), 6 is for [xyxy, conf, cls].
63
+ """
64
+
65
+ num_classes = prediction.shape[2] - 5 # number of classes
66
+ pred_candidates = torch.logical_and(prediction[..., 4] > conf_thres, torch.max(prediction[..., 5:], axis=-1)[0] > conf_thres) # candidates
67
+ # Check the parameters.
68
+ assert 0 <= conf_thres <= 1, f'conf_thresh must be in 0.0 to 1.0, however {conf_thres} is provided.'
69
+ assert 0 <= iou_thres <= 1, f'iou_thres must be in 0.0 to 1.0, however {iou_thres} is provided.'
70
+
71
+ # Function settings.
72
+ max_wh = 4096 # maximum box width and height
73
+ max_nms = 30000 # maximum number of boxes put into torchvision.ops.nms()
74
+ time_limit = 10.0 # quit the function when nms cost time exceed the limit time.
75
+ multi_label &= num_classes > 1 # multiple labels per box
76
+
77
+ output = [torch.zeros((0, 6), device=prediction.device)] * prediction.shape[0]
78
+ for img_idx, x in enumerate(prediction): # image index, image inference
79
+ x = x[pred_candidates[img_idx]] # confidence
80
+
81
+ # If no box remains, skip the next process.
82
+ if not x.shape[0]:
83
+ continue
84
+
85
+ # confidence multiply the objectness
86
+ x[:, 5:] *= x[:, 4:5] # conf = obj_conf * cls_conf
87
+
88
+ # (center x, center y, width, height) to (x1, y1, x2, y2)
89
+ box = xywh2xyxy(x[:, :4])
90
+
91
+ # Detections matrix's shape is (n,6), each row represents (xyxy, conf, cls)
92
+ if multi_label:
93
+ box_idx, class_idx = (x[:, 5:] > conf_thres).nonzero(as_tuple=False).T
94
+ x = torch.cat((box[box_idx], x[box_idx, class_idx + 5, None], class_idx[:, None].float()), 1)
95
+ else: # Only keep the class with highest scores.
96
+ conf, class_idx = x[:, 5:].max(1, keepdim=True)
97
+ x = torch.cat((box, conf, class_idx.float()), 1)[conf.view(-1) > conf_thres]
98
+
99
+ # Filter by class, only keep boxes whose category is in classes.
100
+ if classes is not None:
101
+ x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]
102
+
103
+ # Check shape
104
+ num_box = x.shape[0] # number of boxes
105
+ if not num_box: # no boxes kept.
106
+ continue
107
+ elif num_box > max_nms: # excess max boxes' number.
108
+ x = x[x[:, 4].argsort(descending=True)[:max_nms]] # sort by confidence
109
+
110
+ # Batched NMS
111
+ class_offset = x[:, 5:6] * (0 if agnostic else max_wh) # classes
112
+ boxes, scores = x[:, :4] + class_offset, x[:, 4] # boxes (offset by class), scores
113
+ keep_box_idx = torchvision.ops.nms(boxes, scores, iou_thres) # NMS
114
+ if keep_box_idx.shape[0] > max_det: # limit detections
115
+ keep_box_idx = keep_box_idx[:max_det]
116
+
117
+ output[img_idx] = x[keep_box_idx]
118
+
119
+ return output
120
+
121
+ def plot_box_and_label(image, lw, box, label='', color=(128, 128, 128), txt_color=(255, 255, 255), font=cv2.FONT_HERSHEY_COMPLEX):
122
+ # Add one xyxy box to image with label
123
+ p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
124
+ cv2.rectangle(image, p1, p2, color, thickness=lw, lineType=cv2.LINE_AA)
125
+ if label:
126
+ tf = max(lw - 1, 1) # font thickness
127
+ w, h = cv2.getTextSize(label, 0, fontScale=lw / 3, thickness=tf)[0] # text width, height
128
+ outside = p1[1] - h - 3 >= 0 # label fits outside box
129
+ p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3
130
+ cv2.rectangle(image, p1, p2, color, -1, cv2.LINE_AA) # filled
131
+ cv2.putText(image, label, (p1[0], p1[1] - 2 if outside else p1[1] + h + 2), font, lw / 3, txt_color,
132
+ thickness=tf, lineType=cv2.LINE_AA)
133
+
134
+ def generate_colors(i, bgr=False):
135
+ hex = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
136
+ '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
137
+ palette = []
138
+ for iter in hex:
139
+ h = '#' + iter
140
+ palette.append(tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4)))
141
+ num = len(palette)
142
+ color = palette[int(i) % num]
143
+ return (color[2], color[1], color[0]) if bgr else color
144
+
145
+ def rescale(ori_shape, boxes, target_shape):
146
+ '''Rescale the output to the original image shape'''
147
+ ratio = min(ori_shape[0] / target_shape[0], ori_shape[1] / target_shape[1])
148
+ padding = (ori_shape[1] - target_shape[1] * ratio) / 2, (ori_shape[0] - target_shape[0] * ratio) / 2
149
+
150
+ boxes[:, [0, 2]] -= padding[0]
151
+ boxes[:, [1, 3]] -= padding[1]
152
+ boxes[:, :4] /= ratio
153
+
154
+ boxes[:, 0].clamp_(0, target_shape[1]) # x1
155
+ boxes[:, 1].clamp_(0, target_shape[0]) # y1
156
+ boxes[:, 2].clamp_(0, target_shape[1]) # x2
157
+ boxes[:, 3].clamp_(0, target_shape[0]) # y2
158
+
159
+ return boxes
160
+
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ### Source model
3
+
4
+ - Input shape: 1x3x640x640
5
+ - Number of parameters: 33.24M
6
+ - Model size: 133.20MB
7
+ - Output shape: 1x8400x85
8
+
9
+ Source model repository: [yolov6](https://github.com/meituan/YOLOv6/tree/main)
10
+
11
+ ### Converted model
12
+
13
+ - Precision: W8A16
14
+ - Backend: QNN2.23
15
+ - Target Device: SNM972 QCS8550
16
+
17
+ ## Inference with AidLite SDK
18
+
19
+ ### SDK installation
20
+ 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/)
21
+
22
+ - install AidLite SDK
23
+
24
+ ```bash
25
+ # Install the appropriate version of the aidlite sdk
26
+ sudo aid-pkg update
27
+ sudo aid-pkg install aidlite-sdk
28
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
29
+ sudo aid-pkg install aidlite-{QNN VERSION}
30
+ # eg: Install QNN 2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
31
+ ```
32
+
33
+ - Verify AidLite SDK
34
+
35
+ ```bash
36
+ # aidlite sdk c++ check
37
+ python3 -c "import aidlite; print(aidlite.get_library_version())"
38
+
39
+ # aidlite sdk python check
40
+ python3 -c "import aidlite; print(aidlite.get_py_library_version())"
41
+ ```
42
+
43
+ ### Run demo
44
+
45
+ #### python
46
+ ```bash
47
+ cd yolov6m/model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite
48
+ python3 python/run_test.py --target_model ./models/cutoff_yolov6m_w8a16.qnn223.ctx.bin.aidem --imgs ./python/test.png --invoke_nums 10
49
+
50
+ ```
51
+
52
+ #### cpp
53
+ ```bash
54
+ cd yolov6m/model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp
55
+ mkdir build && cd build
56
+ cmake .. && make
57
+ ./run_test --target_model ../../models/cutoff_yolov6m_w8a16.qnn223.ctx.bin.aidem --imgs ../test.png --invoke_nums 10
58
+ ```
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required (VERSION 3.5)
2
+ project("run_test")
3
+
4
+ find_package(OpenCV REQUIRED)
5
+
6
+ message(STATUS "oPENCV Library status:")
7
+ message(STATUS ">version:${OpenCV_VERSION}")
8
+ message(STATUS "Include:${OpenCV_INCLUDE_DIRS}")
9
+
10
+ set(CMAKE_CXX_FLAGS "-Wno-error=deprecated-declarations -Wno-deprecated-declarations")
11
+
12
+ include_directories(
13
+ /usr/local/include
14
+ /usr/include/opencv4
15
+ )
16
+
17
+ link_directories(
18
+ /usr/local/lib/
19
+ )
20
+
21
+ file(GLOB SRC_LISTS
22
+ ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ )
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp/main.cpp ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <opencv2/opencv.hpp>
6
+ #include <aidlux/aidlite/aidlite.hpp>
7
+ #include <vector>
8
+ #include <numeric>
9
+
10
+ const float INPUT_WIDTH = 640.0;
11
+ const float INPUT_HEIGHT = 640.0;
12
+ const float SCORE_THRESHOLD = 0.25;
13
+ const float NMS_THRESHOLD = 0.45;
14
+ const float CONFIDENCE_THRESHOLD = 0.25;
15
+ const uint32_t size = 640;
16
+ const uint32_t out_size = 8400;
17
+
18
+ const int FONT_FACE = cv::FONT_HERSHEY_SIMPLEX;
19
+ cv::Scalar WHITE = cv::Scalar(255,255,255);
20
+
21
+ const float FONT_SCALE = 1;
22
+ const int THICKNESS = 2;
23
+ using namespace Aidlux::Aidlite;
24
+
25
+ struct Args {
26
+ std::string target_model = "../../models/cutoff_yolov6m_w8a16.qnn223.ctx.bin.aidem";
27
+ std::string imgs = "../test.png";
28
+ int invoke_nums = 10;
29
+ std::string model_type = "QNN";
30
+ };
31
+
32
+ Args parse_args(int argc, char* argv[]) {
33
+ Args args;
34
+ for (int i = 1; i < argc; ++i) {
35
+ std::string arg = argv[i];
36
+ if (arg == "--target_model" && i + 1 < argc) {
37
+ args.target_model = argv[++i];
38
+ } else if (arg == "--imgs" && i + 1 < argc) {
39
+ args.imgs = argv[++i];
40
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
41
+ args.invoke_nums = std::stoi(argv[++i]);
42
+ } else if (arg == "--model_type" && i + 1 < argc) {
43
+ args.model_type = argv[++i];
44
+ }
45
+ }
46
+ return args;
47
+ }
48
+
49
+ std::string to_lower(const std::string& str) {
50
+ std::string lower_str = str;
51
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
52
+ return std::tolower(c);
53
+ });
54
+ return lower_str;
55
+ }
56
+
57
+
58
+ void concatenate(float* qnn_trans_data, float* qnn_mul_data, int batch, int num_elements, int trans_dim, int mul_dim, std::vector<float>& output) {
59
+ int out_dim = trans_dim + mul_dim + 1;
60
+ output.resize(batch * num_elements * out_dim);
61
+ for (int i = 0; i < batch * num_elements; ++i) {
62
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
63
+ float max_val = *std::max_element(&qnn_trans_data[i * trans_dim], &qnn_trans_data[i * trans_dim + trans_dim]);
64
+ output[i * out_dim + 4] = max_val;
65
+ std::memcpy(&output[i * out_dim + 5], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
66
+ }
67
+ }
68
+
69
+ cv::Mat letterbox(cv::Mat im, cv::Size new_shape = cv::Size(640, 640),
70
+ cv::Scalar color = cv::Scalar(114, 114, 114),
71
+ bool auto_pad = true, bool scaleup = true, int stride = 32) {
72
+ // current shape [height, width]
73
+ cv::Size shape = im.size();
74
+ int height = shape.height;
75
+ int width = shape.width;
76
+
77
+ if (new_shape.width == 0) {
78
+ new_shape = cv::Size(new_shape.height, new_shape.height);
79
+ }
80
+
81
+ // Scale ratio (new / old)
82
+ float r = std::min((float)new_shape.height / height, (float)new_shape.width / width);
83
+ if (!scaleup) {
84
+ // only scale down, do not scale up (for better val mAP)
85
+ r = std::min(r, 1.0f);
86
+ }
87
+
88
+ // Compute padding
89
+ cv::Size new_unpad(round(width * r), round(height * r));
90
+ int dw = new_shape.width - new_unpad.width;
91
+ int dh = new_shape.height - new_unpad.height;
92
+
93
+ // minimum rectangle
94
+ if (auto_pad) {
95
+ dw = dw % stride;
96
+ dh = dh % stride;
97
+ }
98
+
99
+ dw /= 2; // divide padding into 2 sides
100
+ dh /= 2;
101
+
102
+ // resize
103
+ if (cv::Size(width, height) != new_unpad) {
104
+ cv::resize(im, im, new_unpad, 0, 0, cv::INTER_LINEAR);
105
+ }
106
+
107
+ int top = round(dh - 0.1);
108
+ int bottom = round(dh + 0.1);
109
+ int left = round(dw - 0.1);
110
+ int right = round(dw + 0.1);
111
+
112
+ cv::copyMakeBorder(im, im, top, bottom, left, right, cv::BORDER_CONSTANT, color);
113
+ return im;
114
+ }
115
+ cv::Scalar generate_colors(int i, bool bgr = false) {
116
+ static const std::vector<std::string> hex_colors = {
117
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
118
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
119
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
120
+ "FF95C8", "FF37C7"
121
+ };
122
+
123
+ int num = hex_colors.size();
124
+ std::string hex = hex_colors[i % num];
125
+
126
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
127
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
128
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
129
+
130
+ if (bgr)
131
+ return cv::Scalar(b, g, r);
132
+ else
133
+ return cv::Scalar(r, g, b);
134
+ }
135
+
136
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
137
+ {
138
+ int baseLine;
139
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
140
+ int y = top - label_size.height - baseLine;
141
+ if (y < 0) {
142
+ y = top + label_size.height + baseLine;
143
+ }
144
+ cv::Point tlc(left, y);
145
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
146
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
147
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
148
+ }
149
+
150
+
151
+ cv::Mat post_process(cv::Mat &input_image, std::vector<float> &outputs, const std::vector<std::string> &class_name)
152
+ {
153
+ // Initialize vectors to hold respective outputs while unwrapping detections.
154
+ std::vector<int> class_ids;
155
+ std::vector<float> confidences;
156
+ std::vector<cv::Rect> boxes;
157
+
158
+ // Resizing factor.
159
+ float r = std::min(INPUT_WIDTH / (float)input_image.cols, INPUT_HEIGHT / (float)input_image.rows);
160
+ int new_unpad_w = round(input_image.cols * r);
161
+ int new_unpad_h = round(input_image.rows * r);
162
+ int dw = (int)INPUT_WIDTH - new_unpad_w;
163
+ int dh = (int)INPUT_HEIGHT - new_unpad_h;
164
+ dw /= 24;
165
+ dh /= 24;
166
+
167
+ // Iterate through outputs for each box prediction
168
+ for (int i = 0; i < outputs.size(); i+=85)
169
+ {
170
+ float confidence = outputs[i+4];
171
+ if (confidence >= CONFIDENCE_THRESHOLD)
172
+ {
173
+ // Create a 1x80 Mat and store class scores of 80 classes.
174
+ cv::Mat scores(1, class_name.size(), CV_32FC1, outputs.data() + i + 5);
175
+ cv::Point class_id;
176
+ double max_class_score;
177
+
178
+ // For multi-label, check each class score
179
+ for (int c = 0; c < class_name.size(); c++) {
180
+ float class_score = scores.at<float>(0, c);
181
+
182
+ // If class score is above threshold, consider this class for the box
183
+ if (class_score > SCORE_THRESHOLD) {
184
+ // Store class ID and confidence in the pre-defined respective vectors.
185
+ confidences.push_back(confidence * class_score); // Multiply with confidence
186
+ class_ids.push_back(c); // class index
187
+ // Center and box dimension.
188
+ float cx = outputs[i];
189
+ float cy = outputs[i+1];
190
+ float w = outputs[i+2];
191
+ float h = outputs[i+3];
192
+
193
+ float x0 = (cx - 0.5f * w - dw) / r;
194
+ float y0 = (cy - 0.5f * h - dh) / r;
195
+ float x1 = (cx + 0.5f * w - dw) / r;
196
+ float y1 = (cy + 0.5f * h - dh) / r;
197
+
198
+ int left = int(x0);
199
+ int top = int(y0);
200
+ int width = int(x1 - x0);
201
+ int height = int(y1 - y0);
202
+
203
+ // Store good detections in the boxes vector.
204
+ boxes.push_back(cv::Rect(left, top, width, height));
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ // Perform Non Maximum Suppression and draw predictions.
211
+ std::vector<int> indices;
212
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
213
+ printf("Detected {%ld} targets.\n", indices.size());
214
+
215
+ // Loop over NMS results and draw bounding boxes
216
+ for (int i = 0; i < indices.size(); i++)
217
+ {
218
+ int idx = indices[i];
219
+ cv::Rect box = boxes[idx];
220
+
221
+ int left = box.x;
222
+ int top = box.y;
223
+ int width = box.width;
224
+ int height = box.height;
225
+ cv::Scalar color = generate_colors(class_ids[idx]);
226
+ // Draw bounding box.
227
+ rectangle(input_image, cv::Point(left, top), cv::Point(left + width, top + height), color, 3*THICKNESS);
228
+
229
+ // Get the label for the class name and its confidence.
230
+ std::string label = cv::format("%.2f", confidences[idx]);
231
+ label = class_name[class_ids[idx]] + ":" + label;
232
+ // Draw class labels.
233
+ draw_label(input_image, label, left, top, color);
234
+ }
235
+ printf("Processing finished.\n");
236
+ return input_image;
237
+ }
238
+
239
+
240
+ int invoke(const Args& args) {
241
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
242
+ << "Image Path: " << args.imgs << "\n"
243
+ << "Inference Nums: " << args.invoke_nums << "\n"
244
+ << "Model Type: " << args.model_type << "\n";
245
+ Model* model = Model::create_instance(args.target_model);
246
+ if(model == nullptr){
247
+ printf("Create model failed !\n");
248
+ return EXIT_FAILURE;
249
+ }
250
+ Config* config = Config::create_instance();
251
+ if(config == nullptr){
252
+ printf("Create config failed !\n");
253
+ return EXIT_FAILURE;
254
+ }
255
+ config->implement_type = ImplementType::TYPE_LOCAL;
256
+ std::string model_type_lower = to_lower(args.model_type);
257
+ if (model_type_lower == "qnn"){
258
+ config->framework_type = FrameworkType::TYPE_QNN223;
259
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
260
+ config->framework_type = FrameworkType::TYPE_SNPE2;
261
+ }
262
+ config->accelerate_type = AccelerateType::TYPE_DSP;
263
+ config->is_quantify_model = 1;
264
+
265
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
266
+ std::vector<std::vector<uint32_t>> output_shapes = {{1, out_size, 80}, {1, out_size, 4}};
267
+ model->set_model_properties(input_shapes, DataType::TYPE_FLOAT32, output_shapes, DataType::TYPE_FLOAT32);
268
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
269
+ if(fast_interpreter == nullptr){
270
+ printf("build_interpretper_from_model_and_config failed !\n");
271
+ return EXIT_FAILURE;
272
+ }
273
+ int result = fast_interpreter->init();
274
+ if(result != EXIT_SUCCESS){
275
+ printf("interpreter->init() failed !\n");
276
+ return EXIT_FAILURE;
277
+ }
278
+ // load model
279
+ fast_interpreter->load_model();
280
+ if(result != EXIT_SUCCESS){
281
+ printf("interpreter->load_model() failed !\n");
282
+ return EXIT_FAILURE;
283
+ }
284
+ printf("detect model load success!\n");
285
+ cv::Size img_size(size, size);
286
+
287
+ cv::Mat img_src = cv::imread(args.imgs);
288
+ printf("img_src cols: %d, img_src rows: %d\n", img_src.cols, img_src.rows);
289
+ cv::Mat img_ori = img_src.clone();
290
+ cv::cvtColor(img_ori, img_ori, cv::COLOR_BGR2RGB);
291
+ cv::Mat resized_img = letterbox(img_ori, img_size);
292
+ cv::Mat input_img = cv::Mat::zeros(img_size, CV_32FC3);
293
+ resized_img.convertTo(resized_img, CV_32FC3, 1.0 / 255.0);
294
+ resized_img.copyTo(input_img(cv::Rect(0, 0, resized_img.cols, resized_img.rows)));
295
+ float *qnn_trans_data = nullptr;
296
+ float *qnn_mul_data = nullptr;
297
+
298
+ std::vector<float> invoke_time;
299
+ for (int i = 0; i < args.invoke_nums; ++i) {
300
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
301
+ if(result != EXIT_SUCCESS){
302
+ printf("interpreter->set_input_tensor() failed !\n");
303
+ return EXIT_FAILURE;
304
+ }
305
+ // 开始计时
306
+ auto t1 = std::chrono::high_resolution_clock::now();
307
+ result = fast_interpreter->invoke();
308
+ auto t2 = std::chrono::high_resolution_clock::now();
309
+ std::chrono::duration<double> cost_time = t2 - t1;
310
+ invoke_time.push_back(cost_time.count() * 1000);
311
+ if(result != EXIT_SUCCESS){
312
+ printf("interpreter->invoke() failed !\n");
313
+ return EXIT_FAILURE;
314
+ }
315
+ uint32_t out_data_1 = 0;
316
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_trans_data, &out_data_1);
317
+ if(result != EXIT_SUCCESS){
318
+ printf("interpreter->get_output_tensor() 1 failed !\n");
319
+ return EXIT_FAILURE;
320
+ }
321
+ uint32_t out_data_2 = 0;
322
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_mul_data, &out_data_2);
323
+ if(result != EXIT_SUCCESS){
324
+ printf("interpreter->get_output_tensor() 2 failed !\n");
325
+ return EXIT_FAILURE;
326
+ }
327
+ }
328
+
329
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
330
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
331
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
332
+ float var_invoketime = 0.0f;
333
+ for (auto time : invoke_time) {
334
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
335
+ }
336
+ var_invoketime /= args.invoke_nums;
337
+ printf("=======================================\n");
338
+ printf("QNN inference %d times :\n --mean_invoke_time is %f \n --max_invoke_time is %f \n --min_invoke_time is %f \n --var_invoketime is %f\n",
339
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
340
+ printf("=======================================\n");
341
+
342
+ std::vector<std::string> class_list = {
343
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
344
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
345
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
346
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
347
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
348
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
349
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
350
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
351
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
352
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
353
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
354
+ "scissors", "teddy bear", "hair drier", "toothbrush"
355
+ };
356
+
357
+ // post process
358
+ std::vector<float> qnn_concat;
359
+ concatenate(qnn_trans_data, qnn_mul_data, 1, out_size, 80, 4, qnn_concat);
360
+ cv::Mat img = post_process(img_src, qnn_concat, class_list);
361
+ cv::imwrite("./results.png", img);
362
+ fast_interpreter->destory();
363
+ return 0;
364
+ }
365
+
366
+
367
+ int main(int argc, char* argv[]) {
368
+ Args args = parse_args(argc, argv);
369
+ return invoke(args);
370
+ }
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/cpp/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/models/cutoff_yolov6m_w8a16.qnn223.ctx.bin.aidem ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8e920a05c31f9b5cc85cd66035ff82bcf0ffe07378413039b2b7e8c43096f2f8
3
+ size 36018768
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, torch, cv2
2
+ import numpy as np
3
+ import time
4
+ import aidlite
5
+ import argparse
6
+ from utils import letterbox,plot_box_and_label,rescale,generate_colors,non_max_suppression
7
+ import torch
8
+
9
+
10
+ def process_image(path, img_size):
11
+ img_src = cv2.imread(path)
12
+ img_src = cv2.cvtColor(img_src,cv2.COLOR_BGR2RGB)
13
+ image = letterbox(img_src, img_size)[0]
14
+ new_h,new_w,_=image.shape
15
+ input_img = np.zeros((img_size[0], img_size[1], 3), np.uint8)
16
+ input_img[0:new_h, 0:new_w] = image
17
+ input_img = input_img.astype(np.float32)
18
+ input_img /= 255 # 0 - 255 to 0.0 - 1.0
19
+ input_img = np.expand_dims(input_img,0)
20
+ return image,input_img, img_src
21
+
22
+ def main(args):
23
+ print("Start main ... ...")
24
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
25
+ # aidlite.log_to_stderr()
26
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
27
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
28
+
29
+ size=640
30
+ out_size=8400
31
+ config = aidlite.Config.create_instance()
32
+ if config is None:
33
+ print("Create config failed !")
34
+ return False
35
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
36
+ if args.model_type.lower()=="qnn":
37
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN223
38
+ elif args.model_type.lower()=="snpe2" or args.model_type.lower()=="snpe":
39
+ config.framework_type = aidlite.FrameworkType.TYPE_SNPE2
40
+
41
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
42
+ config.is_quantify_model = 1
43
+
44
+
45
+ model = aidlite.Model.create_instance(args.target_model)
46
+ if model is None:
47
+ print("Create model failed !")
48
+ return False
49
+ input_shapes = [[1, size, size, 3]]
50
+ output_shapes = [[1, out_size,80],[1, out_size,4]]
51
+ model.set_model_properties(input_shapes, aidlite.DataType.TYPE_FLOAT32,
52
+ output_shapes, aidlite.DataType.TYPE_FLOAT32)
53
+
54
+ interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
55
+ if interpreter is None:
56
+ print("build_interpretper_from_model_and_config failed !")
57
+ return None
58
+ result = interpreter.init()
59
+ if result != 0:
60
+ print(f"interpreter init failed !")
61
+ return False
62
+ result = interpreter.load_model()
63
+ if result != 0:
64
+ print("interpreter load model failed !")
65
+ return False
66
+ print("detect model load success!")
67
+
68
+ # image process
69
+ img_size=[size,size]
70
+ resize_img,input_img, img_src = process_image(args.imgs, img_size)
71
+
72
+ # qnn run
73
+ invoke_time=[]
74
+ for i in range(args.invoke_nums):
75
+ result = interpreter.set_input_tensor(0, input_img.data)
76
+ if result != 0:
77
+ print("interpreter set_input_tensor() failed")
78
+
79
+ t1=time.time()
80
+ result = interpreter.invoke()
81
+ cost_time = (time.time()-t1)*1000
82
+ invoke_time.append(cost_time)
83
+
84
+ if result != 0:
85
+ print("interpreter set_input_tensor() failed")
86
+
87
+ qnn_trans = interpreter.get_output_tensor(0).reshape(1,out_size,80)
88
+ qnn_mul = interpreter.get_output_tensor(1).reshape(1,out_size,4)
89
+
90
+ result = interpreter.destory()
91
+
92
+ ## time 统计
93
+ max_invoke_time = max(invoke_time)
94
+ min_invoke_time = min(invoke_time)
95
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
96
+ var_invoketime=np.var(invoke_time)
97
+ print("=======================================")
98
+ print(f"QNN inference {args.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}")
99
+ print("=======================================")
100
+
101
+ # 后处理
102
+ conf_thres =0.25 #@param {type:"number"}
103
+ iou_thres =0.45 #@param {type:"number"}
104
+ max_det= 1000#@param {type:"integer"}
105
+ agnostic_nms= False #@param {type:"boolean"}
106
+ classes =None
107
+ hide_labels = False #@param {type:"boolean"}
108
+ hide_conf= False #@param {type:"boolean"}
109
+
110
+ qnn_conf = np.ones((1,out_size,1))
111
+ qnn_predict=np.concatenate((qnn_mul,qnn_conf,qnn_trans), axis=2)
112
+ pred_results =torch.from_numpy(qnn_predict.copy())
113
+ det = non_max_suppression(pred_results, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)[0]
114
+
115
+ class_names=[ 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
116
+ 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
117
+ 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
118
+ 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
119
+ 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
120
+ 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
121
+ 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
122
+ 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
123
+ 'hair drier', 'toothbrush' ]
124
+
125
+ img_ori = img_src.copy()
126
+ print(f"Detected {len(det)} targets.")
127
+ if len(det):
128
+ det[:, :4] = rescale(resize_img.shape[:2], det[:, :4], img_src.shape).round()
129
+ for *xyxy, conf, cls in reversed(det):
130
+ class_num = int(cls)
131
+ label = None if hide_labels else (class_names[class_num] if hide_conf else f'{class_names[class_num]} {conf:.2f}')
132
+ plot_box_and_label(img_ori, max(round(sum(img_ori.shape) / 2 * 0.003), 2), xyxy, label, color=generate_colors(class_num, True))
133
+
134
+ cv2.imwrite("./python/results.png",cv2.cvtColor(img_ori,cv2.COLOR_RGB2BGR))
135
+
136
+ def parser_args():
137
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
138
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov6m_w8a16.qnn223.ctx.bin.aidem',help="inference model path")
139
+ parser.add_argument('--imgs',type=str,default='./python/test.png',help="Predict images path")
140
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
141
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
142
+ args = parser.parse_args()
143
+ return args
144
+
145
+ if __name__ == "__main__":
146
+ args = parser_args()
147
+ main(args)
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/python/test.png ADDED

Git LFS Details

  • SHA256: 7c95b20b95830c48c48c1ea3a004b3cc5a392672a3ea130a4eb41db5664ebfe5
  • Pointer size: 131 Bytes
  • Size of remote file: 970 kB
model_farm_yolov6m_qcs8550_qnn2.23_w8a16_aidlite/python/utils.py ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import torch
4
+ import torchvision
5
+
6
+ def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleup=True, stride=32):
7
+ '''Resize and pad image while meeting stride-multiple constraints.'''
8
+ shape = im.shape[:2] # current shape [height, width]
9
+ if isinstance(new_shape, int):
10
+ new_shape = (new_shape, new_shape)
11
+ elif isinstance(new_shape, list) and len(new_shape) == 1:
12
+ new_shape = (new_shape[0], new_shape[0])
13
+
14
+ # Scale ratio (new / old)
15
+ r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
16
+ if not scaleup: # only scale down, do not scale up (for better val mAP)
17
+ r = min(r, 1.0)
18
+
19
+ # Compute padding
20
+ new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))
21
+ dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding
22
+
23
+ if auto: # minimum rectangle
24
+ dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding
25
+
26
+ dw /= 2 # divide padding into 2 sides
27
+ dh /= 2
28
+
29
+ if shape[::-1] != new_unpad: # resize
30
+ im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
31
+ top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
32
+ left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
33
+ im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border
34
+
35
+ return im, r, (left, top)
36
+
37
+
38
+
39
+
40
+ def xywh2xyxy(x):
41
+ '''Convert boxes with shape [n, 4] from [x, y, w, h] to [x1, y1, x2, y2] where x1y1 is top-left, x2y2=bottom-right.'''
42
+ y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
43
+ y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
44
+ y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
45
+ y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
46
+ y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
47
+ return y
48
+
49
+ def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, multi_label=False, max_det=300):
50
+ """Runs Non-Maximum Suppression (NMS) on inference results.
51
+ This code is borrowed from: https://github.com/ultralytics/yolov5/blob/47233e1698b89fc437a4fb9463c815e9171be955/utils/general.py#L775
52
+ Args:
53
+ prediction: (tensor), with shape [N, 5 + num_classes], N is the number of bboxes.
54
+ conf_thres: (float) confidence threshold.
55
+ iou_thres: (float) iou threshold.
56
+ classes: (None or list[int]), if a list is provided, nms only keep the classes you provide.
57
+ agnostic: (bool), when it is set to True, we do class-independent nms, otherwise, different class would do nms respectively.
58
+ multi_label: (bool), when it is set to True, one box can have multi labels, otherwise, one box only huave one label.
59
+ max_det:(int), max number of output bboxes.
60
+
61
+ Returns:
62
+ list of detections, echo item is one tensor with shape (num_boxes, 6), 6 is for [xyxy, conf, cls].
63
+ """
64
+
65
+ num_classes = prediction.shape[2] - 5 # number of classes
66
+ pred_candidates = torch.logical_and(prediction[..., 4] > conf_thres, torch.max(prediction[..., 5:], axis=-1)[0] > conf_thres) # candidates
67
+ # Check the parameters.
68
+ assert 0 <= conf_thres <= 1, f'conf_thresh must be in 0.0 to 1.0, however {conf_thres} is provided.'
69
+ assert 0 <= iou_thres <= 1, f'iou_thres must be in 0.0 to 1.0, however {iou_thres} is provided.'
70
+
71
+ # Function settings.
72
+ max_wh = 4096 # maximum box width and height
73
+ max_nms = 30000 # maximum number of boxes put into torchvision.ops.nms()
74
+ time_limit = 10.0 # quit the function when nms cost time exceed the limit time.
75
+ multi_label &= num_classes > 1 # multiple labels per box
76
+
77
+ output = [torch.zeros((0, 6), device=prediction.device)] * prediction.shape[0]
78
+ for img_idx, x in enumerate(prediction): # image index, image inference
79
+ x = x[pred_candidates[img_idx]] # confidence
80
+
81
+ # If no box remains, skip the next process.
82
+ if not x.shape[0]:
83
+ continue
84
+
85
+ # confidence multiply the objectness
86
+ x[:, 5:] *= x[:, 4:5] # conf = obj_conf * cls_conf
87
+
88
+ # (center x, center y, width, height) to (x1, y1, x2, y2)
89
+ box = xywh2xyxy(x[:, :4])
90
+
91
+ # Detections matrix's shape is (n,6), each row represents (xyxy, conf, cls)
92
+ if multi_label:
93
+ box_idx, class_idx = (x[:, 5:] > conf_thres).nonzero(as_tuple=False).T
94
+ x = torch.cat((box[box_idx], x[box_idx, class_idx + 5, None], class_idx[:, None].float()), 1)
95
+ else: # Only keep the class with highest scores.
96
+ conf, class_idx = x[:, 5:].max(1, keepdim=True)
97
+ x = torch.cat((box, conf, class_idx.float()), 1)[conf.view(-1) > conf_thres]
98
+
99
+ # Filter by class, only keep boxes whose category is in classes.
100
+ if classes is not None:
101
+ x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]
102
+
103
+ # Check shape
104
+ num_box = x.shape[0] # number of boxes
105
+ if not num_box: # no boxes kept.
106
+ continue
107
+ elif num_box > max_nms: # excess max boxes' number.
108
+ x = x[x[:, 4].argsort(descending=True)[:max_nms]] # sort by confidence
109
+
110
+ # Batched NMS
111
+ class_offset = x[:, 5:6] * (0 if agnostic else max_wh) # classes
112
+ boxes, scores = x[:, :4] + class_offset, x[:, 4] # boxes (offset by class), scores
113
+ keep_box_idx = torchvision.ops.nms(boxes, scores, iou_thres) # NMS
114
+ if keep_box_idx.shape[0] > max_det: # limit detections
115
+ keep_box_idx = keep_box_idx[:max_det]
116
+
117
+ output[img_idx] = x[keep_box_idx]
118
+
119
+ return output
120
+
121
+ def plot_box_and_label(image, lw, box, label='', color=(128, 128, 128), txt_color=(255, 255, 255), font=cv2.FONT_HERSHEY_COMPLEX):
122
+ # Add one xyxy box to image with label
123
+ p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))
124
+ cv2.rectangle(image, p1, p2, color, thickness=lw, lineType=cv2.LINE_AA)
125
+ if label:
126
+ tf = max(lw - 1, 1) # font thickness
127
+ w, h = cv2.getTextSize(label, 0, fontScale=lw / 3, thickness=tf)[0] # text width, height
128
+ outside = p1[1] - h - 3 >= 0 # label fits outside box
129
+ p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3
130
+ cv2.rectangle(image, p1, p2, color, -1, cv2.LINE_AA) # filled
131
+ cv2.putText(image, label, (p1[0], p1[1] - 2 if outside else p1[1] + h + 2), font, lw / 3, txt_color,
132
+ thickness=tf, lineType=cv2.LINE_AA)
133
+
134
+ def generate_colors(i, bgr=False):
135
+ hex = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
136
+ '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
137
+ palette = []
138
+ for iter in hex:
139
+ h = '#' + iter
140
+ palette.append(tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4)))
141
+ num = len(palette)
142
+ color = palette[int(i) % num]
143
+ return (color[2], color[1], color[0]) if bgr else color
144
+
145
+ def rescale(ori_shape, boxes, target_shape):
146
+ '''Rescale the output to the original image shape'''
147
+ ratio = min(ori_shape[0] / target_shape[0], ori_shape[1] / target_shape[1])
148
+ padding = (ori_shape[1] - target_shape[1] * ratio) / 2, (ori_shape[0] - target_shape[0] * ratio) / 2
149
+
150
+ boxes[:, [0, 2]] -= padding[0]
151
+ boxes[:, [1, 3]] -= padding[1]
152
+ boxes[:, :4] /= ratio
153
+
154
+ boxes[:, 0].clamp_(0, target_shape[1]) # x1
155
+ boxes[:, 1].clamp_(0, target_shape[0]) # y1
156
+ boxes[:, 2].clamp_(0, target_shape[1]) # x2
157
+ boxes[:, 3].clamp_(0, target_shape[0]) # y2
158
+
159
+ return boxes
160
+