lonalala commited on
Commit
7567221
·
verified ·
1 Parent(s): 4e1074d

Upload 27 files

Browse files
Files changed (27) hide show
  1. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/README.md +59 -0
  2. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/cpp/CMakeLists.txt +30 -0
  3. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/cpp/bus.jpg +3 -0
  4. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/cpp/main.cpp +349 -0
  5. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/models/cutoff_yolov8s_w8a8.qnn216.ctx.bin +3 -0
  6. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/bus.jpg +3 -0
  7. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/run_test.py +30 -0
  8. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/utils.py +123 -0
  9. model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/yolov8s.py +86 -0
  10. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/README.md +59 -0
  11. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/cpp/CMakeLists.txt +30 -0
  12. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/cpp/bus.jpg +3 -0
  13. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/cpp/main.cpp +349 -0
  14. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/models/cutoff_yolov8s_fp16.qnn216.ctx.bin +3 -0
  15. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/bus.jpg +3 -0
  16. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/run_test.py +30 -0
  17. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/utils.py +123 -0
  18. model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/yolov8s.py +86 -0
  19. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/README.md +59 -0
  20. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/cpp/CMakeLists.txt +30 -0
  21. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/cpp/bus.jpg +3 -0
  22. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/cpp/main.cpp +349 -0
  23. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/models/cutoff_yolov8s_w8a8.qnn216.ctx.bin +3 -0
  24. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/bus.jpg +3 -0
  25. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/run_test.py +30 -0
  26. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/utils.py +123 -0
  27. model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/yolov8s.py +86 -0
model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/README.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ### Source model
3
+ - Input shape: 640x640
4
+ - Number of parameters: 10.65M
5
+ - Model size: 42.7M
6
+ - Output shape: 1x84x8400
7
+
8
+ Source model repository: [yolov8](https://github.com/ultralytics/ultralytics)
9
+
10
+ ### Converted model
11
+
12
+ - Precision: INT8
13
+ - Backend: QNN2.16
14
+ - Target Device: FV01 QCS6490
15
+
16
+ ## Model Conversion Reference
17
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/04384e46-ee9f-4c6d-875b-daa4702aa6d0)
18
+
19
+ ## Inference with AidLite SDK
20
+
21
+ ### SDK installation
22
+ 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/)
23
+
24
+ - install AidLite SDK
25
+
26
+ ```bash
27
+ # Install the appropriate version of the aidlite sdk
28
+ sudo aid-pkg update
29
+ sudo aid-pkg install aidlite-sdk
30
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
31
+ sudo aid-pkg install aidlite-{QNN VERSION}
32
+ # eg: Install QNN 2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
33
+ ```
34
+
35
+ - Verify AidLite SDK
36
+
37
+ ```bash
38
+ # aidlite sdk c++ check
39
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
40
+
41
+ # aidlite sdk python check
42
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
43
+ ```
44
+
45
+ ### Run Demo
46
+
47
+ #### python
48
+ ```bash
49
+ cd model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite
50
+ python3 python/run_test.py --target_model ./models/cutoff_yolov8s_w8a8.qnn216.ctx.bin --imgs ./python/bus.jpg --invoke_nums 10
51
+ ```
52
+
53
+ #### cpp
54
+ ```bash
55
+ cd model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/cpp
56
+ mkdir -p build && cd build
57
+ cmake .. && make
58
+ ./run_test --target_model ../../models/cutoff_yolov8s_w8a8.qnn216.ctx.bin --imgs ../bus.jpg --invoke_nums 10
59
+ ```
model_farm_yolov8s_qcs6490_qnn2.16_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_yolov8s_qcs6490_qnn2.16_int8_aidlite/cpp/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/cpp/main.cpp ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 = 0.75;
22
+ const int THICKNESS = 1;
23
+
24
+ const std::vector<std::string> class_list = {
25
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
26
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
27
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
28
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
29
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
30
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
31
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
32
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
33
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
34
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
35
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
36
+ "scissors", "teddy bear", "hair drier", "toothbrush"
37
+ };
38
+
39
+ using namespace Aidlux::Aidlite;
40
+
41
+ struct Args {
42
+ std::string target_model = "../../models/cutoff_yolov8s_w8a8.qnn216.ctx.bin.aidem";
43
+ std::string imgs = "../bus.jpg";
44
+ int invoke_nums = 10;
45
+ std::string model_type = "QNN";
46
+ };
47
+
48
+ Args parse_args(int argc, char* argv[]) {
49
+ Args args;
50
+ for (int i = 1; i < argc; ++i) {
51
+ std::string arg = argv[i];
52
+ if (arg == "--target_model" && i + 1 < argc) {
53
+ args.target_model = argv[++i];
54
+ } else if (arg == "--imgs" && i + 1 < argc) {
55
+ args.imgs = argv[++i];
56
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
57
+ args.invoke_nums = std::stoi(argv[++i]);
58
+ } else if (arg == "--model_type" && i + 1 < argc) {
59
+ args.model_type = argv[++i];
60
+ }
61
+ }
62
+ return args;
63
+ }
64
+
65
+ std::string to_lower(const std::string& str) {
66
+ std::string lower_str = str;
67
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
68
+ return std::tolower(c);
69
+ });
70
+ return lower_str;
71
+ }
72
+
73
+
74
+ 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) {
75
+ int out_dim = trans_dim + mul_dim + 1;
76
+ output.resize(batch * num_elements * out_dim);
77
+ for (int i = 0; i < batch * num_elements; ++i) {
78
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
79
+ float max_val = *std::max_element(&qnn_trans_data[i * trans_dim], &qnn_trans_data[i * trans_dim + trans_dim]);
80
+ output[i * out_dim + 4] = max_val;
81
+ std::memcpy(&output[i * out_dim + 5], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
82
+ }
83
+ }
84
+
85
+ void transformData(const float* input, float* output, int C, int N) {
86
+ for (int c = 0; c < C; ++c) {
87
+ for (int n = 0; n < N; ++n) {
88
+ output[n * C + c] = input[c * N + n];
89
+ }
90
+ }
91
+ }
92
+
93
+ double img_process(cv::Mat frame, cv::Mat &img_input, int size) {
94
+ cv::Mat img_processed = frame.clone();
95
+ int height = img_processed.rows;
96
+ int width = img_processed.cols;
97
+ int length = std::max(height, width);
98
+ double scala = static_cast<double>(length) / size;
99
+
100
+ cv::Mat image = cv::Mat::zeros(cv::Size(length, length), CV_8UC3);
101
+ img_processed.copyTo(image(cv::Rect(0, 0, width, height)));
102
+
103
+ cv::cvtColor(image, img_input, cv::COLOR_BGR2RGB);
104
+ cv::resize(img_input, img_input, cv::Size(size, size));
105
+
106
+ cv::Mat mean_data = cv::Mat::zeros(img_input.size(), CV_32FC3);
107
+ cv::Mat std_data(img_input.size(), CV_32FC3, cv::Scalar(255, 255, 255));
108
+ img_input.convertTo(img_input, CV_32FC3);
109
+ img_input = (img_input - mean_data) / std_data;
110
+ return scala;
111
+ }
112
+
113
+
114
+ cv::Scalar generate_colors(int i, bool bgr = false) {
115
+ static const std::vector<std::string> hex_colors = {
116
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
117
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
118
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
119
+ "FF95C8", "FF37C7"
120
+ };
121
+
122
+ int num = hex_colors.size();
123
+ std::string hex = hex_colors[i % num];
124
+
125
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
126
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
127
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
128
+
129
+ if (bgr)
130
+ return cv::Scalar(b, g, r);
131
+ else
132
+ return cv::Scalar(r, g, b);
133
+ }
134
+
135
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
136
+ {
137
+ int baseLine;
138
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
139
+ int y = top - label_size.height - baseLine;
140
+ if (y < 0) {
141
+ y = top ;
142
+ }
143
+ cv::Point tlc(left, y);
144
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
145
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
146
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
147
+ }
148
+
149
+
150
+ cv::Mat post_process(cv::Mat &input_image, std::vector<float> &outputs, const std::vector<std::string> &class_name, const double ratio)
151
+ {
152
+ // Initialize vectors to hold respective outputs while unwrapping detections.
153
+ std::vector<int> class_ids;
154
+ std::vector<float> confidences;
155
+ std::vector<cv::Rect> boxes;
156
+
157
+ // Iterate through outputs for each box prediction
158
+ for (int i = 0; i < outputs.size(); i+=85)
159
+ {
160
+ float confidence = outputs[i+4];
161
+ if (confidence >= CONFIDENCE_THRESHOLD)
162
+ {
163
+ // Create a 1x80 Mat and store class scores of 80 classes.
164
+ cv::Mat scores(1, class_name.size(), CV_32FC1, outputs.data() + i + 5);
165
+ cv::Point class_id;
166
+ double max_class_score;
167
+
168
+ // For multi-label, check each class score
169
+ for (int c = 0; c < class_name.size(); c++) {
170
+ float class_score = scores.at<float>(0, c);
171
+
172
+ // If class score is above threshold, consider this class for the box
173
+ if (class_score > SCORE_THRESHOLD) {
174
+ // Store class ID and confidence in the pre-defined respective vectors.
175
+ confidences.push_back(confidence * class_score); // Multiply with confidence
176
+ class_ids.push_back(c); // class index
177
+ // Center and box dimension.
178
+ float cx = outputs[i];
179
+ float cy = outputs[i+1];
180
+ float w = outputs[i+2];
181
+ float h = outputs[i+3];
182
+
183
+ int left = int((cx - 0.5 * w) * ratio);
184
+ int top = int((cy - 0.5 * h) * ratio);
185
+ int width = int(w * ratio);
186
+ int height = int(h * ratio);
187
+
188
+ // Store good detections in the boxes vector.
189
+ boxes.push_back(cv::Rect(left, top, width, height));
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ // Perform Non Maximum Suppression and draw predictions.
196
+ std::vector<int> indices;
197
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
198
+ printf("Detected {%ld} targets.\n", indices.size());
199
+
200
+ // Loop over NMS results and draw bounding boxes
201
+ for (int i = 0; i < indices.size(); i++)
202
+ {
203
+ int idx = indices[i];
204
+ cv::Rect box = boxes[idx];
205
+
206
+ int left = box.x;
207
+ int top = box.y;
208
+ int width = box.width;
209
+ int height = box.height;
210
+ cv::Scalar color = generate_colors(class_ids[idx]);
211
+ // Draw bounding box.
212
+ rectangle(input_image, cv::Point(left, top), cv::Point(left + width, top + height), color, 2*THICKNESS);
213
+
214
+ // Get the label for the class name and its confidence.
215
+ std::string label = cv::format("%.2f", confidences[idx]);
216
+ label = class_name[class_ids[idx]] + ":" + label;
217
+ // Draw class labels.
218
+ draw_label(input_image, label, left, top, color);
219
+ }
220
+ printf("Processing finished.\n");
221
+ return input_image;
222
+ }
223
+
224
+ int invoke(const Args& args) {
225
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
226
+ << "Image Path: " << args.imgs << "\n"
227
+ << "Inference Nums: " << args.invoke_nums << "\n"
228
+ << "Model Type: " << args.model_type << "\n";
229
+ Model* model = Model::create_instance(args.target_model);
230
+ if(model == nullptr){
231
+ printf("Create model failed !\n");
232
+ return EXIT_FAILURE;
233
+ }
234
+ Config* config = Config::create_instance();
235
+ if(config == nullptr){
236
+ printf("Create config failed !\n");
237
+ return EXIT_FAILURE;
238
+ }
239
+ config->implement_type = ImplementType::TYPE_LOCAL;
240
+ std::string model_type_lower = to_lower(args.model_type);
241
+ if (model_type_lower == "qnn"){
242
+ config->framework_type = FrameworkType::TYPE_QNN;
243
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
244
+ config->framework_type = FrameworkType::TYPE_SNPE2;
245
+ }
246
+ config->accelerate_type = AccelerateType::TYPE_DSP;
247
+ config->is_quantify_model = 1;
248
+
249
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
250
+ std::vector<std::vector<uint32_t>> output_shapes = {{1, 4, out_size}, {1, 80, out_size}};
251
+ model->set_model_properties(input_shapes, DataType::TYPE_FLOAT32, output_shapes, DataType::TYPE_FLOAT32);
252
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
253
+ if(fast_interpreter == nullptr){
254
+ printf("build_interpretper_from_model_and_config failed !\n");
255
+ return EXIT_FAILURE;
256
+ }
257
+ int result = fast_interpreter->init();
258
+ if(result != EXIT_SUCCESS){
259
+ printf("interpreter->init() failed !\n");
260
+ return EXIT_FAILURE;
261
+ }
262
+ // load model
263
+ fast_interpreter->load_model();
264
+ if(result != EXIT_SUCCESS){
265
+ printf("interpreter->load_model() failed !\n");
266
+ return EXIT_FAILURE;
267
+ }
268
+ printf("detect model load success!\n");
269
+
270
+ cv::Mat frame = cv::imread(args.imgs);
271
+ if (frame.empty()) {
272
+ printf("detect image load failed!\n");
273
+ return 1;
274
+ }
275
+ printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
276
+ cv::Mat input_img;
277
+ double scale = img_process(frame, input_img, size);
278
+ if (input_img.empty()) {
279
+ printf("detect input_img load failed!\n");
280
+ return 1;
281
+ }
282
+
283
+ float *qnn_trans_data = nullptr;
284
+ float *qnn_mul_data = nullptr;
285
+
286
+ std::vector<float> invoke_time;
287
+ for (int i = 0; i < args.invoke_nums; ++i) {
288
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
289
+ if(result != EXIT_SUCCESS){
290
+ printf("interpreter->set_input_tensor() failed !\n");
291
+ return EXIT_FAILURE;
292
+ }
293
+ // 开始计时
294
+ auto t1 = std::chrono::high_resolution_clock::now();
295
+ result = fast_interpreter->invoke();
296
+ auto t2 = std::chrono::high_resolution_clock::now();
297
+ std::chrono::duration<double> cost_time = t2 - t1;
298
+ invoke_time.push_back(cost_time.count() * 1000);
299
+ if(result != EXIT_SUCCESS){
300
+ printf("interpreter->invoke() failed !\n");
301
+ return EXIT_FAILURE;
302
+ }
303
+ uint32_t out_data_1 = 0;
304
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_trans_data, &out_data_1);
305
+ if(result != EXIT_SUCCESS){
306
+ printf("interpreter->get_output_tensor() 1 failed !\n");
307
+ return EXIT_FAILURE;
308
+ }
309
+ uint32_t out_data_2 = 0;
310
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_mul_data, &out_data_2);
311
+ if(result != EXIT_SUCCESS){
312
+ printf("interpreter->get_output_tensor() 2 failed !\n");
313
+ return EXIT_FAILURE;
314
+ }
315
+ }
316
+
317
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
318
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
319
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
320
+ float var_invoketime = 0.0f;
321
+ for (auto time : invoke_time) {
322
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
323
+ }
324
+ var_invoketime /= args.invoke_nums;
325
+ printf("=======================================\n");
326
+ 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",
327
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
328
+ printf("=======================================\n");
329
+
330
+ // std::vector<std::vector<uint32_t>> output_shapes = {{1, 4, out_size}, {1, 80, out_size}};
331
+ float* pos_data = new float[4 * out_size];
332
+ float* class_data = new float[80 * out_size];
333
+ transformData(qnn_trans_data, pos_data, 4, out_size);
334
+ transformData(qnn_mul_data, class_data, 80, out_size);
335
+
336
+ // post process
337
+ std::vector<float> qnn_concat;
338
+ concatenate(class_data, pos_data , 1, out_size, 80, 4, qnn_concat);
339
+ cv::Mat img = post_process(frame, qnn_concat, class_list, scale);
340
+ cv::imwrite("./results.png", img);
341
+ fast_interpreter->destory();
342
+ return 0;
343
+ }
344
+
345
+
346
+ int main(int argc, char* argv[]) {
347
+ Args args = parse_args(argc, argv);
348
+ return invoke(args);
349
+ }
model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/models/cutoff_yolov8s_w8a8.qnn216.ctx.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:60eef403584262893959e5f133f4b523205a71d166750bc1e0853303536cb5ed
3
+ size 11804696
model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/run_test.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import argparse
3
+ from yolov8s import Yolov8S
4
+ from utils import draw_detect_res
5
+
6
+ def parser_args():
7
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
8
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov8s_w8a8.qnn231.ctx.bin.aidem',help="inference model path")
9
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
10
+ parser.add_argument('--height',type=int,default=640,help="run backend")
11
+ parser.add_argument('--weight',type=int,default=640,help="run backend")
12
+ parser.add_argument('--cls_num',type=int,default=80,help="run backend")
13
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
14
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
15
+ args = parser.parse_args()
16
+ return args
17
+
18
+ if __name__ == "__main__":
19
+ args = parser_args()
20
+ height = args.height
21
+ weight = args.weight
22
+
23
+
24
+ model = Yolov8S(args.target_model, args.weight, args.height, args.cls_num)
25
+ frame = cv2.imread(args.imgs)
26
+
27
+ out_boxes= model(frame, args.invoke_nums)
28
+ print(f"=================== \n Detect {len(out_boxes)} targets.")
29
+ result = draw_detect_res(frame, out_boxes)
30
+ cv2.imwrite("./python/result.jpg", result)
model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/utils.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+
4
+ CLASSES = ("person", "bicycle", "car", "motorbike ", "aeroplane ", "bus ", "train", "truck ", "boat", "traffic light",
5
+ "fire hydrant", "stop sign ", "parking meter", "bench", "bird", "cat", "dog ", "horse ", "sheep", "cow", "elephant",
6
+ "bear", "zebra ", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite",
7
+ "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup", "fork", "knife ",
8
+ "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza ", "donut", "cake", "chair", "sofa",
9
+ "pottedplant", "bed", "diningtable", "toilet ", "tvmonitor", "laptop ", "mouse ", "remote ", "keyboard ", "cell phone", "microwave ",
10
+ "oven ", "toaster", "sink", "refrigerator ", "book", "clock", "vase", "scissors ", "teddy bear ", "hair drier", "toothbrush ")
11
+
12
+ def eqprocess(image, size1, size2):
13
+ h,w,_ = image.shape
14
+ mask = np.zeros((size1,size2,3),dtype=np.float32)
15
+ scale1 = h /size1
16
+ scale2 = w / size2
17
+ if scale1 > scale2:
18
+ scale = scale1
19
+ else:
20
+ scale = scale2
21
+ img = cv2.resize(image,(int(w / scale),int(h / scale)))
22
+ mask[:int(h / scale),:int(w / scale),:] = img
23
+ return mask, scale
24
+
25
+ def xywh2xyxy(x):
26
+ '''
27
+ Box (center x, center y, width, height) to (x1, y1, x2, y2)
28
+ '''
29
+ y = np.copy(x)
30
+ y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
31
+ y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
32
+ y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
33
+ y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
34
+ return y
35
+
36
+ def xyxy2xywh(box):
37
+ '''
38
+ Box (left_top x, left_top y, right_bottom x, right_bottom y) to (left_top x, left_top y, width, height)
39
+ '''
40
+ box[:, 2:] = box[:, 2:] - box[:, :2]
41
+ return box
42
+
43
+ def NMS(dets, scores, thresh):
44
+ '''
45
+ 单类NMS算法
46
+ dets.shape = (N, 5), (left_top x, left_top y, right_bottom x, right_bottom y, Scores)
47
+ '''
48
+ x1 = dets[:,0]
49
+ y1 = dets[:,1]
50
+ x2 = dets[:,2]
51
+ y2 = dets[:,3]
52
+ areas = (y2-y1+1) * (x2-x1+1)
53
+ keep = []
54
+ index = scores.argsort()[::-1]
55
+ while index.size >0:
56
+ i = index[0] # every time the first is the biggst, and add it directly
57
+ keep.append(i)
58
+ x11 = np.maximum(x1[i], x1[index[1:]]) # calculate the points of overlap
59
+ y11 = np.maximum(y1[i], y1[index[1:]])
60
+ x22 = np.minimum(x2[i], x2[index[1:]])
61
+ y22 = np.minimum(y2[i], y2[index[1:]])
62
+ w = np.maximum(0, x22-x11+1) # the weights of overlap
63
+ h = np.maximum(0, y22-y11+1) # the height of overlap
64
+ overlaps = w*h
65
+ ious = overlaps / (areas[i]+areas[index[1:]] - overlaps)
66
+ idx = np.where(ious<=thresh)[0]
67
+ index = index[idx+1] # because index start from 1
68
+
69
+ return keep
70
+
71
+
72
+ def draw_detect_res(img, det_pred):
73
+ '''
74
+ 检测结果绘制
75
+ '''
76
+ if det_pred is None:
77
+ return img
78
+
79
+ img = img.astype(np.uint8)
80
+ im_canvas = img.copy()
81
+ color_step = int(255/len(CLASSES))
82
+ for i in range(len(det_pred)):
83
+ x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
84
+ cls_id = int(det_pred[i][5])
85
+ print(i+1,[x1,y1,x2,y2],det_pred[i][4], f'{CLASSES[cls_id]}')
86
+ cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
87
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, int(cls_id*color_step), int(255-cls_id*color_step)),thickness = 2)
88
+ img = cv2.addWeighted(im_canvas, 0.3, img, 0.7, 0)
89
+ return img
90
+
91
+ def scale_mask(masks, im0_shape):
92
+ masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
93
+ interpolation=cv2.INTER_LINEAR)
94
+ if len(masks.shape) == 2:
95
+ masks = masks[:, :, None]
96
+ return masks
97
+
98
+ def crop_mask(masks, boxes):
99
+ n, h, w = masks.shape
100
+ x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
101
+ r = np.arange(w, dtype=x1.dtype)[None, None, :]
102
+ c = np.arange(h, dtype=x1.dtype)[None, :, None]
103
+ return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))
104
+
105
+ def process_mask(protos, masks_in, bboxes, im0_shape):
106
+ c, mh, mw = protos.shape
107
+ masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0) # HWN
108
+ masks = np.ascontiguousarray(masks)
109
+ masks = scale_mask(masks, im0_shape) # re-scale mask from P3 shape to original input image shape
110
+ masks = np.einsum('HWN -> NHW', masks) # HWN -> NHW
111
+ masks = crop_mask(masks, bboxes)
112
+ return np.greater(masks, 0.5)
113
+
114
+ def masks2segments(masks):
115
+ segments = []
116
+ for x in masks.astype('uint8'):
117
+ c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] # CHAIN_APPROX_SIMPLE
118
+ if c:
119
+ c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
120
+ else:
121
+ c = np.zeros((0, 2)) # no segments found
122
+ segments.append(c.astype('float32'))
123
+ return segments
model_farm_yolov8s_qcs6490_qnn2.16_int8_aidlite/python/yolov8s.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import aidlite
4
+ from utils import eqprocess, xywh2xyxy, NMS
5
+ import time
6
+
7
+ OBJ_THRESH = 0.45
8
+ NMS_THRESH = 0.45
9
+
10
+ class Yolov8S(object):
11
+ def __init__(self, model_path, width, height, class_num):
12
+ self.class_num = class_num
13
+ self.width = width
14
+ self.height = height
15
+ input_shape = [[1,height,width,3]]
16
+ self.blocks = int(height * width * ( 1 / 64 + 1 / 256 + 1 / 1024))
17
+ self.maskw = int(width / 4)
18
+ self.maskh = int(height / 4)
19
+ self.output_shape = [[1,4,self.blocks],[1,class_num,self.blocks]]
20
+
21
+ self.model = aidlite.Model.create_instance(model_path)
22
+ if self.model is None:
23
+ print("Create model failed !")
24
+ return
25
+ self.model.set_model_properties(input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
26
+
27
+ self.config = aidlite.Config.create_instance()
28
+ if self.config is None:
29
+ print("build_interpretper_from_model_and_config failed !")
30
+ return
31
+
32
+ self.config.framework_type = aidlite.FrameworkType.TYPE_QNN216
33
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
34
+ self.config.is_quantify_model = 1
35
+
36
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
37
+ if self.interpreter is None:
38
+ print("build_interpretper_from_model_and_config failed !")
39
+ return
40
+
41
+ self.interpreter.init()
42
+ self.interpreter.load_model()
43
+
44
+ def __call__(self, frame,invoke_nums):
45
+ img, scale = eqprocess(frame, self.height, self.width)
46
+ img = img / 255
47
+ img = img.astype(np.float32)
48
+ self.interpreter.set_input_tensor(0,img.data)
49
+
50
+ invoke_time=[]
51
+ for i in range(invoke_nums):
52
+ t1=time.time()
53
+ self.interpreter.invoke()
54
+ cost_time = (time.time()-t1)*1000
55
+ invoke_time.append(cost_time)
56
+
57
+ max_invoke_time = max(invoke_time)
58
+ min_invoke_time = min(invoke_time)
59
+ mean_invoke_time = sum(invoke_time)/invoke_nums
60
+ var_invoketime=np.var(invoke_time)
61
+ print("====================================")
62
+ print(f"QNN invoke {invoke_nums} times:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
63
+ print("====================================")
64
+
65
+ qnn_1 = self.interpreter.get_output_tensor(0)
66
+ qnn_2 = self.interpreter.get_output_tensor(1)
67
+ qnn_out = sorted([qnn_1,qnn_2], key=len)
68
+
69
+ qnn_local = qnn_out[0].reshape(*self.output_shape[0])
70
+ qnn_conf = qnn_out[1].reshape(*self.output_shape[1])
71
+
72
+
73
+ x = np.concatenate([qnn_local, qnn_conf], axis = 1).transpose(0,2,1)
74
+ x = x[np.amax(x[..., 4:], axis=-1) > OBJ_THRESH]
75
+ if len(x) < 1:
76
+ return None, None
77
+
78
+ x = np.c_[x[..., :4], np.amax(x[..., 4:], axis=-1), np.argmax(x[..., 4:], axis=-1)]
79
+
80
+ x[:, :4] = xywh2xyxy(x[:, :4])
81
+ index = NMS(x[:, :4], x[:, 4], NMS_THRESH)
82
+ out_boxes = x[index]
83
+ out_boxes[..., :4] = out_boxes[..., :4] * scale
84
+
85
+ return out_boxes
86
+
model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/README.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ### Source model
3
+ - Input shape: 640x640
4
+ - Number of parameters: 10.65M
5
+ - Model size: 42.7M
6
+ - Output shape: 1x84x8400
7
+
8
+ Source model repository: [yolov8](https://github.com/ultralytics/ultralytics)
9
+
10
+ ### Converted model
11
+
12
+ - Precision: FP16
13
+ - Backend: QNN2.16
14
+ - Target Device: SNM972 QCS8550
15
+
16
+ ## Model Conversion Reference
17
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/8204cbbb-e7dc-4c2b-8eb8-06e11fa82e29)
18
+
19
+ ## Inference with AidLite SDK
20
+
21
+ ### SDK installation
22
+ 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/)
23
+
24
+ - install AidLite SDK
25
+
26
+ ```bash
27
+ # Install the appropriate version of the aidlite sdk
28
+ sudo aid-pkg update
29
+ sudo aid-pkg install aidlite-sdk
30
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
31
+ sudo aid-pkg install aidlite-{QNN VERSION}
32
+ ```
33
+
34
+ - Verify AidLite SDK
35
+
36
+ ```bash
37
+ # Install the appropriate version of the aidlite sdk
38
+ sudo aid-pkg update
39
+ sudo aid-pkg install aidlite-sdk
40
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
41
+ sudo aid-pkg install aidlite-{QNN VERSION}
42
+ # eg: Install QNN 2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
43
+ ```
44
+
45
+ ### Run Demo
46
+
47
+ #### python
48
+ ```bash
49
+ cd model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite
50
+ python3 python/run_test.py --target_model ./models/cutoff_yolov8s_fp16.qnn216.ctx.bin --imgs ./python/bus.jpg --invoke_nums 10
51
+ ```
52
+
53
+ #### cpp
54
+ ```bash
55
+ cd model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/cpp
56
+ mkdir -p build && cd build
57
+ cmake .. && make
58
+ ./run_test --target_model ../../models/cutoff_yolov8s_fp16.qnn216.ctx.bin --imgs ../bus.jpg --invoke_nums 10
59
+ ```
model_farm_yolov8s_qcs8550_qnn2.16_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_yolov8s_qcs8550_qnn2.16_fp16_aidlite/cpp/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/cpp/main.cpp ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 = 0.75;
22
+ const int THICKNESS = 1;
23
+
24
+ const std::vector<std::string> class_list = {
25
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
26
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
27
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
28
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
29
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
30
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
31
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
32
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
33
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
34
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
35
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
36
+ "scissors", "teddy bear", "hair drier", "toothbrush"
37
+ };
38
+
39
+ using namespace Aidlux::Aidlite;
40
+
41
+ struct Args {
42
+ std::string target_model = "../../models/cutoff_yolov8s_fp16.qnn216.ctx.bin.aidem";
43
+ std::string imgs = "../bus.jpg";
44
+ int invoke_nums = 10;
45
+ std::string model_type = "QNN";
46
+ };
47
+
48
+ Args parse_args(int argc, char* argv[]) {
49
+ Args args;
50
+ for (int i = 1; i < argc; ++i) {
51
+ std::string arg = argv[i];
52
+ if (arg == "--target_model" && i + 1 < argc) {
53
+ args.target_model = argv[++i];
54
+ } else if (arg == "--imgs" && i + 1 < argc) {
55
+ args.imgs = argv[++i];
56
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
57
+ args.invoke_nums = std::stoi(argv[++i]);
58
+ } else if (arg == "--model_type" && i + 1 < argc) {
59
+ args.model_type = argv[++i];
60
+ }
61
+ }
62
+ return args;
63
+ }
64
+
65
+ std::string to_lower(const std::string& str) {
66
+ std::string lower_str = str;
67
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
68
+ return std::tolower(c);
69
+ });
70
+ return lower_str;
71
+ }
72
+
73
+
74
+ 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) {
75
+ int out_dim = trans_dim + mul_dim + 1;
76
+ output.resize(batch * num_elements * out_dim);
77
+ for (int i = 0; i < batch * num_elements; ++i) {
78
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
79
+ float max_val = *std::max_element(&qnn_trans_data[i * trans_dim], &qnn_trans_data[i * trans_dim + trans_dim]);
80
+ output[i * out_dim + 4] = max_val;
81
+ std::memcpy(&output[i * out_dim + 5], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
82
+ }
83
+ }
84
+
85
+ void transformData(const float* input, float* output, int C, int N) {
86
+ for (int c = 0; c < C; ++c) {
87
+ for (int n = 0; n < N; ++n) {
88
+ output[n * C + c] = input[c * N + n];
89
+ }
90
+ }
91
+ }
92
+
93
+ double img_process(cv::Mat frame, cv::Mat &img_input, int size) {
94
+ cv::Mat img_processed = frame.clone();
95
+ int height = img_processed.rows;
96
+ int width = img_processed.cols;
97
+ int length = std::max(height, width);
98
+ double scala = static_cast<double>(length) / size;
99
+
100
+ cv::Mat image = cv::Mat::zeros(cv::Size(length, length), CV_8UC3);
101
+ img_processed.copyTo(image(cv::Rect(0, 0, width, height)));
102
+
103
+ cv::cvtColor(image, img_input, cv::COLOR_BGR2RGB);
104
+ cv::resize(img_input, img_input, cv::Size(size, size));
105
+
106
+ cv::Mat mean_data = cv::Mat::zeros(img_input.size(), CV_32FC3);
107
+ cv::Mat std_data(img_input.size(), CV_32FC3, cv::Scalar(255, 255, 255));
108
+ img_input.convertTo(img_input, CV_32FC3);
109
+ img_input = (img_input - mean_data) / std_data;
110
+ return scala;
111
+ }
112
+
113
+
114
+ cv::Scalar generate_colors(int i, bool bgr = false) {
115
+ static const std::vector<std::string> hex_colors = {
116
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
117
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
118
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
119
+ "FF95C8", "FF37C7"
120
+ };
121
+
122
+ int num = hex_colors.size();
123
+ std::string hex = hex_colors[i % num];
124
+
125
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
126
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
127
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
128
+
129
+ if (bgr)
130
+ return cv::Scalar(b, g, r);
131
+ else
132
+ return cv::Scalar(r, g, b);
133
+ }
134
+
135
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
136
+ {
137
+ int baseLine;
138
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
139
+ int y = top - label_size.height - baseLine;
140
+ if (y < 0) {
141
+ y = top ;
142
+ }
143
+ cv::Point tlc(left, y);
144
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
145
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
146
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
147
+ }
148
+
149
+
150
+ cv::Mat post_process(cv::Mat &input_image, std::vector<float> &outputs, const std::vector<std::string> &class_name, const double ratio)
151
+ {
152
+ // Initialize vectors to hold respective outputs while unwrapping detections.
153
+ std::vector<int> class_ids;
154
+ std::vector<float> confidences;
155
+ std::vector<cv::Rect> boxes;
156
+
157
+ // Iterate through outputs for each box prediction
158
+ for (int i = 0; i < outputs.size(); i+=85)
159
+ {
160
+ float confidence = outputs[i+4];
161
+ if (confidence >= CONFIDENCE_THRESHOLD)
162
+ {
163
+ // Create a 1x80 Mat and store class scores of 80 classes.
164
+ cv::Mat scores(1, class_name.size(), CV_32FC1, outputs.data() + i + 5);
165
+ cv::Point class_id;
166
+ double max_class_score;
167
+
168
+ // For multi-label, check each class score
169
+ for (int c = 0; c < class_name.size(); c++) {
170
+ float class_score = scores.at<float>(0, c);
171
+
172
+ // If class score is above threshold, consider this class for the box
173
+ if (class_score > SCORE_THRESHOLD) {
174
+ // Store class ID and confidence in the pre-defined respective vectors.
175
+ confidences.push_back(confidence * class_score); // Multiply with confidence
176
+ class_ids.push_back(c); // class index
177
+ // Center and box dimension.
178
+ float cx = outputs[i];
179
+ float cy = outputs[i+1];
180
+ float w = outputs[i+2];
181
+ float h = outputs[i+3];
182
+
183
+ int left = int((cx - 0.5 * w) * ratio);
184
+ int top = int((cy - 0.5 * h) * ratio);
185
+ int width = int(w * ratio);
186
+ int height = int(h * ratio);
187
+
188
+ // Store good detections in the boxes vector.
189
+ boxes.push_back(cv::Rect(left, top, width, height));
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ // Perform Non Maximum Suppression and draw predictions.
196
+ std::vector<int> indices;
197
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
198
+ printf("Detected {%ld} targets.\n", indices.size());
199
+
200
+ // Loop over NMS results and draw bounding boxes
201
+ for (int i = 0; i < indices.size(); i++)
202
+ {
203
+ int idx = indices[i];
204
+ cv::Rect box = boxes[idx];
205
+
206
+ int left = box.x;
207
+ int top = box.y;
208
+ int width = box.width;
209
+ int height = box.height;
210
+ cv::Scalar color = generate_colors(class_ids[idx]);
211
+ // Draw bounding box.
212
+ rectangle(input_image, cv::Point(left, top), cv::Point(left + width, top + height), color, 2*THICKNESS);
213
+
214
+ // Get the label for the class name and its confidence.
215
+ std::string label = cv::format("%.2f", confidences[idx]);
216
+ label = class_name[class_ids[idx]] + ":" + label;
217
+ // Draw class labels.
218
+ draw_label(input_image, label, left, top, color);
219
+ }
220
+ printf("Processing finished.\n");
221
+ return input_image;
222
+ }
223
+
224
+ int invoke(const Args& args) {
225
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
226
+ << "Image Path: " << args.imgs << "\n"
227
+ << "Inference Nums: " << args.invoke_nums << "\n"
228
+ << "Model Type: " << args.model_type << "\n";
229
+ Model* model = Model::create_instance(args.target_model);
230
+ if(model == nullptr){
231
+ printf("Create model failed !\n");
232
+ return EXIT_FAILURE;
233
+ }
234
+ Config* config = Config::create_instance();
235
+ if(config == nullptr){
236
+ printf("Create config failed !\n");
237
+ return EXIT_FAILURE;
238
+ }
239
+ config->implement_type = ImplementType::TYPE_LOCAL;
240
+ std::string model_type_lower = to_lower(args.model_type);
241
+ if (model_type_lower == "qnn"){
242
+ config->framework_type = FrameworkType::TYPE_QNN;
243
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
244
+ config->framework_type = FrameworkType::TYPE_SNPE2;
245
+ }
246
+ config->accelerate_type = AccelerateType::TYPE_DSP;
247
+ config->is_quantify_model = 1;
248
+
249
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
250
+ std::vector<std::vector<uint32_t>> output_shapes = {{1, 4, out_size}, {1, 80, out_size}};
251
+ model->set_model_properties(input_shapes, DataType::TYPE_FLOAT32, output_shapes, DataType::TYPE_FLOAT32);
252
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
253
+ if(fast_interpreter == nullptr){
254
+ printf("build_interpretper_from_model_and_config failed !\n");
255
+ return EXIT_FAILURE;
256
+ }
257
+ int result = fast_interpreter->init();
258
+ if(result != EXIT_SUCCESS){
259
+ printf("interpreter->init() failed !\n");
260
+ return EXIT_FAILURE;
261
+ }
262
+ // load model
263
+ fast_interpreter->load_model();
264
+ if(result != EXIT_SUCCESS){
265
+ printf("interpreter->load_model() failed !\n");
266
+ return EXIT_FAILURE;
267
+ }
268
+ printf("detect model load success!\n");
269
+
270
+ cv::Mat frame = cv::imread(args.imgs);
271
+ if (frame.empty()) {
272
+ printf("detect image load failed!\n");
273
+ return 1;
274
+ }
275
+ printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
276
+ cv::Mat input_img;
277
+ double scale = img_process(frame, input_img, size);
278
+ if (input_img.empty()) {
279
+ printf("detect input_img load failed!\n");
280
+ return 1;
281
+ }
282
+
283
+ float *qnn_trans_data = nullptr;
284
+ float *qnn_mul_data = nullptr;
285
+
286
+ std::vector<float> invoke_time;
287
+ for (int i = 0; i < args.invoke_nums; ++i) {
288
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
289
+ if(result != EXIT_SUCCESS){
290
+ printf("interpreter->set_input_tensor() failed !\n");
291
+ return EXIT_FAILURE;
292
+ }
293
+ // 开始计时
294
+ auto t1 = std::chrono::high_resolution_clock::now();
295
+ result = fast_interpreter->invoke();
296
+ auto t2 = std::chrono::high_resolution_clock::now();
297
+ std::chrono::duration<double> cost_time = t2 - t1;
298
+ invoke_time.push_back(cost_time.count() * 1000);
299
+ if(result != EXIT_SUCCESS){
300
+ printf("interpreter->invoke() failed !\n");
301
+ return EXIT_FAILURE;
302
+ }
303
+ uint32_t out_data_1 = 0;
304
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_trans_data, &out_data_1);
305
+ if(result != EXIT_SUCCESS){
306
+ printf("interpreter->get_output_tensor() 1 failed !\n");
307
+ return EXIT_FAILURE;
308
+ }
309
+ uint32_t out_data_2 = 0;
310
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_mul_data, &out_data_2);
311
+ if(result != EXIT_SUCCESS){
312
+ printf("interpreter->get_output_tensor() 2 failed !\n");
313
+ return EXIT_FAILURE;
314
+ }
315
+ }
316
+
317
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
318
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
319
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
320
+ float var_invoketime = 0.0f;
321
+ for (auto time : invoke_time) {
322
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
323
+ }
324
+ var_invoketime /= args.invoke_nums;
325
+ printf("=======================================\n");
326
+ 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",
327
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
328
+ printf("=======================================\n");
329
+
330
+ // std::vector<std::vector<uint32_t>> output_shapes = {{1, 4, out_size}, {1, 80, out_size}};
331
+ float* pos_data = new float[4 * out_size];
332
+ float* class_data = new float[80 * out_size];
333
+ transformData(qnn_trans_data, pos_data, 4, out_size);
334
+ transformData(qnn_mul_data, class_data, 80, out_size);
335
+
336
+ // post process
337
+ std::vector<float> qnn_concat;
338
+ concatenate(class_data, pos_data , 1, out_size, 80, 4, qnn_concat);
339
+ cv::Mat img = post_process(frame, qnn_concat, class_list, scale);
340
+ cv::imwrite("./results.png", img);
341
+ fast_interpreter->destory();
342
+ return 0;
343
+ }
344
+
345
+
346
+ int main(int argc, char* argv[]) {
347
+ Args args = parse_args(argc, argv);
348
+ return invoke(args);
349
+ }
model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/models/cutoff_yolov8s_fp16.qnn216.ctx.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:68c451e6059b8cbbfcc732cfe83571223a7e0c4120c1437d78d32d5e4f828d8e
3
+ size 23003136
model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import argparse
3
+ from yolov8s import Yolov8S
4
+ from utils import draw_detect_res
5
+
6
+ def parser_args():
7
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
8
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov8s_w8a8.qnn231.ctx.bin.aidem',help="inference model path")
9
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
10
+ parser.add_argument('--height',type=int,default=640,help="run backend")
11
+ parser.add_argument('--weight',type=int,default=640,help="run backend")
12
+ parser.add_argument('--cls_num',type=int,default=80,help="run backend")
13
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
14
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
15
+ args = parser.parse_args()
16
+ return args
17
+
18
+ if __name__ == "__main__":
19
+ args = parser_args()
20
+ height = args.height
21
+ weight = args.weight
22
+
23
+
24
+ model = Yolov8S(args.target_model, args.weight, args.height, args.cls_num)
25
+ frame = cv2.imread(args.imgs)
26
+
27
+ out_boxes= model(frame,args.invoke_nums)
28
+ print(f"=================== \n Detect {len(out_boxes)} targets.")
29
+ result = draw_detect_res(frame, out_boxes)
30
+ cv2.imwrite("./python/result.jpg", result)
model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/utils.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+
4
+ CLASSES = ("person", "bicycle", "car", "motorbike ", "aeroplane ", "bus ", "train", "truck ", "boat", "traffic light",
5
+ "fire hydrant", "stop sign ", "parking meter", "bench", "bird", "cat", "dog ", "horse ", "sheep", "cow", "elephant",
6
+ "bear", "zebra ", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite",
7
+ "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup", "fork", "knife ",
8
+ "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza ", "donut", "cake", "chair", "sofa",
9
+ "pottedplant", "bed", "diningtable", "toilet ", "tvmonitor", "laptop ", "mouse ", "remote ", "keyboard ", "cell phone", "microwave ",
10
+ "oven ", "toaster", "sink", "refrigerator ", "book", "clock", "vase", "scissors ", "teddy bear ", "hair drier", "toothbrush ")
11
+
12
+ def eqprocess(image, size1, size2):
13
+ h,w,_ = image.shape
14
+ mask = np.zeros((size1,size2,3),dtype=np.float32)
15
+ scale1 = h /size1
16
+ scale2 = w / size2
17
+ if scale1 > scale2:
18
+ scale = scale1
19
+ else:
20
+ scale = scale2
21
+ img = cv2.resize(image,(int(w / scale),int(h / scale)))
22
+ mask[:int(h / scale),:int(w / scale),:] = img
23
+ return mask, scale
24
+
25
+ def xywh2xyxy(x):
26
+ '''
27
+ Box (center x, center y, width, height) to (x1, y1, x2, y2)
28
+ '''
29
+ y = np.copy(x)
30
+ y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
31
+ y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
32
+ y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
33
+ y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
34
+ return y
35
+
36
+ def xyxy2xywh(box):
37
+ '''
38
+ Box (left_top x, left_top y, right_bottom x, right_bottom y) to (left_top x, left_top y, width, height)
39
+ '''
40
+ box[:, 2:] = box[:, 2:] - box[:, :2]
41
+ return box
42
+
43
+ def NMS(dets, scores, thresh):
44
+ '''
45
+ 单类NMS算法
46
+ dets.shape = (N, 5), (left_top x, left_top y, right_bottom x, right_bottom y, Scores)
47
+ '''
48
+ x1 = dets[:,0]
49
+ y1 = dets[:,1]
50
+ x2 = dets[:,2]
51
+ y2 = dets[:,3]
52
+ areas = (y2-y1+1) * (x2-x1+1)
53
+ keep = []
54
+ index = scores.argsort()[::-1]
55
+ while index.size >0:
56
+ i = index[0] # every time the first is the biggst, and add it directly
57
+ keep.append(i)
58
+ x11 = np.maximum(x1[i], x1[index[1:]]) # calculate the points of overlap
59
+ y11 = np.maximum(y1[i], y1[index[1:]])
60
+ x22 = np.minimum(x2[i], x2[index[1:]])
61
+ y22 = np.minimum(y2[i], y2[index[1:]])
62
+ w = np.maximum(0, x22-x11+1) # the weights of overlap
63
+ h = np.maximum(0, y22-y11+1) # the height of overlap
64
+ overlaps = w*h
65
+ ious = overlaps / (areas[i]+areas[index[1:]] - overlaps)
66
+ idx = np.where(ious<=thresh)[0]
67
+ index = index[idx+1] # because index start from 1
68
+
69
+ return keep
70
+
71
+
72
+ def draw_detect_res(img, det_pred):
73
+ '''
74
+ 检测结果绘制
75
+ '''
76
+ if det_pred is None:
77
+ return img
78
+
79
+ img = img.astype(np.uint8)
80
+ im_canvas = img.copy()
81
+ color_step = int(255/len(CLASSES))
82
+ for i in range(len(det_pred)):
83
+ x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
84
+ cls_id = int(det_pred[i][5])
85
+ print(i+1,[x1,y1,x2,y2],det_pred[i][4], f'{CLASSES[cls_id]}')
86
+ cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
87
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, int(cls_id*color_step), int(255-cls_id*color_step)),thickness = 2)
88
+ img = cv2.addWeighted(im_canvas, 0.3, img, 0.7, 0)
89
+ return img
90
+
91
+ def scale_mask(masks, im0_shape):
92
+ masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
93
+ interpolation=cv2.INTER_LINEAR)
94
+ if len(masks.shape) == 2:
95
+ masks = masks[:, :, None]
96
+ return masks
97
+
98
+ def crop_mask(masks, boxes):
99
+ n, h, w = masks.shape
100
+ x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
101
+ r = np.arange(w, dtype=x1.dtype)[None, None, :]
102
+ c = np.arange(h, dtype=x1.dtype)[None, :, None]
103
+ return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))
104
+
105
+ def process_mask(protos, masks_in, bboxes, im0_shape):
106
+ c, mh, mw = protos.shape
107
+ masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0) # HWN
108
+ masks = np.ascontiguousarray(masks)
109
+ masks = scale_mask(masks, im0_shape) # re-scale mask from P3 shape to original input image shape
110
+ masks = np.einsum('HWN -> NHW', masks) # HWN -> NHW
111
+ masks = crop_mask(masks, bboxes)
112
+ return np.greater(masks, 0.5)
113
+
114
+ def masks2segments(masks):
115
+ segments = []
116
+ for x in masks.astype('uint8'):
117
+ c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] # CHAIN_APPROX_SIMPLE
118
+ if c:
119
+ c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
120
+ else:
121
+ c = np.zeros((0, 2)) # no segments found
122
+ segments.append(c.astype('float32'))
123
+ return segments
model_farm_yolov8s_qcs8550_qnn2.16_fp16_aidlite/python/yolov8s.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import aidlite
4
+ from utils import eqprocess, xywh2xyxy, NMS
5
+ import time
6
+
7
+ OBJ_THRESH = 0.45
8
+ NMS_THRESH = 0.45
9
+
10
+ class Yolov8S(object):
11
+ def __init__(self, model_path, width, height, class_num):
12
+ self.class_num = class_num
13
+ self.width = width
14
+ self.height = height
15
+ input_shape = [[1,height,width,3]]
16
+ self.blocks = int(height * width * ( 1 / 64 + 1 / 256 + 1 / 1024))
17
+ self.maskw = int(width / 4)
18
+ self.maskh = int(height / 4)
19
+ self.output_shape = [[1,4,self.blocks],[1,class_num,self.blocks]]
20
+
21
+ self.model = aidlite.Model.create_instance(model_path)
22
+ if self.model is None:
23
+ print("Create model failed !")
24
+ return
25
+ self.model.set_model_properties(input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
26
+
27
+ self.config = aidlite.Config.create_instance()
28
+ if self.config is None:
29
+ print("build_interpretper_from_model_and_config failed !")
30
+ return
31
+
32
+ self.config.framework_type = aidlite.FrameworkType.TYPE_QNN
33
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
34
+ self.config.is_quantify_model = 1
35
+
36
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
37
+ if self.interpreter is None:
38
+ print("build_interpretper_from_model_and_config failed !")
39
+ return
40
+
41
+ self.interpreter.init()
42
+ self.interpreter.load_model()
43
+
44
+ def __call__(self, frame,invoke_nums):
45
+ img, scale = eqprocess(frame, self.height, self.width)
46
+ img = img / 255
47
+ img = img.astype(np.float32)
48
+ self.interpreter.set_input_tensor(0,img.data)
49
+
50
+ invoke_time=[]
51
+ for i in range(invoke_nums):
52
+ t1=time.time()
53
+ self.interpreter.invoke()
54
+ cost_time = (time.time()-t1)*1000
55
+ invoke_time.append(cost_time)
56
+
57
+ max_invoke_time = max(invoke_time)
58
+ min_invoke_time = min(invoke_time)
59
+ mean_invoke_time = sum(invoke_time)/invoke_nums
60
+ var_invoketime=np.var(invoke_time)
61
+ print("====================================")
62
+ print(f"QNN invoke {invoke_nums} times:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
63
+ print("====================================")
64
+
65
+ qnn_1 = self.interpreter.get_output_tensor(0)
66
+ qnn_2 = self.interpreter.get_output_tensor(1)
67
+ qnn_out = sorted([qnn_1,qnn_2], key=len)
68
+
69
+ qnn_local = qnn_out[0].reshape(*self.output_shape[0])
70
+ qnn_conf = qnn_out[1].reshape(*self.output_shape[1])
71
+
72
+
73
+ x = np.concatenate([qnn_local, qnn_conf], axis = 1).transpose(0,2,1)
74
+ x = x[np.amax(x[..., 4:], axis=-1) > OBJ_THRESH]
75
+ if len(x) < 1:
76
+ return None, None
77
+
78
+ x = np.c_[x[..., :4], np.amax(x[..., 4:], axis=-1), np.argmax(x[..., 4:], axis=-1)]
79
+
80
+ x[:, :4] = xywh2xyxy(x[:, :4])
81
+ index = NMS(x[:, :4], x[:, 4], NMS_THRESH)
82
+ out_boxes = x[index]
83
+ out_boxes[..., :4] = out_boxes[..., :4] * scale
84
+
85
+ return out_boxes
86
+
model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/README.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ### Source model
3
+ - Input shape: 640x640
4
+ - Number of parameters: 10.65M
5
+ - Model size: 42.7M
6
+ - Output shape: 1x84x8400
7
+
8
+ Source model repository: [yolov8](https://github.com/ultralytics/ultralytics)
9
+
10
+ ### Converted model
11
+
12
+ - Precision: INT8
13
+ - Backend: QNN2.16
14
+ - Target Device: SNM972 QCS8550
15
+
16
+ ## Model Conversion Reference
17
+ User can find model conversion reference at [aimo.aidlux.com](https://aimo.aidlux.com/#/public/34252a53-87e0-4fe2-b1bb-87c153fc21b7)
18
+
19
+ ## Inference with AidLite SDK
20
+
21
+ ### SDK installation
22
+ 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/)
23
+
24
+ - install AidLite SDK
25
+
26
+ ```bash
27
+ # Install the appropriate version of the aidlite sdk
28
+ sudo aid-pkg update
29
+ sudo aid-pkg install aidlite-sdk
30
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
31
+ sudo aid-pkg install aidlite-{QNN VERSION}
32
+ # eg: Install QNN 2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
33
+ ```
34
+
35
+ - Verify AidLite SDK
36
+
37
+ ```bash
38
+ # aidlite sdk c++ check
39
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
40
+
41
+ # aidlite sdk python check
42
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
43
+ ```
44
+
45
+ ### Run Demo
46
+
47
+ #### python
48
+ ```bash
49
+ cd model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite
50
+ python3 python/run_test.py --target_model ./models/cutoff_yolov8s_w8a8.qnn216.ctx.bin --imgs ./python/bus.jpg --invoke_nums 10
51
+ ```
52
+
53
+ #### cpp
54
+ ```bash
55
+ cd model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/cpp
56
+ mkdir -p build && cd build
57
+ cmake .. && make
58
+ ./run_test --target_model ../../models/cutoff_yolov8s_w8a8.qnn216.ctx.bin --imgs ../bus.jpg --invoke_nums 10
59
+ ```
model_farm_yolov8s_qcs8550_qnn2.16_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_yolov8s_qcs8550_qnn2.16_int8_aidlite/cpp/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/cpp/main.cpp ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 = 0.75;
22
+ const int THICKNESS = 1;
23
+
24
+ const std::vector<std::string> class_list = {
25
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
26
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
27
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
28
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
29
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
30
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
31
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
32
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
33
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
34
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
35
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
36
+ "scissors", "teddy bear", "hair drier", "toothbrush"
37
+ };
38
+
39
+ using namespace Aidlux::Aidlite;
40
+
41
+ struct Args {
42
+ std::string target_model = "../../models/cutoff_yolov8s_w8a8.qnn216.ctx.bin.aidem";
43
+ std::string imgs = "../bus.jpg";
44
+ int invoke_nums = 10;
45
+ std::string model_type = "QNN";
46
+ };
47
+
48
+ Args parse_args(int argc, char* argv[]) {
49
+ Args args;
50
+ for (int i = 1; i < argc; ++i) {
51
+ std::string arg = argv[i];
52
+ if (arg == "--target_model" && i + 1 < argc) {
53
+ args.target_model = argv[++i];
54
+ } else if (arg == "--imgs" && i + 1 < argc) {
55
+ args.imgs = argv[++i];
56
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
57
+ args.invoke_nums = std::stoi(argv[++i]);
58
+ } else if (arg == "--model_type" && i + 1 < argc) {
59
+ args.model_type = argv[++i];
60
+ }
61
+ }
62
+ return args;
63
+ }
64
+
65
+ std::string to_lower(const std::string& str) {
66
+ std::string lower_str = str;
67
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
68
+ return std::tolower(c);
69
+ });
70
+ return lower_str;
71
+ }
72
+
73
+
74
+ 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) {
75
+ int out_dim = trans_dim + mul_dim + 1;
76
+ output.resize(batch * num_elements * out_dim);
77
+ for (int i = 0; i < batch * num_elements; ++i) {
78
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
79
+ float max_val = *std::max_element(&qnn_trans_data[i * trans_dim], &qnn_trans_data[i * trans_dim + trans_dim]);
80
+ output[i * out_dim + 4] = max_val;
81
+ std::memcpy(&output[i * out_dim + 5], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
82
+ }
83
+ }
84
+
85
+ void transformData(const float* input, float* output, int C, int N) {
86
+ for (int c = 0; c < C; ++c) {
87
+ for (int n = 0; n < N; ++n) {
88
+ output[n * C + c] = input[c * N + n];
89
+ }
90
+ }
91
+ }
92
+
93
+ double img_process(cv::Mat frame, cv::Mat &img_input, int size) {
94
+ cv::Mat img_processed = frame.clone();
95
+ int height = img_processed.rows;
96
+ int width = img_processed.cols;
97
+ int length = std::max(height, width);
98
+ double scala = static_cast<double>(length) / size;
99
+
100
+ cv::Mat image = cv::Mat::zeros(cv::Size(length, length), CV_8UC3);
101
+ img_processed.copyTo(image(cv::Rect(0, 0, width, height)));
102
+
103
+ cv::cvtColor(image, img_input, cv::COLOR_BGR2RGB);
104
+ cv::resize(img_input, img_input, cv::Size(size, size));
105
+
106
+ cv::Mat mean_data = cv::Mat::zeros(img_input.size(), CV_32FC3);
107
+ cv::Mat std_data(img_input.size(), CV_32FC3, cv::Scalar(255, 255, 255));
108
+ img_input.convertTo(img_input, CV_32FC3);
109
+ img_input = (img_input - mean_data) / std_data;
110
+ return scala;
111
+ }
112
+
113
+
114
+ cv::Scalar generate_colors(int i, bool bgr = false) {
115
+ static const std::vector<std::string> hex_colors = {
116
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
117
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
118
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
119
+ "FF95C8", "FF37C7"
120
+ };
121
+
122
+ int num = hex_colors.size();
123
+ std::string hex = hex_colors[i % num];
124
+
125
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
126
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
127
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
128
+
129
+ if (bgr)
130
+ return cv::Scalar(b, g, r);
131
+ else
132
+ return cv::Scalar(r, g, b);
133
+ }
134
+
135
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
136
+ {
137
+ int baseLine;
138
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
139
+ int y = top - label_size.height - baseLine;
140
+ if (y < 0) {
141
+ y = top ;
142
+ }
143
+ cv::Point tlc(left, y);
144
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
145
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
146
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
147
+ }
148
+
149
+
150
+ cv::Mat post_process(cv::Mat &input_image, std::vector<float> &outputs, const std::vector<std::string> &class_name, const double ratio)
151
+ {
152
+ // Initialize vectors to hold respective outputs while unwrapping detections.
153
+ std::vector<int> class_ids;
154
+ std::vector<float> confidences;
155
+ std::vector<cv::Rect> boxes;
156
+
157
+ // Iterate through outputs for each box prediction
158
+ for (int i = 0; i < outputs.size(); i+=85)
159
+ {
160
+ float confidence = outputs[i+4];
161
+ if (confidence >= CONFIDENCE_THRESHOLD)
162
+ {
163
+ // Create a 1x80 Mat and store class scores of 80 classes.
164
+ cv::Mat scores(1, class_name.size(), CV_32FC1, outputs.data() + i + 5);
165
+ cv::Point class_id;
166
+ double max_class_score;
167
+
168
+ // For multi-label, check each class score
169
+ for (int c = 0; c < class_name.size(); c++) {
170
+ float class_score = scores.at<float>(0, c);
171
+
172
+ // If class score is above threshold, consider this class for the box
173
+ if (class_score > SCORE_THRESHOLD) {
174
+ // Store class ID and confidence in the pre-defined respective vectors.
175
+ confidences.push_back(confidence * class_score); // Multiply with confidence
176
+ class_ids.push_back(c); // class index
177
+ // Center and box dimension.
178
+ float cx = outputs[i];
179
+ float cy = outputs[i+1];
180
+ float w = outputs[i+2];
181
+ float h = outputs[i+3];
182
+
183
+ int left = int((cx - 0.5 * w) * ratio);
184
+ int top = int((cy - 0.5 * h) * ratio);
185
+ int width = int(w * ratio);
186
+ int height = int(h * ratio);
187
+
188
+ // Store good detections in the boxes vector.
189
+ boxes.push_back(cv::Rect(left, top, width, height));
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ // Perform Non Maximum Suppression and draw predictions.
196
+ std::vector<int> indices;
197
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
198
+ printf("Detected {%ld} targets.\n", indices.size());
199
+
200
+ // Loop over NMS results and draw bounding boxes
201
+ for (int i = 0; i < indices.size(); i++)
202
+ {
203
+ int idx = indices[i];
204
+ cv::Rect box = boxes[idx];
205
+
206
+ int left = box.x;
207
+ int top = box.y;
208
+ int width = box.width;
209
+ int height = box.height;
210
+ cv::Scalar color = generate_colors(class_ids[idx]);
211
+ // Draw bounding box.
212
+ rectangle(input_image, cv::Point(left, top), cv::Point(left + width, top + height), color, 2*THICKNESS);
213
+
214
+ // Get the label for the class name and its confidence.
215
+ std::string label = cv::format("%.2f", confidences[idx]);
216
+ label = class_name[class_ids[idx]] + ":" + label;
217
+ // Draw class labels.
218
+ draw_label(input_image, label, left, top, color);
219
+ }
220
+ printf("Processing finished.\n");
221
+ return input_image;
222
+ }
223
+
224
+ int invoke(const Args& args) {
225
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
226
+ << "Image Path: " << args.imgs << "\n"
227
+ << "Inference Nums: " << args.invoke_nums << "\n"
228
+ << "Model Type: " << args.model_type << "\n";
229
+ Model* model = Model::create_instance(args.target_model);
230
+ if(model == nullptr){
231
+ printf("Create model failed !\n");
232
+ return EXIT_FAILURE;
233
+ }
234
+ Config* config = Config::create_instance();
235
+ if(config == nullptr){
236
+ printf("Create config failed !\n");
237
+ return EXIT_FAILURE;
238
+ }
239
+ config->implement_type = ImplementType::TYPE_LOCAL;
240
+ std::string model_type_lower = to_lower(args.model_type);
241
+ if (model_type_lower == "qnn"){
242
+ config->framework_type = FrameworkType::TYPE_QNN;
243
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
244
+ config->framework_type = FrameworkType::TYPE_SNPE2;
245
+ }
246
+ config->accelerate_type = AccelerateType::TYPE_DSP;
247
+ config->is_quantify_model = 1;
248
+
249
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
250
+ std::vector<std::vector<uint32_t>> output_shapes = {{1, 4, out_size}, {1, 80, out_size}};
251
+ model->set_model_properties(input_shapes, DataType::TYPE_FLOAT32, output_shapes, DataType::TYPE_FLOAT32);
252
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
253
+ if(fast_interpreter == nullptr){
254
+ printf("build_interpretper_from_model_and_config failed !\n");
255
+ return EXIT_FAILURE;
256
+ }
257
+ int result = fast_interpreter->init();
258
+ if(result != EXIT_SUCCESS){
259
+ printf("interpreter->init() failed !\n");
260
+ return EXIT_FAILURE;
261
+ }
262
+ // load model
263
+ fast_interpreter->load_model();
264
+ if(result != EXIT_SUCCESS){
265
+ printf("interpreter->load_model() failed !\n");
266
+ return EXIT_FAILURE;
267
+ }
268
+ printf("detect model load success!\n");
269
+
270
+ cv::Mat frame = cv::imread(args.imgs);
271
+ if (frame.empty()) {
272
+ printf("detect image load failed!\n");
273
+ return 1;
274
+ }
275
+ printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
276
+ cv::Mat input_img;
277
+ double scale = img_process(frame, input_img, size);
278
+ if (input_img.empty()) {
279
+ printf("detect input_img load failed!\n");
280
+ return 1;
281
+ }
282
+
283
+ float *qnn_trans_data = nullptr;
284
+ float *qnn_mul_data = nullptr;
285
+
286
+ std::vector<float> invoke_time;
287
+ for (int i = 0; i < args.invoke_nums; ++i) {
288
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
289
+ if(result != EXIT_SUCCESS){
290
+ printf("interpreter->set_input_tensor() failed !\n");
291
+ return EXIT_FAILURE;
292
+ }
293
+ // 开始计时
294
+ auto t1 = std::chrono::high_resolution_clock::now();
295
+ result = fast_interpreter->invoke();
296
+ auto t2 = std::chrono::high_resolution_clock::now();
297
+ std::chrono::duration<double> cost_time = t2 - t1;
298
+ invoke_time.push_back(cost_time.count() * 1000);
299
+ if(result != EXIT_SUCCESS){
300
+ printf("interpreter->invoke() failed !\n");
301
+ return EXIT_FAILURE;
302
+ }
303
+ uint32_t out_data_1 = 0;
304
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_trans_data, &out_data_1);
305
+ if(result != EXIT_SUCCESS){
306
+ printf("interpreter->get_output_tensor() 1 failed !\n");
307
+ return EXIT_FAILURE;
308
+ }
309
+ uint32_t out_data_2 = 0;
310
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_mul_data, &out_data_2);
311
+ if(result != EXIT_SUCCESS){
312
+ printf("interpreter->get_output_tensor() 2 failed !\n");
313
+ return EXIT_FAILURE;
314
+ }
315
+ }
316
+
317
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
318
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
319
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
320
+ float var_invoketime = 0.0f;
321
+ for (auto time : invoke_time) {
322
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
323
+ }
324
+ var_invoketime /= args.invoke_nums;
325
+ printf("=======================================\n");
326
+ 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",
327
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
328
+ printf("=======================================\n");
329
+
330
+ // std::vector<std::vector<uint32_t>> output_shapes = {{1, 4, out_size}, {1, 80, out_size}};
331
+ float* pos_data = new float[4 * out_size];
332
+ float* class_data = new float[80 * out_size];
333
+ transformData(qnn_trans_data, pos_data, 4, out_size);
334
+ transformData(qnn_mul_data, class_data, 80, out_size);
335
+
336
+ // post process
337
+ std::vector<float> qnn_concat;
338
+ concatenate(class_data, pos_data , 1, out_size, 80, 4, qnn_concat);
339
+ cv::Mat img = post_process(frame, qnn_concat, class_list, scale);
340
+ cv::imwrite("./results.png", img);
341
+ fast_interpreter->destory();
342
+ return 0;
343
+ }
344
+
345
+
346
+ int main(int argc, char* argv[]) {
347
+ Args args = parse_args(argc, argv);
348
+ return invoke(args);
349
+ }
model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/models/cutoff_yolov8s_w8a8.qnn216.ctx.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:25255e85b913a3d079c9a975049b192ae05b77232cb78c0b5077f339c38129e6
3
+ size 11690008
model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: 33b198a1d2839bb9ac4c65d61f9e852196793cae9a0781360859425f6022b69c
  • Pointer size: 131 Bytes
  • Size of remote file: 487 kB
model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/run_test.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import argparse
3
+ from yolov8s import Yolov8S
4
+ from utils import draw_detect_res
5
+
6
+ def parser_args():
7
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
8
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov8s_w8a8.qnn231.ctx.bin.aidem',help="inference model path")
9
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
10
+ parser.add_argument('--height',type=int,default=640,help="run backend")
11
+ parser.add_argument('--weight',type=int,default=640,help="run backend")
12
+ parser.add_argument('--cls_num',type=int,default=80,help="run backend")
13
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
14
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
15
+ args = parser.parse_args()
16
+ return args
17
+
18
+ if __name__ == "__main__":
19
+ args = parser_args()
20
+ height = args.height
21
+ weight = args.weight
22
+
23
+
24
+ model = Yolov8S(args.target_model, args.weight, args.height, args.cls_num)
25
+ frame = cv2.imread(args.imgs)
26
+
27
+ out_boxes= model(frame, args.invoke_nums)
28
+ print(f"=================== \n Detect {len(out_boxes)} targets.")
29
+ result = draw_detect_res(frame, out_boxes)
30
+ cv2.imwrite("./python/result.jpg", result)
model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/utils.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+
4
+ CLASSES = ("person", "bicycle", "car", "motorbike ", "aeroplane ", "bus ", "train", "truck ", "boat", "traffic light",
5
+ "fire hydrant", "stop sign ", "parking meter", "bench", "bird", "cat", "dog ", "horse ", "sheep", "cow", "elephant",
6
+ "bear", "zebra ", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite",
7
+ "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup", "fork", "knife ",
8
+ "spoon", "bowl", "banana", "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza ", "donut", "cake", "chair", "sofa",
9
+ "pottedplant", "bed", "diningtable", "toilet ", "tvmonitor", "laptop ", "mouse ", "remote ", "keyboard ", "cell phone", "microwave ",
10
+ "oven ", "toaster", "sink", "refrigerator ", "book", "clock", "vase", "scissors ", "teddy bear ", "hair drier", "toothbrush ")
11
+
12
+ def eqprocess(image, size1, size2):
13
+ h,w,_ = image.shape
14
+ mask = np.zeros((size1,size2,3),dtype=np.float32)
15
+ scale1 = h /size1
16
+ scale2 = w / size2
17
+ if scale1 > scale2:
18
+ scale = scale1
19
+ else:
20
+ scale = scale2
21
+ img = cv2.resize(image,(int(w / scale),int(h / scale)))
22
+ mask[:int(h / scale),:int(w / scale),:] = img
23
+ return mask, scale
24
+
25
+ def xywh2xyxy(x):
26
+ '''
27
+ Box (center x, center y, width, height) to (x1, y1, x2, y2)
28
+ '''
29
+ y = np.copy(x)
30
+ y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
31
+ y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
32
+ y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
33
+ y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
34
+ return y
35
+
36
+ def xyxy2xywh(box):
37
+ '''
38
+ Box (left_top x, left_top y, right_bottom x, right_bottom y) to (left_top x, left_top y, width, height)
39
+ '''
40
+ box[:, 2:] = box[:, 2:] - box[:, :2]
41
+ return box
42
+
43
+ def NMS(dets, scores, thresh):
44
+ '''
45
+ 单类NMS算法
46
+ dets.shape = (N, 5), (left_top x, left_top y, right_bottom x, right_bottom y, Scores)
47
+ '''
48
+ x1 = dets[:,0]
49
+ y1 = dets[:,1]
50
+ x2 = dets[:,2]
51
+ y2 = dets[:,3]
52
+ areas = (y2-y1+1) * (x2-x1+1)
53
+ keep = []
54
+ index = scores.argsort()[::-1]
55
+ while index.size >0:
56
+ i = index[0] # every time the first is the biggst, and add it directly
57
+ keep.append(i)
58
+ x11 = np.maximum(x1[i], x1[index[1:]]) # calculate the points of overlap
59
+ y11 = np.maximum(y1[i], y1[index[1:]])
60
+ x22 = np.minimum(x2[i], x2[index[1:]])
61
+ y22 = np.minimum(y2[i], y2[index[1:]])
62
+ w = np.maximum(0, x22-x11+1) # the weights of overlap
63
+ h = np.maximum(0, y22-y11+1) # the height of overlap
64
+ overlaps = w*h
65
+ ious = overlaps / (areas[i]+areas[index[1:]] - overlaps)
66
+ idx = np.where(ious<=thresh)[0]
67
+ index = index[idx+1] # because index start from 1
68
+
69
+ return keep
70
+
71
+
72
+ def draw_detect_res(img, det_pred):
73
+ '''
74
+ 检测结果绘制
75
+ '''
76
+ if det_pred is None:
77
+ return img
78
+
79
+ img = img.astype(np.uint8)
80
+ im_canvas = img.copy()
81
+ color_step = int(255/len(CLASSES))
82
+ for i in range(len(det_pred)):
83
+ x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
84
+ cls_id = int(det_pred[i][5])
85
+ print(i+1,[x1,y1,x2,y2],det_pred[i][4], f'{CLASSES[cls_id]}')
86
+ cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
87
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, int(cls_id*color_step), int(255-cls_id*color_step)),thickness = 2)
88
+ img = cv2.addWeighted(im_canvas, 0.3, img, 0.7, 0)
89
+ return img
90
+
91
+ def scale_mask(masks, im0_shape):
92
+ masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
93
+ interpolation=cv2.INTER_LINEAR)
94
+ if len(masks.shape) == 2:
95
+ masks = masks[:, :, None]
96
+ return masks
97
+
98
+ def crop_mask(masks, boxes):
99
+ n, h, w = masks.shape
100
+ x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
101
+ r = np.arange(w, dtype=x1.dtype)[None, None, :]
102
+ c = np.arange(h, dtype=x1.dtype)[None, :, None]
103
+ return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))
104
+
105
+ def process_mask(protos, masks_in, bboxes, im0_shape):
106
+ c, mh, mw = protos.shape
107
+ masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0) # HWN
108
+ masks = np.ascontiguousarray(masks)
109
+ masks = scale_mask(masks, im0_shape) # re-scale mask from P3 shape to original input image shape
110
+ masks = np.einsum('HWN -> NHW', masks) # HWN -> NHW
111
+ masks = crop_mask(masks, bboxes)
112
+ return np.greater(masks, 0.5)
113
+
114
+ def masks2segments(masks):
115
+ segments = []
116
+ for x in masks.astype('uint8'):
117
+ c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] # CHAIN_APPROX_SIMPLE
118
+ if c:
119
+ c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
120
+ else:
121
+ c = np.zeros((0, 2)) # no segments found
122
+ segments.append(c.astype('float32'))
123
+ return segments
model_farm_yolov8s_qcs8550_qnn2.16_int8_aidlite/python/yolov8s.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import aidlite
4
+ from utils import eqprocess, xywh2xyxy, NMS
5
+ import time
6
+
7
+ OBJ_THRESH = 0.45
8
+ NMS_THRESH = 0.45
9
+
10
+ class Yolov8S(object):
11
+ def __init__(self, model_path, width, height, class_num):
12
+ self.class_num = class_num
13
+ self.width = width
14
+ self.height = height
15
+ input_shape = [[1,height,width,3]]
16
+ self.blocks = int(height * width * ( 1 / 64 + 1 / 256 + 1 / 1024))
17
+ self.maskw = int(width / 4)
18
+ self.maskh = int(height / 4)
19
+ self.output_shape = [[1,4,self.blocks],[1,class_num,self.blocks]]
20
+
21
+ self.model = aidlite.Model.create_instance(model_path)
22
+ if self.model is None:
23
+ print("Create model failed !")
24
+ return
25
+ self.model.set_model_properties(input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
26
+
27
+ self.config = aidlite.Config.create_instance()
28
+ if self.config is None:
29
+ print("build_interpretper_from_model_and_config failed !")
30
+ return
31
+
32
+ self.config.framework_type = aidlite.FrameworkType.TYPE_QNN216
33
+ self.config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
34
+ self.config.is_quantify_model = 1
35
+
36
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(self.model, self.config)
37
+ if self.interpreter is None:
38
+ print("build_interpretper_from_model_and_config failed !")
39
+ return
40
+
41
+ self.interpreter.init()
42
+ self.interpreter.load_model()
43
+
44
+ def __call__(self, frame,invoke_nums):
45
+ img, scale = eqprocess(frame, self.height, self.width)
46
+ img = img / 255
47
+ img = img.astype(np.float32)
48
+ self.interpreter.set_input_tensor(0,img.data)
49
+
50
+ invoke_time=[]
51
+ for i in range(invoke_nums):
52
+ t1=time.time()
53
+ self.interpreter.invoke()
54
+ cost_time = (time.time()-t1)*1000
55
+ invoke_time.append(cost_time)
56
+
57
+ max_invoke_time = max(invoke_time)
58
+ min_invoke_time = min(invoke_time)
59
+ mean_invoke_time = sum(invoke_time)/invoke_nums
60
+ var_invoketime=np.var(invoke_time)
61
+ print("====================================")
62
+ print(f"QNN invoke {invoke_nums} times:\n --mean_invoke_time is {mean_invoke_time} \n --max_invoke_time is {max_invoke_time} \n --min_invoke_time is {min_invoke_time} \n --var_invoketime is {var_invoketime}")
63
+ print("====================================")
64
+
65
+ qnn_1 = self.interpreter.get_output_tensor(0)
66
+ qnn_2 = self.interpreter.get_output_tensor(1)
67
+ qnn_out = sorted([qnn_1,qnn_2], key=len)
68
+
69
+ qnn_local = qnn_out[0].reshape(*self.output_shape[0])
70
+ qnn_conf = qnn_out[1].reshape(*self.output_shape[1])
71
+
72
+
73
+ x = np.concatenate([qnn_local, qnn_conf], axis = 1).transpose(0,2,1)
74
+ x = x[np.amax(x[..., 4:], axis=-1) > OBJ_THRESH]
75
+ if len(x) < 1:
76
+ return None, None
77
+
78
+ x = np.c_[x[..., :4], np.amax(x[..., 4:], axis=-1), np.argmax(x[..., 4:], axis=-1)]
79
+
80
+ x[:, :4] = xywh2xyxy(x[:, :4])
81
+ index = NMS(x[:, :4], x[:, 4], NMS_THRESH)
82
+ out_boxes = x[index]
83
+ out_boxes[..., :4] = out_boxes[..., :4] * scale
84
+
85
+ return out_boxes
86
+