qc903113684 commited on
Commit
cf1ec8b
·
verified ·
1 Parent(s): 58f992b

Upload 32 files

Browse files
Files changed (33) hide show
  1. .gitattributes +8 -0
  2. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/README.md +56 -0
  3. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/cpp/CMakeLists.txt +31 -0
  4. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/cpp/bus.jpg +3 -0
  5. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/cpp/run_test.cpp +485 -0
  6. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin +3 -0
  7. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/bus.jpg +3 -0
  8. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/run_test.py +134 -0
  9. model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/utils.py +124 -0
  10. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/README.md +56 -0
  11. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp/CMakeLists.txt +31 -0
  12. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp/bus.jpg +3 -0
  13. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp/run_test.cpp +484 -0
  14. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/models/cutoff_yolov8s-seg_fp16.qnn216.ctx.bin +3 -0
  15. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/python/bus.jpg +3 -0
  16. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/python/run_test.py +134 -0
  17. model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/python/utils.py +124 -0
  18. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/README.md +56 -0
  19. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp/CMakeLists.txt +31 -0
  20. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp/bus.jpg +3 -0
  21. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp/run_test.cpp +484 -0
  22. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/models/cutoff_yolov8s-seg_w8a16.qnn216.ctx.bin +3 -0
  23. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/python/bus.jpg +3 -0
  24. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/python/run_test.py +134 -0
  25. model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/python/utils.py +124 -0
  26. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/README.md +56 -0
  27. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp/CMakeLists.txt +31 -0
  28. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp/bus.jpg +3 -0
  29. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp/run_test.cpp +484 -0
  30. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin +3 -0
  31. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/python/bus.jpg +3 -0
  32. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/python/run_test.py +134 -0
  33. model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/python/utils.py +124 -0
.gitattributes CHANGED
@@ -33,3 +33,11 @@ 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_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/cpp/bus.jpg filter=lfs diff=lfs merge=lfs -text
37
+ model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
38
+ model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp/bus.jpg filter=lfs diff=lfs merge=lfs -text
39
+ model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
40
+ model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp/bus.jpg filter=lfs diff=lfs merge=lfs -text
41
+ model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
42
+ model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp/bus.jpg filter=lfs diff=lfs merge=lfs -text
43
+ model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/python/bus.jpg filter=lfs diff=lfs merge=lfs -text
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/README.md ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ## Source model
3
+ - Input shape: 640x640
4
+ - Number of parameters: 11.27M
5
+ - Model size: 45.22M
6
+ - Output shape: 1x32x160x160, 1x116x8400
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
+ ## Inference with AidLite SDK
17
+
18
+ ### SDK installation
19
+ 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/)
20
+
21
+ - Install AidLite SDK
22
+
23
+ ```bash
24
+ # Install the appropriate version of the aidlite sdk
25
+ sudo aid-pkg update
26
+ sudo aid-pkg install aidlite-sdk
27
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
28
+ sudo aid-pkg install aidlite-{QNN VERSION}
29
+ ```
30
+
31
+ - Verify AidLite SDK
32
+
33
+ ```bash
34
+ # aidlite sdk c++ check
35
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
36
+
37
+ # aidlite sdk python check
38
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
39
+ ```
40
+
41
+ ### Run demo
42
+ #### python
43
+ ```bash
44
+ cd yolov8s_seg/model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite
45
+ python3 ./python/run_test.py --target_model ./models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin --imgs ./python/bus.jpg --invoke_nums 10
46
+ ```
47
+
48
+ #### cpp
49
+ ```bash
50
+ cd yolov8s_seg/model_farm_yolov5s_qcs6490_qnn2.16_int8_aidlite/cpp
51
+ mkdir build && cd build
52
+ cmake ..
53
+ make
54
+ ./run_test
55
+ ```
56
+
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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}/run_test.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ pthread
31
+ )
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/cpp/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/cpp/run_test.cpp ADDED
@@ -0,0 +1,485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <cstring> // 用于 memcpy
6
+ #include <opencv2/opencv.hpp>
7
+ #include <aidlux/aidlite/aidlite.hpp>
8
+ #include <vector>
9
+ #include <numeric>
10
+
11
+ const float INPUT_WIDTH = 640.0;
12
+ const float INPUT_HEIGHT = 640.0;
13
+ const float SCORE_THRESHOLD = 0.25;
14
+ const float NMS_THRESHOLD = 0.45;
15
+ const float CONFIDENCE_THRESHOLD = 0.25;
16
+ const uint32_t size = 640;
17
+ const uint32_t out_size = 8400;
18
+
19
+ const int FONT_FACE = cv::FONT_HERSHEY_SIMPLEX;
20
+ cv::Scalar WHITE = cv::Scalar(255,255,255);
21
+
22
+ const float FONT_SCALE = 0.75;
23
+ const int THICKNESS = 1;
24
+
25
+ const std::vector<std::string> class_list = {
26
+ "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train",
27
+ "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter",
28
+ "bench", "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear",
29
+ "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase",
30
+ "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
31
+ "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle",
32
+ "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
33
+ "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut",
34
+ "cake", "chair", "couch", "potted plant", "bed", "dining table", "toilet",
35
+ "TV", "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave",
36
+ "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
37
+ "scissors", "teddy bear", "hair drier", "toothbrush"
38
+ };
39
+
40
+ using namespace cv;
41
+ using namespace std;
42
+ using namespace Aidlux::Aidlite;
43
+
44
+ struct Args {
45
+ std::string target_model = "../../models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin";
46
+ std::string imgs = "../bus.jpg";
47
+ int invoke_nums = 10;
48
+ std::string model_type = "QNN";
49
+ };
50
+
51
+ Args parse_args(int argc, char* argv[]) {
52
+ Args args;
53
+ for (int i = 1; i < argc; ++i) {
54
+ std::string arg = argv[i];
55
+ if (arg == "--target_model" && i + 1 < argc) {
56
+ args.target_model = argv[++i];
57
+ } else if (arg == "--imgs" && i + 1 < argc) {
58
+ args.imgs = argv[++i];
59
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
60
+ args.invoke_nums = std::stoi(argv[++i]);
61
+ } else if (arg == "--model_type" && i + 1 < argc) {
62
+ args.model_type = argv[++i];
63
+ }
64
+ }
65
+ return args;
66
+ }
67
+
68
+ std::string to_lower(const std::string& str) {
69
+ std::string lower_str = str;
70
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
71
+ return std::tolower(c);
72
+ });
73
+ return lower_str;
74
+ }
75
+
76
+ // concatenate_3(80_class_data, 4_pos_data , 32_canc_data, 1, 8400, 80, 4,32, qnn_concat);
77
+ void concatenate_3(float* qnn_trans_data, float* qnn_mul_data, float* qnn_canc_data, int batch, int num_elements, int trans_dim, int mul_dim, int canc_dim,std::vector<float>& output) {
78
+ // int out_dim = trans_dim + mul_dim + canc_dim + 1; //117
79
+ int out_dim = trans_dim + mul_dim + canc_dim; //116
80
+ output.resize(batch * num_elements * out_dim);
81
+ for (int i = 0; i < batch * num_elements; ++i) {
82
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
83
+ std::memcpy(&output[i * out_dim + mul_dim], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
84
+ std::memcpy(&output[i * out_dim + mul_dim + trans_dim], &qnn_canc_data[i * canc_dim], canc_dim * sizeof(float));
85
+ }
86
+ }
87
+
88
+ // 4*8400
89
+ void transformData(const float* input, float* output, int C, int N) {
90
+ for (int c = 0; c < C; ++c) {
91
+ for (int n = 0; n < N; ++n) {
92
+ output[n * C + c] = input[c * N + n];
93
+ }
94
+ }
95
+ }
96
+
97
+ double img_process(cv::Mat frame, cv::Mat &img_input, int size) {
98
+ cv::Mat img_processed = frame.clone();
99
+ int height = img_processed.rows;
100
+ int width = img_processed.cols;
101
+ int length = std::max(height, width);
102
+ double scala = static_cast<double>(length) / size;
103
+
104
+ cv::Mat image = cv::Mat::zeros(cv::Size(length, length), CV_8UC3);
105
+ img_processed.copyTo(image(cv::Rect(0, 0, width, height)));
106
+
107
+ cv::cvtColor(image, img_input, cv::COLOR_BGR2RGB);
108
+ cv::resize(img_input, img_input, cv::Size(size, size));
109
+
110
+ cv::Mat mean_data = cv::Mat::zeros(img_input.size(), CV_32FC3);
111
+ cv::Mat std_data(img_input.size(), CV_32FC3, cv::Scalar(255, 255, 255));
112
+ img_input.convertTo(img_input, CV_32FC3);
113
+ img_input = (img_input - mean_data) / std_data;
114
+ return scala;
115
+ }
116
+
117
+
118
+ cv::Scalar generate_colors(int i, bool bgr = false) {
119
+ static const std::vector<std::string> hex_colors = {
120
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
121
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
122
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
123
+ "FF95C8", "FF37C7"
124
+ };
125
+
126
+ int num = hex_colors.size();
127
+ std::string hex = hex_colors[i % num];
128
+
129
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
130
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
131
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
132
+
133
+ if (bgr)
134
+ return cv::Scalar(b, g, r);
135
+ else
136
+ return cv::Scalar(r, g, b);
137
+ }
138
+
139
+ float sigmoid_function(float a)
140
+ {
141
+ float b = 1. / (1. + exp(-a));
142
+ return b;
143
+ }
144
+
145
+ int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
146
+
147
+ int current_coordinate[4] = {0, 0, 0, 0};
148
+ for(int a = 0; a < src_dims[0]; ++a){
149
+ current_coordinate[0] = a;
150
+ for(int b = 0; b < src_dims[1]; ++b){
151
+ current_coordinate[1] = b;
152
+ for(int c = 0; c < src_dims[2]; ++c){
153
+ current_coordinate[2] = c;
154
+ for(int d = 0; d < src_dims[3]; ++d){
155
+ current_coordinate[3] = d;
156
+
157
+ int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
158
+ current_coordinate[1]*src_dims[2]*src_dims[3] +
159
+ current_coordinate[2]*src_dims[3] +
160
+ current_coordinate[3];
161
+
162
+ int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
163
+ current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
164
+ current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
165
+ current_coordinate[tsp_dims[3]];
166
+
167
+ dest[new_index] = src[old_index];
168
+ }
169
+ }
170
+ }
171
+ }
172
+
173
+ return EXIT_SUCCESS;
174
+ }
175
+
176
+
177
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
178
+ {
179
+ int baseLine;
180
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
181
+ int y = top - label_size.height - baseLine;
182
+ if (y < 0) {
183
+ y = top ;
184
+ }
185
+ cv::Point tlc(left, y);
186
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
187
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
188
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
189
+ }
190
+
191
+
192
+ cv::Mat post_process(cv::Mat &frame, std::vector<float> &outputs, const std::vector<std::string> &class_name,
193
+ const double ratio, float* protos_data, float* qnn_canc)
194
+ {
195
+ cv::Mat input_image = frame.clone();
196
+ // Initialize vectors to hold respective outputs while unwrapping detections.
197
+ std::vector<int> class_ids;
198
+ std::vector<float> confidences;
199
+ std::vector<cv::Rect> boxes;
200
+ std::vector<cv::Mat> masks;
201
+ std::vector<float> class_scores;
202
+ cv::RNG rng;
203
+ cv::Mat masked_img;
204
+
205
+ unsigned int src_dims[4] = {1, 32,160,160};
206
+ unsigned int tsp_dims[4] = {0,3,1,2};
207
+ unsigned int stride_data_num = 1*32*160*160;
208
+ float* format_data = new float[stride_data_num];
209
+ transpose(protos_data, src_dims, tsp_dims, format_data);
210
+ cv::Mat proto_buffer(32, 160*160, CV_32F, format_data);
211
+ std::cout << "proto_buffer 维度: " << proto_buffer.rows << "x" << proto_buffer.cols << std::endl;
212
+
213
+ for (int i = 0; i < outputs.size(); i+=116)
214
+ {
215
+ auto start = outputs.begin() + i + 4;
216
+ auto end = outputs.begin() + i + 84;
217
+ float max_val = *std::max_element(start, end);
218
+ float confidence = max_val;
219
+ if (confidence >= CONFIDENCE_THRESHOLD)
220
+ {
221
+ auto start = outputs.begin() + i + 4;
222
+ auto end = outputs.begin() + i + 84;
223
+ std::vector<float> middle_data;
224
+ middle_data.assign(start, end);
225
+ // Create a 1x80 Mat and store class scores of 80 classes.
226
+ cv::Mat scores(1, class_name.size(), CV_32FC1, middle_data.data());
227
+ cv::Point class_id;
228
+ double max_class_score;
229
+
230
+ // For multi-label, check each class score
231
+ for (int c = 0; c < class_name.size(); c++) {
232
+ float class_score = scores.at<float>(0, c);
233
+ // If class score is above threshold, consider this class for the box
234
+ if (class_score > SCORE_THRESHOLD) {
235
+ std::vector<float> last32_data;
236
+ auto st_32= outputs.begin() + i + 84;
237
+ auto ed_32 = outputs.begin() + i + 116;
238
+ last32_data.assign(st_32, ed_32);
239
+ cv::Mat mask(1, 32, CV_32FC1, last32_data.data());
240
+ // Store class ID and confidence in the pre-defined respective vectors.
241
+ confidences.push_back(confidence * class_score); // Multiply with confidence
242
+ class_ids.push_back(c); // class index
243
+ // Center and box dimension.
244
+ float cx = outputs[i];
245
+ float cy = outputs[i+1];
246
+ float w = outputs[i+2];
247
+ float h = outputs[i+3];
248
+
249
+ int left = int((cx - 0.5 * w) * ratio);
250
+ int top = int((cy - 0.48 * h) * ratio);
251
+ int width = int(w * ratio);
252
+ int height = int(h * ratio);
253
+
254
+ // Store good detections in the boxes vector.
255
+ boxes.push_back(cv::Rect(left, top, width, height));
256
+ masks.push_back(mask);
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+ std::cout << "boxes.size(): " << boxes.size() << ",confidences.size():" << confidences.size() << std::endl;
263
+
264
+ // Perform Non Maximum Suppression and draw predictions.
265
+ std::vector<int> indices;
266
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
267
+ printf("Detected {%ld} targets.\n", indices.size());
268
+ cv::Mat rgb_mask = cv::Mat::zeros(input_image.size(), input_image.type());
269
+
270
+ // Loop over NMS results and draw bounding boxes
271
+ for (int i = 0; i < indices.size(); i++)
272
+ {
273
+ int idx = indices[i];
274
+ cv::Rect box = boxes[idx];
275
+ cv::Scalar color = generate_colors(class_ids[idx]);
276
+
277
+ int x1 = std::max(0, box.x);
278
+ int y1 = std::max(0, box.y);
279
+ int x2 = std::max(0, box.br().x);
280
+ int y2 = std::max(0, box.br().y);
281
+ cv::Mat ms = masks[idx];
282
+ // 维度验证
283
+ if (ms.cols != proto_buffer.rows) {
284
+ cerr << "维度不匹配: mask.cols=" << ms.cols
285
+ << ", proto_buffer.rows=" << proto_buffer.rows << endl;
286
+ continue;
287
+ }
288
+ cv::Mat m = ms * proto_buffer;
289
+ for (int col = 0; col < m.cols; col++) {
290
+ m.at<float>(0, col) = sigmoid_function(m.at<float>(0, col));
291
+ }
292
+ cv::Mat m1 = m.reshape(1, 160); // 1x25600 -> 160x160
293
+
294
+ float ratio2 = 160.0/640.0;
295
+ int mx1 = std::max(0, int((x1 * ratio2)));
296
+ int mx2 = std::max(0, int((x2 * ratio2)));
297
+ int my1 = std::max(0, int((y1 * ratio2)));
298
+ int my2 = std::max(0, int((y2 * ratio2)));
299
+ cv::Mat mask_roi = m1(cv::Range(my1, my2), cv::Range(mx1, mx2));
300
+ cv::Mat rm, det_mask;
301
+ cv::resize(mask_roi, rm, cv::Size(x2 - x1, y2 - y1));
302
+ for (int r = 0; r < rm.rows; r++) {
303
+ for (int c = 0; c < rm.cols; c++) {
304
+ float pv = rm.at<float>(r, c);
305
+ if (pv > 0.5) {
306
+ rm.at<float>(r, c) = 1.0;
307
+ }
308
+ else {
309
+ rm.at<float>(r, c) = 0.0;
310
+ }
311
+ }
312
+ }
313
+ rm = rm * rng.uniform(0, 255);
314
+ rm.convertTo(det_mask, CV_8UC1);
315
+ if ((y1 + det_mask.rows) >= input_image.rows) {
316
+ y2 = input_image.rows - 1;
317
+ }
318
+ if ((x1 + det_mask.cols) >= input_image.cols) {
319
+ x2 = input_image.cols - 1;
320
+ }
321
+
322
+ cv::Mat mask = cv::Mat::zeros(cv::Size(input_image.cols, input_image.rows), CV_8UC1);
323
+ det_mask(cv::Range(0, y2 - y1), cv::Range(0, x2 - x1)).copyTo(mask(cv::Range(y1, y2), cv::Range(x1, x2)));
324
+ add(rgb_mask, cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), rgb_mask, mask);
325
+ if (input_image.size() != rgb_mask.size()) {
326
+ cv::resize(rgb_mask, rgb_mask, input_image.size());
327
+ }
328
+
329
+ cv::rectangle(input_image, boxes[idx], color, 2, 8);
330
+ std::string label = cv::format("%.2f", confidences[idx]);
331
+ label = class_name[class_ids[idx]] + ":" + label;
332
+ cv::putText(input_image, label, cv::Point(boxes[idx].tl().x, boxes[idx].tl().y - 10), cv::FONT_HERSHEY_SIMPLEX, .5, color);
333
+ cv::addWeighted(input_image, 0.5, rgb_mask, 0.5, 0, masked_img);
334
+
335
+ }
336
+ printf("Processing finished.\n");
337
+ return masked_img;
338
+ }
339
+
340
+
341
+
342
+ int invoke(const Args& args) {
343
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
344
+ << "Image Path: " << args.imgs << "\n"
345
+ << "Inference Nums: " << args.invoke_nums << "\n"
346
+ << "Model Type: " << args.model_type << "\n";
347
+ Model* model = Model::create_instance(args.target_model);
348
+ if(model == nullptr){
349
+ printf("Create model failed !\n");
350
+ return EXIT_FAILURE;
351
+ }
352
+ Config* config = Config::create_instance();
353
+ if(config == nullptr){
354
+ printf("Create config failed !\n");
355
+ return EXIT_FAILURE;
356
+ }
357
+ config->implement_type = ImplementType::TYPE_LOCAL;
358
+ std::string model_type_lower = to_lower(args.model_type);
359
+ if (model_type_lower == "qnn"){
360
+ config->framework_type = FrameworkType::TYPE_QNN216;
361
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
362
+ config->framework_type = FrameworkType::TYPE_SNPE2;
363
+ }
364
+ config->accelerate_type = AccelerateType::TYPE_DSP;
365
+ config->is_quantify_model = 1;
366
+
367
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, size, size, 3}};
368
+ std::vector<std::vector<uint32_t>> output_shapes = {{1,32,8400},{1,4,8400},{1,80,8400},{1,160, 160,32}};
369
+ model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
370
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
371
+ if(fast_interpreter == nullptr){
372
+ printf("build_interpretper_from_model_and_config failed !\n");
373
+ return EXIT_FAILURE;
374
+ }
375
+ int result = fast_interpreter->init();
376
+ if(result != EXIT_SUCCESS){
377
+ printf("interpreter->init() failed !\n");
378
+ return EXIT_FAILURE;
379
+ }
380
+ // load model
381
+ fast_interpreter->load_model();
382
+ if(result != EXIT_SUCCESS){
383
+ printf("interpreter->load_model() failed !\n");
384
+ return EXIT_FAILURE;
385
+ }
386
+ printf("detect model load success!\n");
387
+
388
+ cv::Mat frame = cv::imread(args.imgs);
389
+ if (frame.empty()) {
390
+ printf("detect image load failed!\n");
391
+ return 1;
392
+ }
393
+ printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
394
+ cv::Mat input_img;
395
+ double scale = img_process(frame, input_img, size);
396
+ if (input_img.empty()) {
397
+ printf("detect input_img load failed!\n");
398
+ return 1;
399
+ }
400
+
401
+ float *qnn_seg_data = nullptr;
402
+ float *qnn_trans_data = nullptr;
403
+ float *qnn_mul_data = nullptr;
404
+ float *qnn_canc_data = nullptr;
405
+
406
+ std::vector<float> invoke_time;
407
+ for (int i = 0; i < args.invoke_nums; ++i) {
408
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
409
+ if(result != EXIT_SUCCESS){
410
+ printf("interpreter->set_input_tensor() failed !\n");
411
+ return EXIT_FAILURE;
412
+ }
413
+ // 开始计时
414
+ auto t1 = std::chrono::high_resolution_clock::now();
415
+ result = fast_interpreter->invoke();
416
+ auto t2 = std::chrono::high_resolution_clock::now();
417
+ std::chrono::duration<double> cost_time = t2 - t1;
418
+ invoke_time.push_back(cost_time.count() * 1000);
419
+ if(result != EXIT_SUCCESS){
420
+ printf("interpreter->invoke() failed !\n");
421
+ return EXIT_FAILURE;
422
+ }
423
+ uint32_t out_data_1 = 0;
424
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_canc_data, &out_data_1);
425
+ if(result != EXIT_SUCCESS){
426
+ printf("interpreter->get_output_tensor() 1 failed !\n");
427
+ return EXIT_FAILURE;
428
+ }
429
+
430
+ uint32_t out_data_4 = 0;
431
+ result = fast_interpreter->get_output_tensor(2, (void**)&qnn_trans_data, &out_data_4);
432
+ if(result != EXIT_SUCCESS){
433
+ printf("interpreter->get_output_tensor() 2 failed !\n");
434
+ return EXIT_FAILURE;
435
+ }
436
+
437
+ uint32_t out_data_2 = 0;
438
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_seg_data, &out_data_2);
439
+ if(result != EXIT_SUCCESS){
440
+ printf("interpreter->get_output_tensor() 2 failed !\n");
441
+ return EXIT_FAILURE;
442
+ }
443
+
444
+ uint32_t out_data_80 = 0;
445
+ result = fast_interpreter->get_output_tensor(3, (void**)&qnn_mul_data, &out_data_80);
446
+ if(result != EXIT_SUCCESS){
447
+ printf("interpreter->get_output_tensor() 2 failed !\n");
448
+ return EXIT_FAILURE;
449
+ }
450
+ }
451
+
452
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
453
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
454
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
455
+ float var_invoketime = 0.0f;
456
+ for (auto time : invoke_time) {
457
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
458
+ }
459
+ var_invoketime /= args.invoke_nums;
460
+ printf("=======================================\n");
461
+ 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",
462
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
463
+ printf("=======================================\n");
464
+
465
+ float* pos_data = new float[4 * out_size];
466
+ float* class_data = new float[80 * out_size];
467
+ float* canc_data = new float[32 * out_size];
468
+ transformData(qnn_trans_data, pos_data, 4, out_size);
469
+ transformData(qnn_mul_data, class_data, 80, out_size);
470
+ transformData(qnn_canc_data, canc_data, 32, out_size);
471
+
472
+ // post process
473
+ std::vector<float> qnn_concat;
474
+ concatenate_3(class_data, pos_data, canc_data , 1, out_size, 80, 4, 32, qnn_concat);
475
+ cv::Mat img = post_process(frame, qnn_concat, class_list, scale, qnn_seg_data, qnn_canc_data);
476
+ cv::imwrite("./results.png", img);
477
+ fast_interpreter->destory();
478
+ return 0;
479
+ }
480
+
481
+
482
+ int main(int argc, char* argv[]) {
483
+ Args args = parse_args(argc, argv);
484
+ return invoke(args);
485
+ }
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:48497c146c2f745ed415a5a079396443152caadc4fa5d34740e5e8b8a9c6b4a1
3
+ size 12515768
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/run_test.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import aidlite
4
+ from utils import eqprocess, xywh2xyxy, NMS, process_mask, masks2segments, draw_detect_res
5
+ import os
6
+ import time
7
+ import argparse
8
+ import onnxruntime
9
+
10
+ # 定义相似度函数
11
+ def get_acc(onnx_out,other_out):
12
+ cosine_similarity=np.dot(np.array(onnx_out),np.array(other_out))/(np.linalg.norm(np.array(onnx_out)) * np.linalg.norm(np.array(other_out)))
13
+ return cosine_similarity
14
+
15
+
16
+ class qnn_predict(object):
17
+ def __init__(self,args) -> None:
18
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
19
+ # aidlite.log_to_stderr()
20
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
21
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
22
+ config = aidlite.Config.create_instance()
23
+ if config is None:
24
+ print("Create model failed !")
25
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
26
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN
27
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
28
+ config.is_quantify_model = 1
29
+
30
+ model = aidlite.Model.create_instance(args.target_model)
31
+ if model is None:
32
+ print("Create model failed !")
33
+
34
+ self.conf = args.conf_thres
35
+ self.iou=args.iou_thres
36
+ self.width = args.width
37
+ self.height = args.height
38
+ self.class_num = args.class_num
39
+ self.input_shape = [[1,self.height,self.width,3]]
40
+ self.blocks = int(self.height * self.width * ( 1 / 64 + 1 / 256 + 1 / 1024))
41
+ self.maskw = int(self.width / 4)
42
+ self.maskh = int(self.height / 4)
43
+ self.output_shape = [[1,32,self.blocks],[1,4,self.blocks],[1,self.class_num,self.blocks],[1,self.maskh, self.maskw,32]]
44
+
45
+ model.set_model_properties(self.input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
46
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
47
+ if self.interpreter is None:
48
+ print("build_interpretper_from_model_and_config failed !")
49
+ result = self.interpreter.init()
50
+ if result != 0:
51
+ print(f"interpreter init failed !")
52
+ result = self.interpreter.load_model()
53
+ if result != 0:
54
+ print("interpreter load model failed !")
55
+ print("detect model load success!")
56
+
57
+ def pretreat_img(self,frame):
58
+ img, scale = eqprocess(frame, self.height, self.width)
59
+ img = img / 255
60
+ img = img.astype(np.float32)
61
+ return img,scale
62
+
63
+ def qnn_run(self, orig_imgs,args):
64
+ input_img_f,scale=self.pretreat_img(orig_imgs) # 图片resize HWC
65
+ input_img = np.expand_dims(input_img_f, 0)
66
+
67
+ invoke_time=[]
68
+ for i in range(args.invoke_nums):
69
+ self.interpreter.set_input_tensor(0, input_img.data)
70
+ t0 = time.time()
71
+ self.interpreter.invoke()
72
+ t1 = time.time()
73
+ cost_time=(t1-t0)*1000
74
+ invoke_time.append(cost_time)
75
+
76
+ input0_data = self.interpreter.get_output_tensor(2).reshape(1,4,self.blocks)
77
+ input1_data = self.interpreter.get_output_tensor(3).reshape(1,self.class_num,self.blocks)
78
+ input2_data = self.interpreter.get_output_tensor(1).reshape(1,32,self.blocks)
79
+ protos = self.interpreter.get_output_tensor(0).reshape(1,self.maskh, self.maskw,32).transpose(0,3,1,2)
80
+
81
+ boxes = np.concatenate([input0_data, input1_data, input2_data], axis = 1)
82
+ x = boxes.transpose(0,2,1)
83
+ x = x[np.amax(x[..., 4:-32], axis=-1) > self.conf]
84
+ if len(x) < 1:
85
+ return None, None
86
+
87
+ x = np.c_[x[..., :4], np.amax(x[..., 4:-32], axis=-1), np.argmax(x[..., 4:-32], axis=-1), x[..., -32:]]
88
+
89
+ x[:, :4] = xywh2xyxy(x[:, :4])
90
+ index = NMS(x[:, :4], x[:, 4], self.iou)
91
+ out_boxes = x[index]
92
+ out_boxes[..., :4] = out_boxes[..., :4] * scale
93
+
94
+ masks = process_mask(protos[0], out_boxes[:, -32:], out_boxes[:, :4], orig_imgs.shape)
95
+ segments = masks2segments(masks)
96
+
97
+ ## time 统计
98
+ max_invoke_time = max(invoke_time)
99
+ min_invoke_time = min(invoke_time)
100
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
101
+ var_invoketime=np.var(invoke_time)
102
+ print("========================================")
103
+ 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}")
104
+ print("========================================")
105
+
106
+ return out_boxes, segments
107
+
108
+
109
+ def parser_args():
110
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
111
+ parser.add_argument('--target_model',type=str,default='/home/aidlux/modelfarm/yolov8s_seg/model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin',help="inference model path")
112
+ parser.add_argument('--imgs',type=str,default='/home/aidlux/modelfarm/yolov8s_seg/model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/bus.jpg',help="Predict images path")
113
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
114
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
115
+ parser.add_argument('--width',type=int,default=640,help="Model input size")
116
+ parser.add_argument('--height',type=int,default=640,help="Model input size")
117
+ parser.add_argument('--conf_thres',type=float,default=0.45,help="confidence threshold for filtering the annotations")
118
+ parser.add_argument('--iou_thres',type=float,default=0.45,help="Iou threshold for filtering the annotations")
119
+ parser.add_argument('--class_num',type=int,default=80,help="Iou threshold for filtering the annotations")
120
+ args = parser.parse_args()
121
+ return args
122
+
123
+ def main(args):
124
+ model = qnn_predict(args)
125
+ frame = cv2.imread(args.imgs)
126
+ qnn_out_boxes, qnn_segments = model.qnn_run(frame,args)
127
+ result = draw_detect_res(frame, qnn_out_boxes, qnn_segments)
128
+ cv2.imwrite("./bus_result.jpg", result)
129
+
130
+ if __name__ == "__main__":
131
+ args = parser_args()
132
+ main(args)
133
+
134
+
model_farm_yolov8s_seg_qsc6490_qnn2.16_int8_aidlite/python/utils.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ def draw_detect_res(img, det_pred, segments):
72
+ '''
73
+ 检测结果绘制
74
+ '''
75
+ if det_pred is None:
76
+ return img
77
+
78
+ img = img.astype(np.uint8)
79
+ im_canvas = img.copy()
80
+ color_step = int(255/len(CLASSES))
81
+ for i in range(len(det_pred)):
82
+ x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
83
+ cls_id = int(det_pred[i][5])
84
+ cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
85
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, int(cls_id*color_step), int(255-cls_id*color_step)),thickness = 2)
86
+ if len(segments[i]) > 0:
87
+ cv2.polylines(img, np.int32([segments[i]]), True, (0, int(cls_id*color_step), int(255-cls_id*color_step)), 2)
88
+ cv2.fillPoly(img, np.int32([segments[i]]), (0, int(cls_id*color_step), int(255-cls_id*color_step)))
89
+ img = cv2.addWeighted(im_canvas, 0.3, img, 0.7, 0)
90
+ return img
91
+
92
+ def scale_mask(masks, im0_shape):
93
+ masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
94
+ interpolation=cv2.INTER_LINEAR)
95
+ if len(masks.shape) == 2:
96
+ masks = masks[:, :, None]
97
+ return masks
98
+
99
+ def crop_mask(masks, boxes):
100
+ n, h, w = masks.shape
101
+ x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
102
+ r = np.arange(w, dtype=x1.dtype)[None, None, :]
103
+ c = np.arange(h, dtype=x1.dtype)[None, :, None]
104
+ return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))
105
+
106
+ def process_mask(protos, masks_in, bboxes, im0_shape):
107
+ c, mh, mw = protos.shape
108
+ masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0) # HWN
109
+ masks = np.ascontiguousarray(masks)
110
+ masks = scale_mask(masks, im0_shape) # re-scale mask from P3 shape to original input image shape
111
+ masks = np.einsum('HWN -> NHW', masks) # HWN -> NHW
112
+ masks = crop_mask(masks, bboxes)
113
+ return np.greater(masks, 0.5)
114
+
115
+ def masks2segments(masks):
116
+ segments = []
117
+ for x in masks.astype('uint8'):
118
+ c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] # CHAIN_APPROX_SIMPLE
119
+ if c:
120
+ c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
121
+ else:
122
+ c = np.zeros((0, 2)) # no segments found
123
+ segments.append(c.astype('float32'))
124
+ return segments
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/README.md ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ## Source model
3
+ - Input shape: 640x640
4
+ - Number of parameters: 11.27M
5
+ - Model size: 45.22M
6
+ - Output shape: 1x32x160x160, 1x116x8400
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
+ ## Inference with AidLite SDK
17
+
18
+ ### SDK installation
19
+ 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/)
20
+
21
+ - Install AidLite SDK
22
+
23
+ ```bash
24
+ # Install the appropriate version of the aidlite sdk
25
+ sudo aid-pkg update
26
+ sudo aid-pkg install aidlite-sdk
27
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
28
+ sudo aid-pkg install aidlite-{QNN VERSION}
29
+ ```
30
+
31
+ - Verify AidLite SDK
32
+
33
+ ```bash
34
+ # aidlite sdk c++ check
35
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
36
+
37
+ # aidlite sdk python check
38
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
39
+ ```
40
+
41
+ ### Run demo
42
+ #### python
43
+ ```bash
44
+ cd yolov8s_seg/model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite
45
+ python3 ./python/run_test.py --target_model ./models/cutoff_yolov8s-seg_fp16.qnn216.ctx.bin --imgs ./python/bus.jpg --invoke_nums 10
46
+ ```
47
+
48
+ #### cpp
49
+ ```bash
50
+ cd yolov8s_seg/model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp
51
+ mkdir build && cd build
52
+ cmake ..
53
+ make
54
+ ./run_test
55
+ ```
56
+
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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}/run_test.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ pthread
31
+ )
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/cpp/run_test.cpp ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <cstring> // 用于 memcpy
6
+ #include <opencv2/opencv.hpp>
7
+ #include <aidlux/aidlite/aidlite.hpp>
8
+ #include <vector>
9
+ #include <numeric>
10
+
11
+ const float INPUT_WIDTH = 640.0;
12
+ const float INPUT_HEIGHT = 640.0;
13
+ const float SCORE_THRESHOLD = 0.25;
14
+ const float NMS_THRESHOLD = 0.45;
15
+ const float CONFIDENCE_THRESHOLD = 0.25;
16
+ const int 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 cv;
40
+ using namespace std;
41
+ using namespace Aidlux::Aidlite;
42
+
43
+ struct Args {
44
+ std::string target_model = "../../models/cutoff_yolov8s-seg_fp16.qnn216.ctx.bin";
45
+ std::string imgs = "../bus.jpg";
46
+ int invoke_nums = 10;
47
+ std::string model_type = "QNN";
48
+ };
49
+
50
+ Args parse_args(int argc, char* argv[]) {
51
+ Args args;
52
+ for (int i = 1; i < argc; ++i) {
53
+ std::string arg = argv[i];
54
+ if (arg == "--target_model" && i + 1 < argc) {
55
+ args.target_model = argv[++i];
56
+ } else if (arg == "--imgs" && i + 1 < argc) {
57
+ args.imgs = argv[++i];
58
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
59
+ args.invoke_nums = std::stoi(argv[++i]);
60
+ } else if (arg == "--model_type" && i + 1 < argc) {
61
+ args.model_type = argv[++i];
62
+ }
63
+ }
64
+ return args;
65
+ }
66
+
67
+ std::string to_lower(const std::string& str) {
68
+ std::string lower_str = str;
69
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
70
+ return std::tolower(c);
71
+ });
72
+ return lower_str;
73
+ }
74
+
75
+ // concatenate_3(80_class_data, 4_pos_data , 32_canc_data, 1, 8400, 80, 4,32, qnn_concat);
76
+ void concatenate_3(float* qnn_trans_data, float* qnn_mul_data, float* qnn_canc_data, int batch, int num_elements, int trans_dim, int mul_dim, int canc_dim,std::vector<float>& output) {
77
+ // int out_dim = trans_dim + mul_dim + canc_dim + 1; //117
78
+ int out_dim = trans_dim + mul_dim + canc_dim; //116
79
+ output.resize(batch * num_elements * out_dim);
80
+ for (int i = 0; i < batch * num_elements; ++i) {
81
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
82
+ std::memcpy(&output[i * out_dim + mul_dim], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
83
+ std::memcpy(&output[i * out_dim + mul_dim + trans_dim], &qnn_canc_data[i * canc_dim], canc_dim * sizeof(float));
84
+ }
85
+ }
86
+
87
+ // 4*8400
88
+ void transformData(const float* input, float* output, int C, int N) {
89
+ for (int c = 0; c < C; ++c) {
90
+ for (int n = 0; n < N; ++n) {
91
+ output[n * C + c] = input[c * N + n];
92
+ }
93
+ }
94
+ }
95
+
96
+ double img_process(cv::Mat frame, cv::Mat &img_input, int size) {
97
+ cv::Mat img_processed = frame.clone();
98
+ int height = img_processed.rows;
99
+ int width = img_processed.cols;
100
+ int length = std::max(height, width);
101
+ double scala = static_cast<double>(length) / size;
102
+
103
+ cv::Mat image = cv::Mat::zeros(cv::Size(length, length), CV_8UC3);
104
+ img_processed.copyTo(image(cv::Rect(0, 0, width, height)));
105
+
106
+ cv::cvtColor(image, img_input, cv::COLOR_BGR2RGB);
107
+ cv::resize(img_input, img_input, cv::Size(size, size));
108
+
109
+ cv::Mat mean_data = cv::Mat::zeros(img_input.size(), CV_32FC3);
110
+ cv::Mat std_data(img_input.size(), CV_32FC3, cv::Scalar(255, 255, 255));
111
+ img_input.convertTo(img_input, CV_32FC3);
112
+ img_input = (img_input - mean_data) / std_data;
113
+ return scala;
114
+ }
115
+
116
+
117
+ cv::Scalar generate_colors(int i, bool bgr = false) {
118
+ static const std::vector<std::string> hex_colors = {
119
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
120
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
121
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
122
+ "FF95C8", "FF37C7"
123
+ };
124
+
125
+ int num = hex_colors.size();
126
+ std::string hex = hex_colors[i % num];
127
+
128
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
129
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
130
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
131
+
132
+ if (bgr)
133
+ return cv::Scalar(b, g, r);
134
+ else
135
+ return cv::Scalar(r, g, b);
136
+ }
137
+
138
+ float sigmoid_function(float a)
139
+ {
140
+ float b = 1. / (1. + exp(-a));
141
+ return b;
142
+ }
143
+
144
+ int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
145
+
146
+ int current_coordinate[4] = {0, 0, 0, 0};
147
+ for(int a = 0; a < src_dims[0]; ++a){
148
+ current_coordinate[0] = a;
149
+ for(int b = 0; b < src_dims[1]; ++b){
150
+ current_coordinate[1] = b;
151
+ for(int c = 0; c < src_dims[2]; ++c){
152
+ current_coordinate[2] = c;
153
+ for(int d = 0; d < src_dims[3]; ++d){
154
+ current_coordinate[3] = d;
155
+
156
+ int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
157
+ current_coordinate[1]*src_dims[2]*src_dims[3] +
158
+ current_coordinate[2]*src_dims[3] +
159
+ current_coordinate[3];
160
+
161
+ int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
162
+ current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
163
+ current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
164
+ current_coordinate[tsp_dims[3]];
165
+
166
+ dest[new_index] = src[old_index];
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ return EXIT_SUCCESS;
173
+ }
174
+
175
+
176
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
177
+ {
178
+ int baseLine;
179
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
180
+ int y = top - label_size.height - baseLine;
181
+ if (y < 0) {
182
+ y = top ;
183
+ }
184
+ cv::Point tlc(left, y);
185
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
186
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
187
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
188
+ }
189
+
190
+
191
+ cv::Mat post_process(cv::Mat &frame, std::vector<float> &outputs, const std::vector<std::string> &class_name,
192
+ const double ratio, float* protos_data, float* qnn_canc)
193
+ {
194
+ cv::Mat input_image = frame.clone();
195
+ // Initialize vectors to hold respective outputs while unwrapping detections.
196
+ std::vector<int> class_ids;
197
+ std::vector<float> confidences;
198
+ std::vector<cv::Rect> boxes;
199
+ std::vector<cv::Mat> masks;
200
+ std::vector<float> class_scores;
201
+ cv::RNG rng;
202
+ cv::Mat masked_img;
203
+
204
+ unsigned int src_dims[4] = {1, 32,160,160};
205
+ unsigned int tsp_dims[4] = {0,3,1,2};
206
+ unsigned int stride_data_num = 1*32*160*160;
207
+ float* format_data = new float[stride_data_num];
208
+ transpose(protos_data, src_dims, tsp_dims, format_data);
209
+ cv::Mat proto_buffer(32, 160*160, CV_32F, format_data);
210
+ std::cout << "proto_buffer 维度: " << proto_buffer.rows << "x" << proto_buffer.cols << std::endl;
211
+
212
+ for (int i = 0; i < outputs.size(); i+=116)
213
+ {
214
+ auto start = outputs.begin() + i + 4;
215
+ auto end = outputs.begin() + i + 84;
216
+ float max_val = *std::max_element(start, end);
217
+ float confidence = max_val;
218
+ if (confidence >= CONFIDENCE_THRESHOLD)
219
+ {
220
+ auto start = outputs.begin() + i + 4;
221
+ auto end = outputs.begin() + i + 84;
222
+ std::vector<float> middle_data;
223
+ middle_data.assign(start, end);
224
+ // Create a 1x80 Mat and store class scores of 80 classes.
225
+ cv::Mat scores(1, class_name.size(), CV_32FC1, middle_data.data());
226
+ cv::Point class_id;
227
+ double max_class_score;
228
+
229
+ // For multi-label, check each class score
230
+ for (int c = 0; c < class_name.size(); c++) {
231
+ float class_score = scores.at<float>(0, c);
232
+ // If class score is above threshold, consider this class for the box
233
+ if (class_score > SCORE_THRESHOLD) {
234
+ std::vector<float> last32_data;
235
+ auto st_32= outputs.begin() + i + 84;
236
+ auto ed_32 = outputs.begin() + i + 116;
237
+ last32_data.assign(st_32, ed_32);
238
+ cv::Mat mask(1, 32, CV_32FC1, last32_data.data());
239
+ // Store class ID and confidence in the pre-defined respective vectors.
240
+ confidences.push_back(confidence * class_score); // Multiply with confidence
241
+ class_ids.push_back(c); // class index
242
+ // Center and box dimension.
243
+ float cx = outputs[i];
244
+ float cy = outputs[i+1];
245
+ float w = outputs[i+2];
246
+ float h = outputs[i+3];
247
+
248
+ int left = int((cx - 0.5 * w) * ratio);
249
+ int top = int((cy - 0.48 * h) * ratio);
250
+ int width = int(w * ratio);
251
+ int height = int(h * ratio);
252
+
253
+ // Store good detections in the boxes vector.
254
+ boxes.push_back(cv::Rect(left, top, width, height));
255
+ masks.push_back(mask);
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ std::cout << "boxes.size(): " << boxes.size() << ",confidences.size():" << confidences.size() << std::endl;
262
+
263
+ // Perform Non Maximum Suppression and draw predictions.
264
+ std::vector<int> indices;
265
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
266
+ printf("Detected {%ld} targets.\n", indices.size());
267
+ cv::Mat rgb_mask = cv::Mat::zeros(input_image.size(), input_image.type());
268
+
269
+ // Loop over NMS results and draw bounding boxes
270
+ for (int i = 0; i < indices.size(); i++)
271
+ {
272
+ int idx = indices[i];
273
+ cv::Rect box = boxes[idx];
274
+ cv::Scalar color = generate_colors(class_ids[idx]);
275
+
276
+ int x1 = std::max(0, box.x);
277
+ int y1 = std::max(0, box.y);
278
+ int x2 = std::max(0, box.br().x);
279
+ int y2 = std::max(0, box.br().y);
280
+ cv::Mat ms = masks[idx];
281
+ // 维度验证
282
+ if (ms.cols != proto_buffer.rows) {
283
+ cerr << "维度不匹配: mask.cols=" << ms.cols
284
+ << ", proto_buffer.rows=" << proto_buffer.rows << endl;
285
+ continue;
286
+ }
287
+ cv::Mat m = ms * proto_buffer;
288
+ for (int col = 0; col < m.cols; col++) {
289
+ m.at<float>(0, col) = sigmoid_function(m.at<float>(0, col));
290
+ }
291
+ cv::Mat m1 = m.reshape(1, 160); // 1x25600 -> 160x160
292
+
293
+ float ratio2 = 160.0/640.0;
294
+ int mx1 = std::max(0, int((x1 * ratio2)));
295
+ int mx2 = std::max(0, int((x2 * ratio2)));
296
+ int my1 = std::max(0, int((y1 * ratio2)));
297
+ int my2 = std::max(0, int((y2 * ratio2)));
298
+ cv::Mat mask_roi = m1(cv::Range(my1, my2), cv::Range(mx1, mx2));
299
+ cv::Mat rm, det_mask;
300
+ cv::resize(mask_roi, rm, cv::Size(x2 - x1, y2 - y1));
301
+ for (int r = 0; r < rm.rows; r++) {
302
+ for (int c = 0; c < rm.cols; c++) {
303
+ float pv = rm.at<float>(r, c);
304
+ if (pv > 0.5) {
305
+ rm.at<float>(r, c) = 1.0;
306
+ }
307
+ else {
308
+ rm.at<float>(r, c) = 0.0;
309
+ }
310
+ }
311
+ }
312
+ rm = rm * rng.uniform(0, 255);
313
+ rm.convertTo(det_mask, CV_8UC1);
314
+ if ((y1 + det_mask.rows) >= input_image.rows) {
315
+ y2 = input_image.rows - 1;
316
+ }
317
+ if ((x1 + det_mask.cols) >= input_image.cols) {
318
+ x2 = input_image.cols - 1;
319
+ }
320
+
321
+ cv::Mat mask = cv::Mat::zeros(cv::Size(input_image.cols, input_image.rows), CV_8UC1);
322
+ det_mask(cv::Range(0, y2 - y1), cv::Range(0, x2 - x1)).copyTo(mask(cv::Range(y1, y2), cv::Range(x1, x2)));
323
+ add(rgb_mask, cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), rgb_mask, mask);
324
+ if (input_image.size() != rgb_mask.size()) {
325
+ cv::resize(rgb_mask, rgb_mask, input_image.size());
326
+ }
327
+
328
+ cv::rectangle(input_image, boxes[idx], color, 2, 8);
329
+ std::string label = cv::format("%.2f", confidences[idx]);
330
+ label = class_name[class_ids[idx]] + ":" + label;
331
+ cv::putText(input_image, label, cv::Point(boxes[idx].tl().x, boxes[idx].tl().y - 10), cv::FONT_HERSHEY_SIMPLEX, .5, color);
332
+ cv::addWeighted(input_image, 0.5, rgb_mask, 0.5, 0, masked_img);
333
+
334
+ }
335
+ printf("Processing finished.\n");
336
+ return masked_img;
337
+ }
338
+
339
+
340
+
341
+ int invoke(const Args& args) {
342
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
343
+ << "Image Path: " << args.imgs << "\n"
344
+ << "Inference Nums: " << args.invoke_nums << "\n"
345
+ << "Model Type: " << args.model_type << "\n";
346
+ Model* model = Model::create_instance(args.target_model);
347
+ if(model == nullptr){
348
+ printf("Create model failed !\n");
349
+ return EXIT_FAILURE;
350
+ }
351
+ Config* config = Config::create_instance();
352
+ if(config == nullptr){
353
+ printf("Create config failed !\n");
354
+ return EXIT_FAILURE;
355
+ }
356
+ config->implement_type = ImplementType::TYPE_LOCAL;
357
+ std::string model_type_lower = to_lower(args.model_type);
358
+ if (model_type_lower == "qnn"){
359
+ config->framework_type = FrameworkType::TYPE_QNN;
360
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
361
+ config->framework_type = FrameworkType::TYPE_SNPE2;
362
+ }
363
+ config->accelerate_type = AccelerateType::TYPE_DSP;
364
+ config->is_quantify_model = 1;
365
+
366
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, 640, 640, 3}};
367
+ std::vector<std::vector<uint32_t>> output_shapes = {{1,32,8400},{1,4,8400},{1,80,8400},{1,160, 160,32}};
368
+ model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
369
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
370
+ if(fast_interpreter == nullptr){
371
+ printf("build_interpretper_from_model_and_config failed !\n");
372
+ return EXIT_FAILURE;
373
+ }
374
+ int result = fast_interpreter->init();
375
+ if(result != EXIT_SUCCESS){
376
+ printf("interpreter->init() failed !\n");
377
+ return EXIT_FAILURE;
378
+ }
379
+ // load model
380
+ fast_interpreter->load_model();
381
+ if(result != EXIT_SUCCESS){
382
+ printf("interpreter->load_model() failed !\n");
383
+ return EXIT_FAILURE;
384
+ }
385
+ printf("detect model load success!\n");
386
+
387
+ cv::Mat frame = cv::imread(args.imgs);
388
+ if (frame.empty()) {
389
+ printf("detect image load failed!\n");
390
+ return 1;
391
+ }
392
+ printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
393
+ cv::Mat input_img;
394
+ double scale = img_process(frame, input_img, 640);
395
+ if (input_img.empty()) {
396
+ printf("detect input_img load failed!\n");
397
+ return 1;
398
+ }
399
+
400
+ float *qnn_seg_data = nullptr;
401
+ float *qnn_trans_data = nullptr;
402
+ float *qnn_mul_data = nullptr;
403
+ float *qnn_canc_data = nullptr;
404
+
405
+ std::vector<float> invoke_time;
406
+ for (int i = 0; i < args.invoke_nums; ++i) {
407
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
408
+ if(result != EXIT_SUCCESS){
409
+ printf("interpreter->set_input_tensor() failed !\n");
410
+ return EXIT_FAILURE;
411
+ }
412
+ // 开始计时
413
+ auto t1 = std::chrono::high_resolution_clock::now();
414
+ result = fast_interpreter->invoke();
415
+ auto t2 = std::chrono::high_resolution_clock::now();
416
+ std::chrono::duration<double> cost_time = t2 - t1;
417
+ invoke_time.push_back(cost_time.count() * 1000);
418
+ if(result != EXIT_SUCCESS){
419
+ printf("interpreter->invoke() failed !\n");
420
+ return EXIT_FAILURE;
421
+ }
422
+ uint32_t out_data_1 = 0;
423
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_canc_data, &out_data_1);
424
+ if(result != EXIT_SUCCESS){
425
+ printf("interpreter->get_output_tensor() 1 failed !\n");
426
+ return EXIT_FAILURE;
427
+ }
428
+
429
+ uint32_t out_data_4 = 0;
430
+ result = fast_interpreter->get_output_tensor(2, (void**)&qnn_trans_data, &out_data_4);
431
+ if(result != EXIT_SUCCESS){
432
+ printf("interpreter->get_output_tensor() 2 failed !\n");
433
+ return EXIT_FAILURE;
434
+ }
435
+
436
+ uint32_t out_data_2 = 0;
437
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_seg_data, &out_data_2);
438
+ if(result != EXIT_SUCCESS){
439
+ printf("interpreter->get_output_tensor() 2 failed !\n");
440
+ return EXIT_FAILURE;
441
+ }
442
+
443
+ uint32_t out_data_80 = 0;
444
+ result = fast_interpreter->get_output_tensor(3, (void**)&qnn_mul_data, &out_data_80);
445
+ if(result != EXIT_SUCCESS){
446
+ printf("interpreter->get_output_tensor() 2 failed !\n");
447
+ return EXIT_FAILURE;
448
+ }
449
+ }
450
+
451
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
452
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
453
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
454
+ float var_invoketime = 0.0f;
455
+ for (auto time : invoke_time) {
456
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
457
+ }
458
+ var_invoketime /= args.invoke_nums;
459
+ printf("=======================================\n");
460
+ 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",
461
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
462
+ printf("=======================================\n");
463
+
464
+ float* pos_data = new float[4 * out_size];
465
+ float* class_data = new float[80 * out_size];
466
+ float* canc_data = new float[32 * out_size];
467
+ transformData(qnn_trans_data, pos_data, 4, out_size);
468
+ transformData(qnn_mul_data, class_data, 80, out_size);
469
+ transformData(qnn_canc_data, canc_data, 32, out_size);
470
+
471
+ // post process
472
+ std::vector<float> qnn_concat;
473
+ concatenate_3(class_data, pos_data, canc_data , 1, out_size, 80, 4, 32, qnn_concat);
474
+ cv::Mat img = post_process(frame, qnn_concat, class_list, scale, qnn_seg_data, qnn_canc_data);
475
+ cv::imwrite("./results.png", img);
476
+ fast_interpreter->destory();
477
+ return 0;
478
+ }
479
+
480
+
481
+ int main(int argc, char* argv[]) {
482
+ Args args = parse_args(argc, argv);
483
+ return invoke(args);
484
+ }
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/models/cutoff_yolov8s-seg_fp16.qnn216.ctx.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0e45c04396d4e658baad5bf5db76fea2ea8e1cb7694bfb17b5a2677cb92af0a0
3
+ size 24361344
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import aidlite
4
+ from utils import eqprocess, xywh2xyxy, NMS, process_mask, masks2segments, draw_detect_res
5
+ import os
6
+ import time
7
+ import argparse
8
+ import onnxruntime
9
+
10
+ # 定义相似度函数
11
+ def get_acc(onnx_out,other_out):
12
+ cosine_similarity=np.dot(np.array(onnx_out),np.array(other_out))/(np.linalg.norm(np.array(onnx_out)) * np.linalg.norm(np.array(other_out)))
13
+ return cosine_similarity
14
+
15
+
16
+ class qnn_predict(object):
17
+ def __init__(self,args) -> None:
18
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
19
+ # aidlite.log_to_stderr()
20
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
21
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
22
+ config = aidlite.Config.create_instance()
23
+ if config is None:
24
+ print("Create model failed !")
25
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
26
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN
27
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
28
+ config.is_quantify_model = 1
29
+
30
+ model = aidlite.Model.create_instance(args.target_model)
31
+ if model is None:
32
+ print("Create model failed !")
33
+
34
+ self.conf = args.conf_thres
35
+ self.iou=args.iou_thres
36
+ self.width = args.width
37
+ self.height = args.height
38
+ self.class_num = args.class_num
39
+ self.input_shape = [[1,self.height,self.width,3]]
40
+ self.blocks = int(self.height * self.width * ( 1 / 64 + 1 / 256 + 1 / 1024))
41
+ self.maskw = int(self.width / 4)
42
+ self.maskh = int(self.height / 4)
43
+ self.output_shape = [[1,32,self.blocks],[1,4,self.blocks],[1,self.class_num,self.blocks],[1,self.maskh, self.maskw,32]]
44
+
45
+ model.set_model_properties(self.input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
46
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
47
+ if self.interpreter is None:
48
+ print("build_interpretper_from_model_and_config failed !")
49
+ result = self.interpreter.init()
50
+ if result != 0:
51
+ print(f"interpreter init failed !")
52
+ result = self.interpreter.load_model()
53
+ if result != 0:
54
+ print("interpreter load model failed !")
55
+ print("detect model load success!")
56
+
57
+ def pretreat_img(self,frame):
58
+ img, scale = eqprocess(frame, self.height, self.width)
59
+ img = img / 255
60
+ img = img.astype(np.float32)
61
+ return img,scale
62
+
63
+ def qnn_run(self, orig_imgs,args):
64
+ input_img_f,scale=self.pretreat_img(orig_imgs) # 图片resize HWC
65
+ input_img = np.expand_dims(input_img_f, 0)
66
+
67
+ invoke_time=[]
68
+ for i in range(args.invoke_nums):
69
+ self.interpreter.set_input_tensor(0, input_img.data)
70
+ t0 = time.time()
71
+ self.interpreter.invoke()
72
+ t1 = time.time()
73
+ cost_time=(t1-t0)*1000
74
+ invoke_time.append(cost_time)
75
+
76
+ input0_data = self.interpreter.get_output_tensor(2).reshape(1,4,self.blocks)
77
+ input1_data = self.interpreter.get_output_tensor(3).reshape(1,self.class_num,self.blocks)
78
+ input2_data = self.interpreter.get_output_tensor(1).reshape(1,32,self.blocks)
79
+ protos = self.interpreter.get_output_tensor(0).reshape(1,self.maskh, self.maskw,32).transpose(0,3,1,2)
80
+
81
+ boxes = np.concatenate([input0_data, input1_data, input2_data], axis = 1)
82
+ x = boxes.transpose(0,2,1)
83
+ x = x[np.amax(x[..., 4:-32], axis=-1) > self.conf]
84
+ if len(x) < 1:
85
+ return None, None
86
+
87
+ x = np.c_[x[..., :4], np.amax(x[..., 4:-32], axis=-1), np.argmax(x[..., 4:-32], axis=-1), x[..., -32:]]
88
+
89
+ x[:, :4] = xywh2xyxy(x[:, :4])
90
+ index = NMS(x[:, :4], x[:, 4], self.iou)
91
+ out_boxes = x[index]
92
+ out_boxes[..., :4] = out_boxes[..., :4] * scale
93
+
94
+ masks = process_mask(protos[0], out_boxes[:, -32:], out_boxes[:, :4], orig_imgs.shape)
95
+ segments = masks2segments(masks)
96
+
97
+ ## time 统计
98
+ max_invoke_time = max(invoke_time)
99
+ min_invoke_time = min(invoke_time)
100
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
101
+ var_invoketime=np.var(invoke_time)
102
+ print("========================================")
103
+ 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}")
104
+ print("========================================")
105
+
106
+ return out_boxes, segments
107
+
108
+
109
+ def parser_args():
110
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
111
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov8s-seg_fp16.qnn216.ctx.bin',help="inference model path")
112
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
113
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
114
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
115
+ parser.add_argument('--width',type=int,default=640,help="Model input size")
116
+ parser.add_argument('--height',type=int,default=640,help="Model input size")
117
+ parser.add_argument('--conf_thres',type=float,default=0.45,help="confidence threshold for filtering the annotations")
118
+ parser.add_argument('--iou_thres',type=float,default=0.45,help="Iou threshold for filtering the annotations")
119
+ parser.add_argument('--class_num',type=int,default=80,help="Iou threshold for filtering the annotations")
120
+ args = parser.parse_args()
121
+ return args
122
+
123
+ def main(args):
124
+ model = qnn_predict(args)
125
+ frame = cv2.imread(args.imgs)
126
+ qnn_out_boxes, qnn_segments = model.qnn_run(frame,args)
127
+ result = draw_detect_res(frame, qnn_out_boxes, qnn_segments)
128
+ cv2.imwrite("./python/bus_result.jpg", result)
129
+
130
+ if __name__ == "__main__":
131
+ args = parser_args()
132
+ main(args)
133
+
134
+
model_farm_yolov8s_seg_qsc8550_qnn2.16_fp16_aidlite/python/utils.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ def draw_detect_res(img, det_pred, segments):
72
+ '''
73
+ 检测结果绘制
74
+ '''
75
+ if det_pred is None:
76
+ return img
77
+
78
+ img = img.astype(np.uint8)
79
+ im_canvas = img.copy()
80
+ color_step = int(255/len(CLASSES))
81
+ for i in range(len(det_pred)):
82
+ x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
83
+ cls_id = int(det_pred[i][5])
84
+ cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
85
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, int(cls_id*color_step), int(255-cls_id*color_step)),thickness = 2)
86
+ if len(segments[i]) > 0:
87
+ cv2.polylines(img, np.int32([segments[i]]), True, (0, int(cls_id*color_step), int(255-cls_id*color_step)), 2)
88
+ cv2.fillPoly(img, np.int32([segments[i]]), (0, int(cls_id*color_step), int(255-cls_id*color_step)))
89
+ img = cv2.addWeighted(im_canvas, 0.3, img, 0.7, 0)
90
+ return img
91
+
92
+ def scale_mask(masks, im0_shape):
93
+ masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
94
+ interpolation=cv2.INTER_LINEAR)
95
+ if len(masks.shape) == 2:
96
+ masks = masks[:, :, None]
97
+ return masks
98
+
99
+ def crop_mask(masks, boxes):
100
+ n, h, w = masks.shape
101
+ x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
102
+ r = np.arange(w, dtype=x1.dtype)[None, None, :]
103
+ c = np.arange(h, dtype=x1.dtype)[None, :, None]
104
+ return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))
105
+
106
+ def process_mask(protos, masks_in, bboxes, im0_shape):
107
+ c, mh, mw = protos.shape
108
+ masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0) # HWN
109
+ masks = np.ascontiguousarray(masks)
110
+ masks = scale_mask(masks, im0_shape) # re-scale mask from P3 shape to original input image shape
111
+ masks = np.einsum('HWN -> NHW', masks) # HWN -> NHW
112
+ masks = crop_mask(masks, bboxes)
113
+ return np.greater(masks, 0.5)
114
+
115
+ def masks2segments(masks):
116
+ segments = []
117
+ for x in masks.astype('uint8'):
118
+ c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] # CHAIN_APPROX_SIMPLE
119
+ if c:
120
+ c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
121
+ else:
122
+ c = np.zeros((0, 2)) # no segments found
123
+ segments.append(c.astype('float32'))
124
+ return segments
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/README.md ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ## Source model
3
+ - Input shape: 640x640
4
+ - Number of parameters: 11.27M
5
+ - Model size: 45.22M
6
+ - Output shape: 1x32x160x160, 1x116x8400
7
+
8
+ Source model repository: [yolov8](https://github.com/ultralytics/ultralytics)
9
+
10
+ ### Converted model
11
+
12
+ - Precision: W8A16
13
+ - Backend: QNN2.16
14
+ - Target Device: SNM972 QCS8550
15
+
16
+ ## Inference with AidLite SDK
17
+
18
+ ### SDK installation
19
+ 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/)
20
+
21
+ - Install AidLite SDK
22
+
23
+ ```bash
24
+ # Install the appropriate version of the aidlite sdk
25
+ sudo aid-pkg update
26
+ sudo aid-pkg install aidlite-sdk
27
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
28
+ sudo aid-pkg install aidlite-{QNN VERSION}
29
+ ```
30
+
31
+ - Verify AidLite SDK
32
+
33
+ ```bash
34
+ # aidlite sdk c++ check
35
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
36
+
37
+ # aidlite sdk python check
38
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
39
+ ```
40
+
41
+ ### Run demo
42
+ #### python
43
+ ```bash
44
+ cd yolov8s_seg/model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite
45
+ python3 ./python/run_test.py --target_model ./models/cutoff_yolov8s-seg_w8a16.qnn216.ctx.bin --imgs ./python/bus.jpg --invoke_nums 10
46
+ ```
47
+
48
+ #### cpp
49
+ ```bash
50
+ cd yolov8s_seg/model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp
51
+ mkdir build && cd build
52
+ cmake ..
53
+ make
54
+ ./run_test
55
+ ```
56
+
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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}/run_test.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ pthread
31
+ )
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/cpp/run_test.cpp ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <cstring> // 用于 memcpy
6
+ #include <opencv2/opencv.hpp>
7
+ #include <aidlux/aidlite/aidlite.hpp>
8
+ #include <vector>
9
+ #include <numeric>
10
+
11
+ const float INPUT_WIDTH = 640.0;
12
+ const float INPUT_HEIGHT = 640.0;
13
+ const float SCORE_THRESHOLD = 0.25;
14
+ const float NMS_THRESHOLD = 0.45;
15
+ const float CONFIDENCE_THRESHOLD = 0.25;
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 cv;
40
+ using namespace std;
41
+ using namespace Aidlux::Aidlite;
42
+
43
+ struct Args {
44
+ std::string target_model = "../../models/cutoff_yolov8s-seg_w8a16.qnn216.ctx.bin";
45
+ std::string imgs = "../bus.jpg";
46
+ int invoke_nums = 10;
47
+ std::string model_type = "QNN";
48
+ };
49
+
50
+ Args parse_args(int argc, char* argv[]) {
51
+ Args args;
52
+ for (int i = 1; i < argc; ++i) {
53
+ std::string arg = argv[i];
54
+ if (arg == "--target_model" && i + 1 < argc) {
55
+ args.target_model = argv[++i];
56
+ } else if (arg == "--imgs" && i + 1 < argc) {
57
+ args.imgs = argv[++i];
58
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
59
+ args.invoke_nums = std::stoi(argv[++i]);
60
+ } else if (arg == "--model_type" && i + 1 < argc) {
61
+ args.model_type = argv[++i];
62
+ }
63
+ }
64
+ return args;
65
+ }
66
+
67
+ std::string to_lower(const std::string& str) {
68
+ std::string lower_str = str;
69
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
70
+ return std::tolower(c);
71
+ });
72
+ return lower_str;
73
+ }
74
+
75
+ // concatenate_3(80_class_data, 4_pos_data , 32_canc_data, 1, 8400, 80, 4,32, qnn_concat);
76
+ void concatenate_3(float* qnn_trans_data, float* qnn_mul_data, float* qnn_canc_data, int batch, int num_elements, int trans_dim, int mul_dim, int canc_dim,std::vector<float>& output) {
77
+ // int out_dim = trans_dim + mul_dim + canc_dim + 1; //117
78
+ int out_dim = trans_dim + mul_dim + canc_dim; //116
79
+ output.resize(batch * num_elements * out_dim);
80
+ for (int i = 0; i < batch * num_elements; ++i) {
81
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
82
+ std::memcpy(&output[i * out_dim + mul_dim], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
83
+ std::memcpy(&output[i * out_dim + mul_dim + trans_dim], &qnn_canc_data[i * canc_dim], canc_dim * sizeof(float));
84
+ }
85
+ }
86
+
87
+ // 4*8400
88
+ void transformData(const float* input, float* output, int C, int N) {
89
+ for (int c = 0; c < C; ++c) {
90
+ for (int n = 0; n < N; ++n) {
91
+ output[n * C + c] = input[c * N + n];
92
+ }
93
+ }
94
+ }
95
+
96
+ double img_process(cv::Mat frame, cv::Mat &img_input, int size) {
97
+ cv::Mat img_processed = frame.clone();
98
+ int height = img_processed.rows;
99
+ int width = img_processed.cols;
100
+ int length = std::max(height, width);
101
+ double scala = static_cast<double>(length) / size;
102
+
103
+ cv::Mat image = cv::Mat::zeros(cv::Size(length, length), CV_8UC3);
104
+ img_processed.copyTo(image(cv::Rect(0, 0, width, height)));
105
+
106
+ cv::cvtColor(image, img_input, cv::COLOR_BGR2RGB);
107
+ cv::resize(img_input, img_input, cv::Size(size, size));
108
+
109
+ cv::Mat mean_data = cv::Mat::zeros(img_input.size(), CV_32FC3);
110
+ cv::Mat std_data(img_input.size(), CV_32FC3, cv::Scalar(255, 255, 255));
111
+ img_input.convertTo(img_input, CV_32FC3);
112
+ img_input = (img_input - mean_data) / std_data;
113
+ return scala;
114
+ }
115
+
116
+
117
+ cv::Scalar generate_colors(int i, bool bgr = false) {
118
+ static const std::vector<std::string> hex_colors = {
119
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
120
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
121
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
122
+ "FF95C8", "FF37C7"
123
+ };
124
+
125
+ int num = hex_colors.size();
126
+ std::string hex = hex_colors[i % num];
127
+
128
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
129
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
130
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
131
+
132
+ if (bgr)
133
+ return cv::Scalar(b, g, r);
134
+ else
135
+ return cv::Scalar(r, g, b);
136
+ }
137
+
138
+ float sigmoid_function(float a)
139
+ {
140
+ float b = 1. / (1. + exp(-a));
141
+ return b;
142
+ }
143
+
144
+ int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
145
+
146
+ int current_coordinate[4] = {0, 0, 0, 0};
147
+ for(int a = 0; a < src_dims[0]; ++a){
148
+ current_coordinate[0] = a;
149
+ for(int b = 0; b < src_dims[1]; ++b){
150
+ current_coordinate[1] = b;
151
+ for(int c = 0; c < src_dims[2]; ++c){
152
+ current_coordinate[2] = c;
153
+ for(int d = 0; d < src_dims[3]; ++d){
154
+ current_coordinate[3] = d;
155
+
156
+ int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
157
+ current_coordinate[1]*src_dims[2]*src_dims[3] +
158
+ current_coordinate[2]*src_dims[3] +
159
+ current_coordinate[3];
160
+
161
+ int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
162
+ current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
163
+ current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
164
+ current_coordinate[tsp_dims[3]];
165
+
166
+ dest[new_index] = src[old_index];
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ return EXIT_SUCCESS;
173
+ }
174
+
175
+
176
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
177
+ {
178
+ int baseLine;
179
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
180
+ int y = top - label_size.height - baseLine;
181
+ if (y < 0) {
182
+ y = top ;
183
+ }
184
+ cv::Point tlc(left, y);
185
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
186
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
187
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
188
+ }
189
+
190
+
191
+ cv::Mat post_process(cv::Mat &frame, std::vector<float> &outputs, const std::vector<std::string> &class_name,
192
+ const double ratio, float* protos_data, float* qnn_canc)
193
+ {
194
+ cv::Mat input_image = frame.clone();
195
+ // Initialize vectors to hold respective outputs while unwrapping detections.
196
+ std::vector<int> class_ids;
197
+ std::vector<float> confidences;
198
+ std::vector<cv::Rect> boxes;
199
+ std::vector<cv::Mat> masks;
200
+ std::vector<float> class_scores;
201
+ cv::RNG rng;
202
+ cv::Mat masked_img;
203
+
204
+ unsigned int src_dims[4] = {1, 32,160,160};
205
+ unsigned int tsp_dims[4] = {0,3,1,2};
206
+ unsigned int stride_data_num = 1*32*160*160;
207
+ float* format_data = new float[stride_data_num];
208
+ transpose(protos_data, src_dims, tsp_dims, format_data);
209
+ cv::Mat proto_buffer(32, 160*160, CV_32F, format_data);
210
+ std::cout << "proto_buffer 维度: " << proto_buffer.rows << "x" << proto_buffer.cols << std::endl;
211
+
212
+ for (int i = 0; i < outputs.size(); i+=116)
213
+ {
214
+ auto start = outputs.begin() + i + 4;
215
+ auto end = outputs.begin() + i + 84;
216
+ float max_val = *std::max_element(start, end);
217
+ float confidence = max_val;
218
+ if (confidence >= CONFIDENCE_THRESHOLD)
219
+ {
220
+ auto start = outputs.begin() + i + 4;
221
+ auto end = outputs.begin() + i + 84;
222
+ std::vector<float> middle_data;
223
+ middle_data.assign(start, end);
224
+ // Create a 1x80 Mat and store class scores of 80 classes.
225
+ cv::Mat scores(1, class_name.size(), CV_32FC1, middle_data.data());
226
+ cv::Point class_id;
227
+ double max_class_score;
228
+
229
+ // For multi-label, check each class score
230
+ for (int c = 0; c < class_name.size(); c++) {
231
+ float class_score = scores.at<float>(0, c);
232
+ // If class score is above threshold, consider this class for the box
233
+ if (class_score > SCORE_THRESHOLD) {
234
+ std::vector<float> last32_data;
235
+ auto st_32= outputs.begin() + i + 84;
236
+ auto ed_32 = outputs.begin() + i + 116;
237
+ last32_data.assign(st_32, ed_32);
238
+ cv::Mat mask(1, 32, CV_32FC1, last32_data.data());
239
+ // Store class ID and confidence in the pre-defined respective vectors.
240
+ confidences.push_back(confidence * class_score); // Multiply with confidence
241
+ class_ids.push_back(c); // class index
242
+ // Center and box dimension.
243
+ float cx = outputs[i];
244
+ float cy = outputs[i+1];
245
+ float w = outputs[i+2];
246
+ float h = outputs[i+3];
247
+
248
+ int left = int((cx - 0.5 * w) * ratio);
249
+ int top = int((cy - 0.48 * h) * ratio);
250
+ int width = int(w * ratio);
251
+ int height = int(h * ratio);
252
+
253
+ // Store good detections in the boxes vector.
254
+ boxes.push_back(cv::Rect(left, top, width, height));
255
+ masks.push_back(mask);
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ std::cout << "boxes.size(): " << boxes.size() << ",confidences.size():" << confidences.size() << std::endl;
262
+
263
+ // Perform Non Maximum Suppression and draw predictions.
264
+ std::vector<int> indices;
265
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
266
+ printf("Detected {%ld} targets.\n", indices.size());
267
+ cv::Mat rgb_mask = cv::Mat::zeros(input_image.size(), input_image.type());
268
+
269
+ // Loop over NMS results and draw bounding boxes
270
+ for (int i = 0; i < indices.size(); i++)
271
+ {
272
+ int idx = indices[i];
273
+ cv::Rect box = boxes[idx];
274
+ cv::Scalar color = generate_colors(class_ids[idx]);
275
+
276
+ int x1 = std::max(0, box.x);
277
+ int y1 = std::max(0, box.y);
278
+ int x2 = std::max(0, box.br().x);
279
+ int y2 = std::max(0, box.br().y);
280
+ cv::Mat ms = masks[idx];
281
+ // 维度验证
282
+ if (ms.cols != proto_buffer.rows) {
283
+ cerr << "维度不匹配: mask.cols=" << ms.cols
284
+ << ", proto_buffer.rows=" << proto_buffer.rows << endl;
285
+ continue;
286
+ }
287
+ cv::Mat m = ms * proto_buffer;
288
+ for (int col = 0; col < m.cols; col++) {
289
+ m.at<float>(0, col) = sigmoid_function(m.at<float>(0, col));
290
+ }
291
+ cv::Mat m1 = m.reshape(1, 160); // 1x25600 -> 160x160
292
+
293
+ float ratio2 = 160.0/640.0;
294
+ int mx1 = std::max(0, int((x1 * ratio2)));
295
+ int mx2 = std::max(0, int((x2 * ratio2)));
296
+ int my1 = std::max(0, int((y1 * ratio2)));
297
+ int my2 = std::max(0, int((y2 * ratio2)));
298
+ cv::Mat mask_roi = m1(cv::Range(my1, my2), cv::Range(mx1, mx2));
299
+ cv::Mat rm, det_mask;
300
+ cv::resize(mask_roi, rm, cv::Size(x2 - x1, y2 - y1));
301
+ for (int r = 0; r < rm.rows; r++) {
302
+ for (int c = 0; c < rm.cols; c++) {
303
+ float pv = rm.at<float>(r, c);
304
+ if (pv > 0.5) {
305
+ rm.at<float>(r, c) = 1.0;
306
+ }
307
+ else {
308
+ rm.at<float>(r, c) = 0.0;
309
+ }
310
+ }
311
+ }
312
+ rm = rm * rng.uniform(0, 255);
313
+ rm.convertTo(det_mask, CV_8UC1);
314
+ if ((y1 + det_mask.rows) >= input_image.rows) {
315
+ y2 = input_image.rows - 1;
316
+ }
317
+ if ((x1 + det_mask.cols) >= input_image.cols) {
318
+ x2 = input_image.cols - 1;
319
+ }
320
+
321
+ cv::Mat mask = cv::Mat::zeros(cv::Size(input_image.cols, input_image.rows), CV_8UC1);
322
+ det_mask(cv::Range(0, y2 - y1), cv::Range(0, x2 - x1)).copyTo(mask(cv::Range(y1, y2), cv::Range(x1, x2)));
323
+ add(rgb_mask, cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), rgb_mask, mask);
324
+ if (input_image.size() != rgb_mask.size()) {
325
+ cv::resize(rgb_mask, rgb_mask, input_image.size());
326
+ }
327
+
328
+ cv::rectangle(input_image, boxes[idx], color, 2, 8);
329
+ std::string label = cv::format("%.2f", confidences[idx]);
330
+ label = class_name[class_ids[idx]] + ":" + label;
331
+ cv::putText(input_image, label, cv::Point(boxes[idx].tl().x, boxes[idx].tl().y - 10), cv::FONT_HERSHEY_SIMPLEX, .5, color);
332
+ cv::addWeighted(input_image, 0.5, rgb_mask, 0.5, 0, masked_img);
333
+
334
+ }
335
+ printf("Processing finished.\n");
336
+ return masked_img;
337
+ }
338
+
339
+
340
+
341
+ int invoke(const Args& args) {
342
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
343
+ << "Image Path: " << args.imgs << "\n"
344
+ << "Inference Nums: " << args.invoke_nums << "\n"
345
+ << "Model Type: " << args.model_type << "\n";
346
+ Model* model = Model::create_instance(args.target_model);
347
+ if(model == nullptr){
348
+ printf("Create model failed !\n");
349
+ return EXIT_FAILURE;
350
+ }
351
+ Config* config = Config::create_instance();
352
+ if(config == nullptr){
353
+ printf("Create config failed !\n");
354
+ return EXIT_FAILURE;
355
+ }
356
+ config->implement_type = ImplementType::TYPE_LOCAL;
357
+ std::string model_type_lower = to_lower(args.model_type);
358
+ if (model_type_lower == "qnn"){
359
+ config->framework_type = FrameworkType::TYPE_QNN216;
360
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
361
+ config->framework_type = FrameworkType::TYPE_SNPE2;
362
+ }
363
+ config->accelerate_type = AccelerateType::TYPE_DSP;
364
+ config->is_quantify_model = 1;
365
+
366
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, 640, 640, 3}};
367
+ std::vector<std::vector<uint32_t>> output_shapes = {{1,32,8400},{1,4,8400},{1,80,8400},{1,160, 160,32}};
368
+ model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
369
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
370
+ if(fast_interpreter == nullptr){
371
+ printf("build_interpretper_from_model_and_config failed !\n");
372
+ return EXIT_FAILURE;
373
+ }
374
+ int result = fast_interpreter->init();
375
+ if(result != EXIT_SUCCESS){
376
+ printf("interpreter->init() failed !\n");
377
+ return EXIT_FAILURE;
378
+ }
379
+ // load model
380
+ fast_interpreter->load_model();
381
+ if(result != EXIT_SUCCESS){
382
+ printf("interpreter->load_model() failed !\n");
383
+ return EXIT_FAILURE;
384
+ }
385
+ printf("detect model load success!\n");
386
+
387
+ cv::Mat frame = cv::imread(args.imgs);
388
+ if (frame.empty()) {
389
+ printf("detect image load failed!\n");
390
+ return 1;
391
+ }
392
+ printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
393
+ cv::Mat input_img;
394
+ double scale = img_process(frame, input_img, 640);
395
+ if (input_img.empty()) {
396
+ printf("detect input_img load failed!\n");
397
+ return 1;
398
+ }
399
+
400
+ float *qnn_seg_data = nullptr;
401
+ float *qnn_trans_data = nullptr;
402
+ float *qnn_mul_data = nullptr;
403
+ float *qnn_canc_data = nullptr;
404
+
405
+ std::vector<float> invoke_time;
406
+ for (int i = 0; i < args.invoke_nums; ++i) {
407
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
408
+ if(result != EXIT_SUCCESS){
409
+ printf("interpreter->set_input_tensor() failed !\n");
410
+ return EXIT_FAILURE;
411
+ }
412
+ // 开始计时
413
+ auto t1 = std::chrono::high_resolution_clock::now();
414
+ result = fast_interpreter->invoke();
415
+ auto t2 = std::chrono::high_resolution_clock::now();
416
+ std::chrono::duration<double> cost_time = t2 - t1;
417
+ invoke_time.push_back(cost_time.count() * 1000);
418
+ if(result != EXIT_SUCCESS){
419
+ printf("interpreter->invoke() failed !\n");
420
+ return EXIT_FAILURE;
421
+ }
422
+ uint32_t out_data_1 = 0;
423
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_canc_data, &out_data_1);
424
+ if(result != EXIT_SUCCESS){
425
+ printf("interpreter->get_output_tensor() 1 failed !\n");
426
+ return EXIT_FAILURE;
427
+ }
428
+
429
+ uint32_t out_data_4 = 0;
430
+ result = fast_interpreter->get_output_tensor(2, (void**)&qnn_trans_data, &out_data_4);
431
+ if(result != EXIT_SUCCESS){
432
+ printf("interpreter->get_output_tensor() 2 failed !\n");
433
+ return EXIT_FAILURE;
434
+ }
435
+
436
+ uint32_t out_data_2 = 0;
437
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_seg_data, &out_data_2);
438
+ if(result != EXIT_SUCCESS){
439
+ printf("interpreter->get_output_tensor() 2 failed !\n");
440
+ return EXIT_FAILURE;
441
+ }
442
+
443
+ uint32_t out_data_80 = 0;
444
+ result = fast_interpreter->get_output_tensor(3, (void**)&qnn_mul_data, &out_data_80);
445
+ if(result != EXIT_SUCCESS){
446
+ printf("interpreter->get_output_tensor() 2 failed !\n");
447
+ return EXIT_FAILURE;
448
+ }
449
+ }
450
+
451
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
452
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
453
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
454
+ float var_invoketime = 0.0f;
455
+ for (auto time : invoke_time) {
456
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
457
+ }
458
+ var_invoketime /= args.invoke_nums;
459
+ printf("=======================================\n");
460
+ 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",
461
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
462
+ printf("=======================================\n");
463
+
464
+ float* pos_data = new float[4 * out_size];
465
+ float* class_data = new float[80 * out_size];
466
+ float* canc_data = new float[32 * out_size];
467
+ transformData(qnn_trans_data, pos_data, 4, out_size);
468
+ transformData(qnn_mul_data, class_data, 80, out_size);
469
+ transformData(qnn_canc_data, canc_data, 32, out_size);
470
+
471
+ // post process
472
+ std::vector<float> qnn_concat;
473
+ concatenate_3(class_data, pos_data, canc_data , 1, out_size, 80, 4, 32, qnn_concat);
474
+ cv::Mat img = post_process(frame, qnn_concat, class_list, scale, qnn_seg_data, qnn_canc_data);
475
+ cv::imwrite("./results.png", img);
476
+ fast_interpreter->destory();
477
+ return 0;
478
+ }
479
+
480
+
481
+ int main(int argc, char* argv[]) {
482
+ Args args = parse_args(argc, argv);
483
+ return invoke(args);
484
+ }
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/models/cutoff_yolov8s-seg_w8a16.qnn216.ctx.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a91723cbfce181aa057abc23ff0884dc8bb9d81a1acad745a62b6d9d22c7b9ab
3
+ size 12765624
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/python/run_test.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import aidlite
4
+ from utils import eqprocess, xywh2xyxy, NMS, process_mask, masks2segments, draw_detect_res
5
+ import os
6
+ import time
7
+ import argparse
8
+ import onnxruntime
9
+
10
+ # 定义相似度函数
11
+ def get_acc(onnx_out,other_out):
12
+ cosine_similarity=np.dot(np.array(onnx_out),np.array(other_out))/(np.linalg.norm(np.array(onnx_out)) * np.linalg.norm(np.array(other_out)))
13
+ return cosine_similarity
14
+
15
+
16
+ class qnn_predict(object):
17
+ def __init__(self,args) -> None:
18
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
19
+ # aidlite.log_to_stderr()
20
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
21
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
22
+ config = aidlite.Config.create_instance()
23
+ if config is None:
24
+ print("Create model failed !")
25
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
26
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN
27
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
28
+ config.is_quantify_model = 1
29
+
30
+ model = aidlite.Model.create_instance(args.target_model)
31
+ if model is None:
32
+ print("Create model failed !")
33
+
34
+ self.conf = args.conf_thres
35
+ self.iou=args.iou_thres
36
+ self.width = args.width
37
+ self.height = args.height
38
+ self.class_num = args.class_num
39
+ self.input_shape = [[1,self.height,self.width,3]]
40
+ self.blocks = int(self.height * self.width * ( 1 / 64 + 1 / 256 + 1 / 1024))
41
+ self.maskw = int(self.width / 4)
42
+ self.maskh = int(self.height / 4)
43
+ self.output_shape = [[1,32,self.blocks],[1,4,self.blocks],[1,self.class_num,self.blocks],[1,self.maskh, self.maskw,32]]
44
+
45
+ model.set_model_properties(self.input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
46
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
47
+ if self.interpreter is None:
48
+ print("build_interpretper_from_model_and_config failed !")
49
+ result = self.interpreter.init()
50
+ if result != 0:
51
+ print(f"interpreter init failed !")
52
+ result = self.interpreter.load_model()
53
+ if result != 0:
54
+ print("interpreter load model failed !")
55
+ print("detect model load success!")
56
+
57
+ def pretreat_img(self,frame):
58
+ img, scale = eqprocess(frame, self.height, self.width)
59
+ img = img / 255
60
+ img = img.astype(np.float32)
61
+ return img,scale
62
+
63
+ def qnn_run(self, orig_imgs,args):
64
+ input_img_f,scale=self.pretreat_img(orig_imgs) # 图片resize HWC
65
+ input_img = np.expand_dims(input_img_f, 0)
66
+
67
+ invoke_time=[]
68
+ for i in range(args.invoke_nums):
69
+ self.interpreter.set_input_tensor(0, input_img.data)
70
+ t0 = time.time()
71
+ self.interpreter.invoke()
72
+ t1 = time.time()
73
+ cost_time=(t1-t0)*1000
74
+ invoke_time.append(cost_time)
75
+
76
+ input0_data = self.interpreter.get_output_tensor(2).reshape(1,4,self.blocks)
77
+ input1_data = self.interpreter.get_output_tensor(3).reshape(1,self.class_num,self.blocks)
78
+ input2_data = self.interpreter.get_output_tensor(1).reshape(1,32,self.blocks)
79
+ protos = self.interpreter.get_output_tensor(0).reshape(1,self.maskh, self.maskw,32).transpose(0,3,1,2)
80
+
81
+ boxes = np.concatenate([input0_data, input1_data, input2_data], axis = 1)
82
+ x = boxes.transpose(0,2,1)
83
+ x = x[np.amax(x[..., 4:-32], axis=-1) > self.conf]
84
+ if len(x) < 1:
85
+ return None, None
86
+
87
+ x = np.c_[x[..., :4], np.amax(x[..., 4:-32], axis=-1), np.argmax(x[..., 4:-32], axis=-1), x[..., -32:]]
88
+
89
+ x[:, :4] = xywh2xyxy(x[:, :4])
90
+ index = NMS(x[:, :4], x[:, 4], self.iou)
91
+ out_boxes = x[index]
92
+ out_boxes[..., :4] = out_boxes[..., :4] * scale
93
+
94
+ masks = process_mask(protos[0], out_boxes[:, -32:], out_boxes[:, :4], orig_imgs.shape)
95
+ segments = masks2segments(masks)
96
+
97
+ ## time 统计
98
+ max_invoke_time = max(invoke_time)
99
+ min_invoke_time = min(invoke_time)
100
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
101
+ var_invoketime=np.var(invoke_time)
102
+ print("========================================")
103
+ 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}")
104
+ print("========================================")
105
+
106
+ return out_boxes, segments
107
+
108
+
109
+ def parser_args():
110
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
111
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov8s-seg_w8a16.qnn216.ctx.bin',help="inference model path")
112
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
113
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
114
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
115
+ parser.add_argument('--width',type=int,default=640,help="Model input size")
116
+ parser.add_argument('--height',type=int,default=640,help="Model input size")
117
+ parser.add_argument('--conf_thres',type=float,default=0.45,help="confidence threshold for filtering the annotations")
118
+ parser.add_argument('--iou_thres',type=float,default=0.45,help="Iou threshold for filtering the annotations")
119
+ parser.add_argument('--class_num',type=int,default=80,help="Iou threshold for filtering the annotations")
120
+ args = parser.parse_args()
121
+ return args
122
+
123
+ def main(args):
124
+ model = qnn_predict(args)
125
+ frame = cv2.imread(args.imgs)
126
+ qnn_out_boxes, qnn_segments = model.qnn_run(frame,args)
127
+ result = draw_detect_res(frame, qnn_out_boxes, qnn_segments)
128
+ cv2.imwrite("./python/bus_result.jpg", result)
129
+
130
+ if __name__ == "__main__":
131
+ args = parser_args()
132
+ main(args)
133
+
134
+
model_farm_yolov8s_seg_qsc8550_qnn2.16_int16_aidlite/python/utils.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ def draw_detect_res(img, det_pred, segments):
72
+ '''
73
+ 检测结果绘制
74
+ '''
75
+ if det_pred is None:
76
+ return img
77
+
78
+ img = img.astype(np.uint8)
79
+ im_canvas = img.copy()
80
+ color_step = int(255/len(CLASSES))
81
+ for i in range(len(det_pred)):
82
+ x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
83
+ cls_id = int(det_pred[i][5])
84
+ cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
85
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, int(cls_id*color_step), int(255-cls_id*color_step)),thickness = 2)
86
+ if len(segments[i]) > 0:
87
+ cv2.polylines(img, np.int32([segments[i]]), True, (0, int(cls_id*color_step), int(255-cls_id*color_step)), 2)
88
+ cv2.fillPoly(img, np.int32([segments[i]]), (0, int(cls_id*color_step), int(255-cls_id*color_step)))
89
+ img = cv2.addWeighted(im_canvas, 0.3, img, 0.7, 0)
90
+ return img
91
+
92
+ def scale_mask(masks, im0_shape):
93
+ masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
94
+ interpolation=cv2.INTER_LINEAR)
95
+ if len(masks.shape) == 2:
96
+ masks = masks[:, :, None]
97
+ return masks
98
+
99
+ def crop_mask(masks, boxes):
100
+ n, h, w = masks.shape
101
+ x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
102
+ r = np.arange(w, dtype=x1.dtype)[None, None, :]
103
+ c = np.arange(h, dtype=x1.dtype)[None, :, None]
104
+ return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))
105
+
106
+ def process_mask(protos, masks_in, bboxes, im0_shape):
107
+ c, mh, mw = protos.shape
108
+ masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0) # HWN
109
+ masks = np.ascontiguousarray(masks)
110
+ masks = scale_mask(masks, im0_shape) # re-scale mask from P3 shape to original input image shape
111
+ masks = np.einsum('HWN -> NHW', masks) # HWN -> NHW
112
+ masks = crop_mask(masks, bboxes)
113
+ return np.greater(masks, 0.5)
114
+
115
+ def masks2segments(masks):
116
+ segments = []
117
+ for x in masks.astype('uint8'):
118
+ c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] # CHAIN_APPROX_SIMPLE
119
+ if c:
120
+ c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
121
+ else:
122
+ c = np.zeros((0, 2)) # no segments found
123
+ segments.append(c.astype('float32'))
124
+ return segments
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/README.md ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Model Information
2
+ ## Source model
3
+ - Input shape: 640x640
4
+ - Number of parameters: 11.27M
5
+ - Model size: 45.22M
6
+ - Output shape: 1x32x160x160, 1x116x8400
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
+ ## Inference with AidLite SDK
17
+
18
+ ### SDK installation
19
+ 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/)
20
+
21
+ - Install AidLite SDK
22
+
23
+ ```bash
24
+ # Install the appropriate version of the aidlite sdk
25
+ sudo aid-pkg update
26
+ sudo aid-pkg install aidlite-sdk
27
+ # Download the qnn version that matches the above backend. Eg Install QNN2.23 Aidlite: sudo aid-pkg install aidlite-qnn223
28
+ sudo aid-pkg install aidlite-{QNN VERSION}
29
+ ```
30
+
31
+ - Verify AidLite SDK
32
+
33
+ ```bash
34
+ # aidlite sdk c++ check
35
+ python3 -c "import aidlite ; print(aidlite.get_library_version())"
36
+
37
+ # aidlite sdk python check
38
+ python3 -c "import aidlite ; print(aidlite.get_py_library_version())"
39
+ ```
40
+
41
+ ### Run demo
42
+ #### python
43
+ ```bash
44
+ cd yolov8s_seg/model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite
45
+ python3 ./python/run_test.py --target_model ./models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin --imgs ./python/bus.jpg --invoke_nums 10
46
+ ```
47
+
48
+ #### cpp
49
+ ```bash
50
+ cd yolov8s_seg/model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp
51
+ mkdir build && cd build
52
+ cmake ..
53
+ make
54
+ ./run_test
55
+ ```
56
+
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp/CMakeLists.txt ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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}/run_test.cpp
23
+ )
24
+
25
+ add_executable(run_test ${SRC_LISTS})
26
+
27
+ target_link_libraries(run_test
28
+ aidlite
29
+ ${OpenCV_LIBS}
30
+ pthread
31
+ )
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/cpp/run_test.cpp ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iostream>
2
+ #include <string>
3
+ #include <algorithm>
4
+ #include <cctype>
5
+ #include <cstring> // 用于 memcpy
6
+ #include <opencv2/opencv.hpp>
7
+ #include <aidlux/aidlite/aidlite.hpp>
8
+ #include <vector>
9
+ #include <numeric>
10
+
11
+ const float INPUT_WIDTH = 640.0;
12
+ const float INPUT_HEIGHT = 640.0;
13
+ const float SCORE_THRESHOLD = 0.25;
14
+ const float NMS_THRESHOLD = 0.45;
15
+ const float CONFIDENCE_THRESHOLD = 0.25;
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 cv;
40
+ using namespace std;
41
+ using namespace Aidlux::Aidlite;
42
+
43
+ struct Args {
44
+ std::string target_model = "../../models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin";
45
+ std::string imgs = "../bus.jpg";
46
+ int invoke_nums = 10;
47
+ std::string model_type = "QNN";
48
+ };
49
+
50
+ Args parse_args(int argc, char* argv[]) {
51
+ Args args;
52
+ for (int i = 1; i < argc; ++i) {
53
+ std::string arg = argv[i];
54
+ if (arg == "--target_model" && i + 1 < argc) {
55
+ args.target_model = argv[++i];
56
+ } else if (arg == "--imgs" && i + 1 < argc) {
57
+ args.imgs = argv[++i];
58
+ } else if (arg == "--invoke_nums" && i + 1 < argc) {
59
+ args.invoke_nums = std::stoi(argv[++i]);
60
+ } else if (arg == "--model_type" && i + 1 < argc) {
61
+ args.model_type = argv[++i];
62
+ }
63
+ }
64
+ return args;
65
+ }
66
+
67
+ std::string to_lower(const std::string& str) {
68
+ std::string lower_str = str;
69
+ std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(), [](unsigned char c) {
70
+ return std::tolower(c);
71
+ });
72
+ return lower_str;
73
+ }
74
+
75
+ // concatenate_3(80_class_data, 4_pos_data , 32_canc_data, 1, 8400, 80, 4,32, qnn_concat);
76
+ void concatenate_3(float* qnn_trans_data, float* qnn_mul_data, float* qnn_canc_data, int batch, int num_elements, int trans_dim, int mul_dim, int canc_dim,std::vector<float>& output) {
77
+ // int out_dim = trans_dim + mul_dim + canc_dim + 1; //117
78
+ int out_dim = trans_dim + mul_dim + canc_dim; //116
79
+ output.resize(batch * num_elements * out_dim);
80
+ for (int i = 0; i < batch * num_elements; ++i) {
81
+ std::memcpy(&output[i * out_dim], &qnn_mul_data[i * mul_dim], mul_dim * sizeof(float));
82
+ std::memcpy(&output[i * out_dim + mul_dim], &qnn_trans_data[i * trans_dim], trans_dim * sizeof(float));
83
+ std::memcpy(&output[i * out_dim + mul_dim + trans_dim], &qnn_canc_data[i * canc_dim], canc_dim * sizeof(float));
84
+ }
85
+ }
86
+
87
+ // 4*8400
88
+ void transformData(const float* input, float* output, int C, int N) {
89
+ for (int c = 0; c < C; ++c) {
90
+ for (int n = 0; n < N; ++n) {
91
+ output[n * C + c] = input[c * N + n];
92
+ }
93
+ }
94
+ }
95
+
96
+ double img_process(cv::Mat frame, cv::Mat &img_input, int size) {
97
+ cv::Mat img_processed = frame.clone();
98
+ int height = img_processed.rows;
99
+ int width = img_processed.cols;
100
+ int length = std::max(height, width);
101
+ double scala = static_cast<double>(length) / size;
102
+
103
+ cv::Mat image = cv::Mat::zeros(cv::Size(length, length), CV_8UC3);
104
+ img_processed.copyTo(image(cv::Rect(0, 0, width, height)));
105
+
106
+ cv::cvtColor(image, img_input, cv::COLOR_BGR2RGB);
107
+ cv::resize(img_input, img_input, cv::Size(size, size));
108
+
109
+ cv::Mat mean_data = cv::Mat::zeros(img_input.size(), CV_32FC3);
110
+ cv::Mat std_data(img_input.size(), CV_32FC3, cv::Scalar(255, 255, 255));
111
+ img_input.convertTo(img_input, CV_32FC3);
112
+ img_input = (img_input - mean_data) / std_data;
113
+ return scala;
114
+ }
115
+
116
+
117
+ cv::Scalar generate_colors(int i, bool bgr = false) {
118
+ static const std::vector<std::string> hex_colors = {
119
+ "FF3838", "FF9D97", "FF701F", "FFB21D", "CFD231", "48F90A",
120
+ "92CC17", "3DDB86", "1A9334", "00D4BB", "2C99A8", "00C2FF",
121
+ "344593", "6473FF", "0018EC", "8438FF", "520085", "CB38FF",
122
+ "FF95C8", "FF37C7"
123
+ };
124
+
125
+ int num = hex_colors.size();
126
+ std::string hex = hex_colors[i % num];
127
+
128
+ int r = std::stoi(hex.substr(0, 2), nullptr, 16);
129
+ int g = std::stoi(hex.substr(2, 2), nullptr, 16);
130
+ int b = std::stoi(hex.substr(4, 2), nullptr, 16);
131
+
132
+ if (bgr)
133
+ return cv::Scalar(b, g, r);
134
+ else
135
+ return cv::Scalar(r, g, b);
136
+ }
137
+
138
+ float sigmoid_function(float a)
139
+ {
140
+ float b = 1. / (1. + exp(-a));
141
+ return b;
142
+ }
143
+
144
+ int transpose(float* src, unsigned int* src_dims, unsigned int* tsp_dims, float* dest){
145
+
146
+ int current_coordinate[4] = {0, 0, 0, 0};
147
+ for(int a = 0; a < src_dims[0]; ++a){
148
+ current_coordinate[0] = a;
149
+ for(int b = 0; b < src_dims[1]; ++b){
150
+ current_coordinate[1] = b;
151
+ for(int c = 0; c < src_dims[2]; ++c){
152
+ current_coordinate[2] = c;
153
+ for(int d = 0; d < src_dims[3]; ++d){
154
+ current_coordinate[3] = d;
155
+
156
+ int old_index = current_coordinate[0]*src_dims[1]*src_dims[2]*src_dims[3] +
157
+ current_coordinate[1]*src_dims[2]*src_dims[3] +
158
+ current_coordinate[2]*src_dims[3] +
159
+ current_coordinate[3];
160
+
161
+ int new_index = current_coordinate[tsp_dims[0]]*src_dims[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
162
+ current_coordinate[tsp_dims[1]]*src_dims[tsp_dims[2]]*src_dims[tsp_dims[3]] +
163
+ current_coordinate[tsp_dims[2]]*src_dims[tsp_dims[3]] +
164
+ current_coordinate[tsp_dims[3]];
165
+
166
+ dest[new_index] = src[old_index];
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ return EXIT_SUCCESS;
173
+ }
174
+
175
+
176
+ void draw_label(cv::Mat& input_image, std::string label, int left, int top, cv::Scalar color)
177
+ {
178
+ int baseLine;
179
+ cv::Size label_size = cv::getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS, &baseLine);
180
+ int y = top - label_size.height - baseLine;
181
+ if (y < 0) {
182
+ y = top ;
183
+ }
184
+ cv::Point tlc(left, y);
185
+ cv::Point brc(left + label_size.width, y + label_size.height + baseLine);
186
+ rectangle(input_image, tlc, brc, color, cv::FILLED);
187
+ putText(input_image, label, cv::Point(left, y + label_size.height), FONT_FACE, FONT_SCALE, WHITE, THICKNESS);
188
+ }
189
+
190
+
191
+ cv::Mat post_process(cv::Mat &frame, std::vector<float> &outputs, const std::vector<std::string> &class_name,
192
+ const double ratio, float* protos_data, float* qnn_canc)
193
+ {
194
+ cv::Mat input_image = frame.clone();
195
+ // Initialize vectors to hold respective outputs while unwrapping detections.
196
+ std::vector<int> class_ids;
197
+ std::vector<float> confidences;
198
+ std::vector<cv::Rect> boxes;
199
+ std::vector<cv::Mat> masks;
200
+ std::vector<float> class_scores;
201
+ cv::RNG rng;
202
+ cv::Mat masked_img;
203
+
204
+ unsigned int src_dims[4] = {1, 32,160,160};
205
+ unsigned int tsp_dims[4] = {0,3,1,2};
206
+ unsigned int stride_data_num = 1*32*160*160;
207
+ float* format_data = new float[stride_data_num];
208
+ transpose(protos_data, src_dims, tsp_dims, format_data);
209
+ cv::Mat proto_buffer(32, 160*160, CV_32F, format_data);
210
+ std::cout << "proto_buffer 维度: " << proto_buffer.rows << "x" << proto_buffer.cols << std::endl;
211
+
212
+ for (int i = 0; i < outputs.size(); i+=116)
213
+ {
214
+ auto start = outputs.begin() + i + 4;
215
+ auto end = outputs.begin() + i + 84;
216
+ float max_val = *std::max_element(start, end);
217
+ float confidence = max_val;
218
+ if (confidence >= CONFIDENCE_THRESHOLD)
219
+ {
220
+ auto start = outputs.begin() + i + 4;
221
+ auto end = outputs.begin() + i + 84;
222
+ std::vector<float> middle_data;
223
+ middle_data.assign(start, end);
224
+ // Create a 1x80 Mat and store class scores of 80 classes.
225
+ cv::Mat scores(1, class_name.size(), CV_32FC1, middle_data.data());
226
+ cv::Point class_id;
227
+ double max_class_score;
228
+
229
+ // For multi-label, check each class score
230
+ for (int c = 0; c < class_name.size(); c++) {
231
+ float class_score = scores.at<float>(0, c);
232
+ // If class score is above threshold, consider this class for the box
233
+ if (class_score > SCORE_THRESHOLD) {
234
+ std::vector<float> last32_data;
235
+ auto st_32= outputs.begin() + i + 84;
236
+ auto ed_32 = outputs.begin() + i + 116;
237
+ last32_data.assign(st_32, ed_32);
238
+ cv::Mat mask(1, 32, CV_32FC1, last32_data.data());
239
+ // Store class ID and confidence in the pre-defined respective vectors.
240
+ confidences.push_back(confidence * class_score); // Multiply with confidence
241
+ class_ids.push_back(c); // class index
242
+ // Center and box dimension.
243
+ float cx = outputs[i];
244
+ float cy = outputs[i+1];
245
+ float w = outputs[i+2];
246
+ float h = outputs[i+3];
247
+
248
+ int left = int((cx - 0.5 * w) * ratio);
249
+ int top = int((cy - 0.5 * h) * ratio);
250
+ int width = int(w * ratio);
251
+ int height = int(h * ratio);
252
+
253
+ // Store good detections in the boxes vector.
254
+ boxes.push_back(cv::Rect(left, top, width, height));
255
+ masks.push_back(mask);
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ std::cout << "boxes.size(): " << boxes.size() << ",confidences.size():" << confidences.size() << std::endl;
262
+
263
+ // Perform Non Maximum Suppression and draw predictions.
264
+ std::vector<int> indices;
265
+ cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
266
+ printf("Detected {%ld} targets.\n", indices.size());
267
+ cv::Mat rgb_mask = cv::Mat::zeros(input_image.size(), input_image.type());
268
+
269
+ // Loop over NMS results and draw bounding boxes
270
+ for (int i = 0; i < indices.size(); i++)
271
+ {
272
+ int idx = indices[i];
273
+ cv::Rect box = boxes[idx];
274
+ cv::Scalar color = generate_colors(class_ids[idx]);
275
+
276
+ int x1 = std::max(0, box.x);
277
+ int y1 = std::max(0, box.y);
278
+ int x2 = std::max(0, box.br().x);
279
+ int y2 = std::max(0, box.br().y);
280
+ cv::Mat ms = masks[idx];
281
+ // 维度验证
282
+ if (ms.cols != proto_buffer.rows) {
283
+ cerr << "维度不匹配: mask.cols=" << ms.cols
284
+ << ", proto_buffer.rows=" << proto_buffer.rows << endl;
285
+ continue;
286
+ }
287
+ cv::Mat m = ms * proto_buffer;
288
+ for (int col = 0; col < m.cols; col++) {
289
+ m.at<float>(0, col) = sigmoid_function(m.at<float>(0, col));
290
+ }
291
+ cv::Mat m1 = m.reshape(1, 160); // 1x25600 -> 160x160
292
+
293
+ float ratio2 = 160.0/640.0;
294
+ int mx1 = std::max(0, int((x1 * ratio2)));
295
+ int mx2 = std::max(0, int((x2 * ratio2)));
296
+ int my1 = std::max(0, int((y1 * ratio2)));
297
+ int my2 = std::max(0, int((y2 * ratio2)));
298
+ cv::Mat mask_roi = m1(cv::Range(my1, my2), cv::Range(mx1, mx2));
299
+ cv::Mat rm, det_mask;
300
+ cv::resize(mask_roi, rm, cv::Size(x2 - x1, y2 - y1));
301
+ for (int r = 0; r < rm.rows; r++) {
302
+ for (int c = 0; c < rm.cols; c++) {
303
+ float pv = rm.at<float>(r, c);
304
+ if (pv > 0.5) {
305
+ rm.at<float>(r, c) = 1.0;
306
+ }
307
+ else {
308
+ rm.at<float>(r, c) = 0.0;
309
+ }
310
+ }
311
+ }
312
+ rm = rm * rng.uniform(0, 255);
313
+ rm.convertTo(det_mask, CV_8UC1);
314
+ if ((y1 + det_mask.rows) >= input_image.rows) {
315
+ y2 = input_image.rows - 1;
316
+ }
317
+ if ((x1 + det_mask.cols) >= input_image.cols) {
318
+ x2 = input_image.cols - 1;
319
+ }
320
+
321
+ cv::Mat mask = cv::Mat::zeros(cv::Size(input_image.cols, input_image.rows), CV_8UC1);
322
+ det_mask(cv::Range(0, y2 - y1), cv::Range(0, x2 - x1)).copyTo(mask(cv::Range(y1, y2), cv::Range(x1, x2)));
323
+ add(rgb_mask, cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), rgb_mask, mask);
324
+ if (input_image.size() != rgb_mask.size()) {
325
+ cv::resize(rgb_mask, rgb_mask, input_image.size());
326
+ }
327
+
328
+ cv::rectangle(input_image, boxes[idx], color, 2, 8);
329
+ std::string label = cv::format("%.2f", confidences[idx]);
330
+ label = class_name[class_ids[idx]] + ":" + label;
331
+ cv::putText(input_image, label, cv::Point(boxes[idx].tl().x, boxes[idx].tl().y - 10), cv::FONT_HERSHEY_SIMPLEX, .5, color);
332
+ cv::addWeighted(input_image, 0.5, rgb_mask, 0.5, 0, masked_img);
333
+
334
+ }
335
+ printf("Processing finished.\n");
336
+ return masked_img;
337
+ }
338
+
339
+
340
+
341
+ int invoke(const Args& args) {
342
+ std::cout << "Start main ... ... Model Path: " << args.target_model << "\n"
343
+ << "Image Path: " << args.imgs << "\n"
344
+ << "Inference Nums: " << args.invoke_nums << "\n"
345
+ << "Model Type: " << args.model_type << "\n";
346
+ Model* model = Model::create_instance(args.target_model);
347
+ if(model == nullptr){
348
+ printf("Create model failed !\n");
349
+ return EXIT_FAILURE;
350
+ }
351
+ Config* config = Config::create_instance();
352
+ if(config == nullptr){
353
+ printf("Create config failed !\n");
354
+ return EXIT_FAILURE;
355
+ }
356
+ config->implement_type = ImplementType::TYPE_LOCAL;
357
+ std::string model_type_lower = to_lower(args.model_type);
358
+ if (model_type_lower == "qnn"){
359
+ config->framework_type = FrameworkType::TYPE_QNN;
360
+ } else if (model_type_lower == "snpe2" || model_type_lower == "snpe") {
361
+ config->framework_type = FrameworkType::TYPE_SNPE2;
362
+ }
363
+ config->accelerate_type = AccelerateType::TYPE_DSP;
364
+ config->is_quantify_model = 1;
365
+
366
+ std::vector<std::vector<uint32_t>> input_shapes = {{1, 640, 640, 3}};
367
+ std::vector<std::vector<uint32_t>> output_shapes = {{1,32,8400},{1,4,8400},{1,80,8400},{1,160, 160,32}};
368
+ model->set_model_properties(input_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32, output_shapes, Aidlux::Aidlite::DataType::TYPE_FLOAT32);
369
+ std::unique_ptr<Interpreter> fast_interpreter = InterpreterBuilder::build_interpretper_from_model_and_config(model, config);
370
+ if(fast_interpreter == nullptr){
371
+ printf("build_interpretper_from_model_and_config failed !\n");
372
+ return EXIT_FAILURE;
373
+ }
374
+ int result = fast_interpreter->init();
375
+ if(result != EXIT_SUCCESS){
376
+ printf("interpreter->init() failed !\n");
377
+ return EXIT_FAILURE;
378
+ }
379
+ // load model
380
+ fast_interpreter->load_model();
381
+ if(result != EXIT_SUCCESS){
382
+ printf("interpreter->load_model() failed !\n");
383
+ return EXIT_FAILURE;
384
+ }
385
+ printf("detect model load success!\n");
386
+
387
+ cv::Mat frame = cv::imread(args.imgs);
388
+ if (frame.empty()) {
389
+ printf("detect image load failed!\n");
390
+ return 1;
391
+ }
392
+ printf("img_src cols: %d, img_src rows: %d\n", frame.cols, frame.rows);
393
+ cv::Mat input_img;
394
+ double scale = img_process(frame, input_img, 640);
395
+ if (input_img.empty()) {
396
+ printf("detect input_img load failed!\n");
397
+ return 1;
398
+ }
399
+
400
+ float *qnn_seg_data = nullptr;
401
+ float *qnn_trans_data = nullptr;
402
+ float *qnn_mul_data = nullptr;
403
+ float *qnn_canc_data = nullptr;
404
+
405
+ std::vector<float> invoke_time;
406
+ for (int i = 0; i < args.invoke_nums; ++i) {
407
+ result = fast_interpreter->set_input_tensor(0, input_img.data);
408
+ if(result != EXIT_SUCCESS){
409
+ printf("interpreter->set_input_tensor() failed !\n");
410
+ return EXIT_FAILURE;
411
+ }
412
+ // 开始计时
413
+ auto t1 = std::chrono::high_resolution_clock::now();
414
+ result = fast_interpreter->invoke();
415
+ auto t2 = std::chrono::high_resolution_clock::now();
416
+ std::chrono::duration<double> cost_time = t2 - t1;
417
+ invoke_time.push_back(cost_time.count() * 1000);
418
+ if(result != EXIT_SUCCESS){
419
+ printf("interpreter->invoke() failed !\n");
420
+ return EXIT_FAILURE;
421
+ }
422
+ uint32_t out_data_1 = 0;
423
+ result = fast_interpreter->get_output_tensor(1, (void**)&qnn_canc_data, &out_data_1);
424
+ if(result != EXIT_SUCCESS){
425
+ printf("interpreter->get_output_tensor() 1 failed !\n");
426
+ return EXIT_FAILURE;
427
+ }
428
+
429
+ uint32_t out_data_4 = 0;
430
+ result = fast_interpreter->get_output_tensor(2, (void**)&qnn_trans_data, &out_data_4);
431
+ if(result != EXIT_SUCCESS){
432
+ printf("interpreter->get_output_tensor() 2 failed !\n");
433
+ return EXIT_FAILURE;
434
+ }
435
+
436
+ uint32_t out_data_2 = 0;
437
+ result = fast_interpreter->get_output_tensor(0, (void**)&qnn_seg_data, &out_data_2);
438
+ if(result != EXIT_SUCCESS){
439
+ printf("interpreter->get_output_tensor() 2 failed !\n");
440
+ return EXIT_FAILURE;
441
+ }
442
+
443
+ uint32_t out_data_80 = 0;
444
+ result = fast_interpreter->get_output_tensor(3, (void**)&qnn_mul_data, &out_data_80);
445
+ if(result != EXIT_SUCCESS){
446
+ printf("interpreter->get_output_tensor() 2 failed !\n");
447
+ return EXIT_FAILURE;
448
+ }
449
+ }
450
+
451
+ float max_invoke_time = *std::max_element(invoke_time.begin(), invoke_time.end());
452
+ float min_invoke_time = *std::min_element(invoke_time.begin(), invoke_time.end());
453
+ float mean_invoke_time = std::accumulate(invoke_time.begin(), invoke_time.end(), 0.0f) / args.invoke_nums;
454
+ float var_invoketime = 0.0f;
455
+ for (auto time : invoke_time) {
456
+ var_invoketime += (time - mean_invoke_time) * (time - mean_invoke_time);
457
+ }
458
+ var_invoketime /= args.invoke_nums;
459
+ printf("=======================================\n");
460
+ 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",
461
+ args.invoke_nums, mean_invoke_time, max_invoke_time, min_invoke_time, var_invoketime);
462
+ printf("=======================================\n");
463
+
464
+ float* pos_data = new float[4 * out_size];
465
+ float* class_data = new float[80 * out_size];
466
+ float* canc_data = new float[32 * out_size];
467
+ transformData(qnn_trans_data, pos_data, 4, out_size);
468
+ transformData(qnn_mul_data, class_data, 80, out_size);
469
+ transformData(qnn_canc_data, canc_data, 32, out_size);
470
+
471
+ // post process
472
+ std::vector<float> qnn_concat;
473
+ concatenate_3(class_data, pos_data, canc_data , 1, out_size, 80, 4, 32, qnn_concat);
474
+ cv::Mat img = post_process(frame, qnn_concat, class_list, scale, qnn_seg_data, qnn_canc_data);
475
+ cv::imwrite("./results.png", img);
476
+ fast_interpreter->destory();
477
+ return 0;
478
+ }
479
+
480
+
481
+ int main(int argc, char* argv[]) {
482
+ Args args = parse_args(argc, argv);
483
+ return invoke(args);
484
+ }
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c79839a3aaf6e1447ef583d55854f5255a5bdfb477526b7de3b8ff4357e0b63d
3
+ size 12384696
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/python/bus.jpg ADDED

Git LFS Details

  • SHA256: fb4914d123d97c440cd127ef0e98d4bdc68cd88e2683657528928b4a34014e16
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/python/run_test.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import aidlite
4
+ from utils import eqprocess, xywh2xyxy, NMS, process_mask, masks2segments, draw_detect_res
5
+ import os
6
+ import time
7
+ import argparse
8
+ import onnxruntime
9
+
10
+ # 定义相似度函数
11
+ def get_acc(onnx_out,other_out):
12
+ cosine_similarity=np.dot(np.array(onnx_out),np.array(other_out))/(np.linalg.norm(np.array(onnx_out)) * np.linalg.norm(np.array(other_out)))
13
+ return cosine_similarity
14
+
15
+
16
+ class qnn_predict(object):
17
+ def __init__(self,args) -> None:
18
+ # aidlite.set_log_level(aidlite.LogLevel.INFO)
19
+ # aidlite.log_to_stderr()
20
+ # print(f"Aidlite library version : {aidlite.get_library_version()}")
21
+ # print(f"Aidlite python library version : {aidlite.get_py_library_version()}")
22
+ config = aidlite.Config.create_instance()
23
+ if config is None:
24
+ print("Create model failed !")
25
+ config.implement_type = aidlite.ImplementType.TYPE_LOCAL
26
+ config.framework_type = aidlite.FrameworkType.TYPE_QNN
27
+ config.accelerate_type = aidlite.AccelerateType.TYPE_DSP
28
+ config.is_quantify_model = 1
29
+
30
+ model = aidlite.Model.create_instance(args.target_model)
31
+ if model is None:
32
+ print("Create model failed !")
33
+
34
+ self.conf = args.conf_thres
35
+ self.iou=args.iou_thres
36
+ self.width = args.width
37
+ self.height = args.height
38
+ self.class_num = args.class_num
39
+ self.input_shape = [[1,self.height,self.width,3]]
40
+ self.blocks = int(self.height * self.width * ( 1 / 64 + 1 / 256 + 1 / 1024))
41
+ self.maskw = int(self.width / 4)
42
+ self.maskh = int(self.height / 4)
43
+ self.output_shape = [[1,32,self.blocks],[1,4,self.blocks],[1,self.class_num,self.blocks],[1,self.maskh, self.maskw,32]]
44
+
45
+ model.set_model_properties(self.input_shape, aidlite.DataType.TYPE_FLOAT32, self.output_shape, aidlite.DataType.TYPE_FLOAT32)
46
+ self.interpreter = aidlite.InterpreterBuilder.build_interpretper_from_model_and_config(model, config)
47
+ if self.interpreter is None:
48
+ print("build_interpretper_from_model_and_config failed !")
49
+ result = self.interpreter.init()
50
+ if result != 0:
51
+ print(f"interpreter init failed !")
52
+ result = self.interpreter.load_model()
53
+ if result != 0:
54
+ print("interpreter load model failed !")
55
+ print("detect model load success!")
56
+
57
+ def pretreat_img(self,frame):
58
+ img, scale = eqprocess(frame, self.height, self.width)
59
+ img = img / 255
60
+ img = img.astype(np.float32)
61
+ return img,scale
62
+
63
+ def qnn_run(self, orig_imgs,args):
64
+ input_img_f,scale=self.pretreat_img(orig_imgs) # 图片resize HWC
65
+ input_img = np.expand_dims(input_img_f, 0)
66
+
67
+ invoke_time=[]
68
+ for i in range(args.invoke_nums):
69
+ self.interpreter.set_input_tensor(0, input_img.data)
70
+ t0 = time.time()
71
+ self.interpreter.invoke()
72
+ t1 = time.time()
73
+ cost_time=(t1-t0)*1000
74
+ invoke_time.append(cost_time)
75
+
76
+ input0_data = self.interpreter.get_output_tensor(2).reshape(1,4,self.blocks)
77
+ input1_data = self.interpreter.get_output_tensor(3).reshape(1,self.class_num,self.blocks)
78
+ input2_data = self.interpreter.get_output_tensor(1).reshape(1,32,self.blocks)
79
+ protos = self.interpreter.get_output_tensor(0).reshape(1,self.maskh, self.maskw,32).transpose(0,3,1,2)
80
+
81
+ boxes = np.concatenate([input0_data, input1_data, input2_data], axis = 1)
82
+ x = boxes.transpose(0,2,1)
83
+ x = x[np.amax(x[..., 4:-32], axis=-1) > self.conf]
84
+ if len(x) < 1:
85
+ return None, None
86
+
87
+ x = np.c_[x[..., :4], np.amax(x[..., 4:-32], axis=-1), np.argmax(x[..., 4:-32], axis=-1), x[..., -32:]]
88
+
89
+ x[:, :4] = xywh2xyxy(x[:, :4])
90
+ index = NMS(x[:, :4], x[:, 4], self.iou)
91
+ out_boxes = x[index]
92
+ out_boxes[..., :4] = out_boxes[..., :4] * scale
93
+
94
+ masks = process_mask(protos[0], out_boxes[:, -32:], out_boxes[:, :4], orig_imgs.shape)
95
+ segments = masks2segments(masks)
96
+
97
+ ## time 统计
98
+ max_invoke_time = max(invoke_time)
99
+ min_invoke_time = min(invoke_time)
100
+ mean_invoke_time = sum(invoke_time)/args.invoke_nums
101
+ var_invoketime=np.var(invoke_time)
102
+ print("========================================")
103
+ 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}")
104
+ print("========================================")
105
+
106
+ return out_boxes, segments
107
+
108
+
109
+ def parser_args():
110
+ parser = argparse.ArgumentParser(description="Run model benchmarks")
111
+ parser.add_argument('--target_model',type=str,default='./models/cutoff_yolov8s-seg_w8a8.qnn216.ctx.bin',help="inference model path")
112
+ parser.add_argument('--imgs',type=str,default='./python/bus.jpg',help="Predict images path")
113
+ parser.add_argument('--invoke_nums',type=int,default=10,help="Inference nums")
114
+ parser.add_argument('--model_type',type=str,default='QNN',help="run backend")
115
+ parser.add_argument('--width',type=int,default=640,help="Model input size")
116
+ parser.add_argument('--height',type=int,default=640,help="Model input size")
117
+ parser.add_argument('--conf_thres',type=float,default=0.45,help="confidence threshold for filtering the annotations")
118
+ parser.add_argument('--iou_thres',type=float,default=0.45,help="Iou threshold for filtering the annotations")
119
+ parser.add_argument('--class_num',type=int,default=80,help="Iou threshold for filtering the annotations")
120
+ args = parser.parse_args()
121
+ return args
122
+
123
+ def main(args):
124
+ model = qnn_predict(args)
125
+ frame = cv2.imread(args.imgs)
126
+ qnn_out_boxes, qnn_segments = model.qnn_run(frame,args)
127
+ result = draw_detect_res(frame, qnn_out_boxes, qnn_segments)
128
+ cv2.imwrite("./python/bus_result.jpg", result)
129
+
130
+ if __name__ == "__main__":
131
+ args = parser_args()
132
+ main(args)
133
+
134
+
model_farm_yolov8s_seg_qsc8550_qnn2.16_int8_aidlite/python/utils.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ def draw_detect_res(img, det_pred, segments):
72
+ '''
73
+ 检测结果绘制
74
+ '''
75
+ if det_pred is None:
76
+ return img
77
+
78
+ img = img.astype(np.uint8)
79
+ im_canvas = img.copy()
80
+ color_step = int(255/len(CLASSES))
81
+ for i in range(len(det_pred)):
82
+ x1, y1, x2, y2 = [int(t) for t in det_pred[i][:4]]
83
+ cls_id = int(det_pred[i][5])
84
+ cv2.putText(img, f'{CLASSES[cls_id]}', (x1, y1-6), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
85
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, int(cls_id*color_step), int(255-cls_id*color_step)),thickness = 2)
86
+ if len(segments[i]) > 0:
87
+ cv2.polylines(img, np.int32([segments[i]]), True, (0, int(cls_id*color_step), int(255-cls_id*color_step)), 2)
88
+ cv2.fillPoly(img, np.int32([segments[i]]), (0, int(cls_id*color_step), int(255-cls_id*color_step)))
89
+ img = cv2.addWeighted(im_canvas, 0.3, img, 0.7, 0)
90
+ return img
91
+
92
+ def scale_mask(masks, im0_shape):
93
+ masks = cv2.resize(masks, (im0_shape[1], im0_shape[0]),
94
+ interpolation=cv2.INTER_LINEAR)
95
+ if len(masks.shape) == 2:
96
+ masks = masks[:, :, None]
97
+ return masks
98
+
99
+ def crop_mask(masks, boxes):
100
+ n, h, w = masks.shape
101
+ x1, y1, x2, y2 = np.split(boxes[:, :, None], 4, 1)
102
+ r = np.arange(w, dtype=x1.dtype)[None, None, :]
103
+ c = np.arange(h, dtype=x1.dtype)[None, :, None]
104
+ return masks * ((r >= x1) * (r < x2) * (c >= y1) * (c < y2))
105
+
106
+ def process_mask(protos, masks_in, bboxes, im0_shape):
107
+ c, mh, mw = protos.shape
108
+ masks = np.matmul(masks_in, protos.reshape((c, -1))).reshape((-1, mh, mw)).transpose(1, 2, 0) # HWN
109
+ masks = np.ascontiguousarray(masks)
110
+ masks = scale_mask(masks, im0_shape) # re-scale mask from P3 shape to original input image shape
111
+ masks = np.einsum('HWN -> NHW', masks) # HWN -> NHW
112
+ masks = crop_mask(masks, bboxes)
113
+ return np.greater(masks, 0.5)
114
+
115
+ def masks2segments(masks):
116
+ segments = []
117
+ for x in masks.astype('uint8'):
118
+ c = cv2.findContours(x, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] # CHAIN_APPROX_SIMPLE
119
+ if c:
120
+ c = np.array(c[np.array([len(x) for x in c]).argmax()]).reshape(-1, 2)
121
+ else:
122
+ c = np.zeros((0, 2)) # no segments found
123
+ segments.append(c.astype('float32'))
124
+ return segments