1 /*
2 * Copyright 2023 Unionman Technology Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <cmath>
22 #include <ctime>
23 #include <unistd.h>
24 #include "nn_sdk.h"
25 #include "nn_demo.h"
26 #include "nn_util.h"
27 #include <pthread.h>
28 #include "jpeglib.h"
29 #include <vector>
30 #include <iostream>
31
32 #define USE_OPENCV
33 #ifdef USE_OPENCV
34 #include <opencv2/opencv.hpp>
35 using namespace cv;
36 #endif
37 using namespace std;
38 #define NBG_FROM_MEMORY
39
40 static const char *coco_names[] = {
41 "person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train",
42 "truck", "boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench",
43 "bird", "cat", "dog", "horse", "sheep", "cow", "elephant",
44 "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie",
45 "suitcase", "frisbee", "skis", "snowboard", "sports ball", "kite", "baseball bat",
46 "baseball glove", "skateboard", "surfboard", "tennis racket", "bottle", "wine glass", "cup",
47 "fork", "knife", "spoon", "bowl", "banana", "apple", "sandwich",
48 "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake",
49 "chair", "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor",
50 "laptop", "mouse", "remote", "keyboard", "cell phone", "microwave", "oven",
51 "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors",
52 "teddy bear", "hair drier", "toothbrush"};
53
54 static void *context = nullptr;
55 char *jpath = nullptr;
56 static unsigned char *rawdata = nullptr;
57 static unsigned char *data_carplate = nullptr;
58 static unsigned char *outbuf = nullptr;
59 static unsigned char *inbuf = nullptr;
60 static int use_dma = 0;
61
62 static int input_width = 0, input_high = 0;
63 static int display_width = 640, display_high = 480;
64 nn_input inData;
changeFileName(const std::string & filePath,const std::string & newFileName)65 static std::string changeFileName(const std::string& filePath, const std::string& newFileName)
66 {
67 size_t lastSlashPos = filePath.find_last_of('/');
68 if (lastSlashPos != std::string::npos) {
69 std::string pathBeforeFileName = filePath.substr(0, lastSlashPos + 1);
70 std::string newPath = pathBeforeFileName + newFileName;
71 return newPath;
72 } else {
73 std::cerr << "Invalid file path format." << std::endl;
74 return "erro";
75 }
76 }
77
run_network(void * qcontext,unsigned char * qrawdata,int fbmode,unsigned char * fbbuf)78 int run_network(void *qcontext, unsigned char *qrawdata, int fbmode, unsigned char *fbbuf)
79 {
80 img_classify_out_t *cls_out = nullptr;
81 obj_detect_out_t *obj_detect_out = nullptr;
82 nn_output *outdata = nullptr;
83 aml_module_t modelType;
84 int sz = 1;
85 int j;
86 unsigned int i = 0;
87 int ret = 0;
88 float *buffer = nullptr;
89
90 int cols = WIDTH;
91 int rows = HIGH;
92
93 FILE *fp, *File;
94 aml_output_config_t outconfig;
95 memset(&outconfig, 0, sizeof(aml_output_config_t));
96
97 if (use_dma == 1) {
98 if (qrawdata != inbuf) {
99 memcpy(inbuf, qrawdata, input_high * input_width * CHANNEL);
100 aml_util_flushTensorHandle(qcontext, AML_INPUT_TENSOR); // !!note,flush the input buffer in dma mode
101 }
102 } else {
103 inData.input = qrawdata;
104 }
105
106 ret = aml_module_input_set(qcontext, &inData);
107 if (ret != 0) {
108 printf("aml_module_input_set error\n");
109 }
110
111 #ifndef USE_OPENCV
112 if (rawdata != nullptr) {
113 free(rawdata);
114 rawdata = nullptr;
115 }
116 #endif
117
118 #ifdef USE_OPENCV
119 cv::Mat img;
120 cv::Mat img2;
121 #endif
122
123 // start to record usage time
124 clock_t start, end;
125 double cpu_time_used;
126 start = clock();
127
128 outdata = (nn_output *)aml_module_output_get_simple(qcontext);
129
130 // end to record usage time
131 end = clock();
132 cpu_time_used = (static_cast<double>(end - start)) / CLOCKS_PER_SEC;
133 double fps = 1 / cpu_time_used;
134 printf("used time: %f s; fps: %f\n", cpu_time_used, fps);
135 #ifdef YOLOV2
136 obj_detect_out = (obj_detect_out_t *)postprocess_object_detect(outdata);
137 #else
138 obj_detect_out = (obj_detect_out_t *)postprocess_yolov5(outdata);
139 #endif
140
141 #ifdef USE_OPENCV
142 img = cv::Mat(cols, rows, CV_8UC3);
143 img.data = rawdata;
144 if (fbmode != 0) {
145 img2 = imread((char *)fbbuf);
146 cols = img2.cols;
147 rows = img2.rows;
148 }
149 #endif
150
151 if (obj_detect_out == nullptr) {
152 printf("aml_module_output_get error\n");
153 return -1;
154 }
155
156 {
157 int classid;
158 float prob;
159 printf("object_num:%d\n", obj_detect_out->detNum);
160 for (i = 0; i < obj_detect_out->detNum; i++) {
161 classid = (int)obj_detect_out->pBox[i].objectClass;
162 prob = obj_detect_out->pBox[i].score;
163
164 int left = 0, right = 0, top = 0, bot = 0;
165 #ifdef YOLOV2
166 left = (obj_detect_out->pBox[i].x - obj_detect_out->pBox[i].w / 2L) * cols;
167 right = (obj_detect_out->pBox[i].x + obj_detect_out->pBox[i].w / 2L) * cols;
168 top = (obj_detect_out->pBox[i].y - obj_detect_out->pBox[i].h / 2L) * rows;
169 bot = (obj_detect_out->pBox[i].y + obj_detect_out->pBox[i].h / 2L) * rows;
170 #else
171 left = (obj_detect_out->pBox[i].x - obj_detect_out->pBox[i].w / 2L);
172 right = (obj_detect_out->pBox[i].x + obj_detect_out->pBox[i].w / 2L);
173 top = (obj_detect_out->pBox[i].y - obj_detect_out->pBox[i].h / 2L);
174 bot = (obj_detect_out->pBox[i].y + obj_detect_out->pBox[i].h / 2L);
175 #endif
176 int border = 2.f;
177 if (left < border) {
178 left = border;
179 }
180 if (right > cols - border) {
181 right = cols - border;
182 }
183 if (top < border) {
184 top = border;
185 }
186 if (bot > rows - border) {
187 bot = rows - border;
188 }
189 printf("class:%s,prob:%f,[left = %d,right = %d,top = %d,bot = %d]\n", coco_names[classid], prob, left,
190 right, top, bot);
191 #ifdef USE_OPENCV
192 {
193 cv::rectangle(img, cv::Point(left, top), cv::Point(right, bot), cv::Scalar(0L, 0L, 255L), 2L, 8L);
194 cv::putText(img, cv::format("%s %.2f", coco_names[classid], prob), cv::Point(left, top - 10L),
195 cv::FONT_HERSHEY_SIMPLEX, 0.5f, cv::Scalar(0L, 255L, 0L));
196 }
197 #endif
198 }
199 memset(obj_detect_out, 0, sizeof(obj_detect_out_t));
200 }
201 #ifdef USE_OPENCV
202
203 std::string modifiedPath = changeFileName(jpath, "out.bmp");
204 std::strcpy(jpath, modifiedPath.c_str());
205 cv::imwrite(jpath, img);
206
207 img2.release();
208 #endif
209
210 #ifdef USE_OPENCV
211 if (rawdata != nullptr) {
212 free(rawdata);
213 rawdata = nullptr;
214 }
215 #endif
216 return ret;
217 }
218
init_network(int argc,char ** argv)219 void *init_network(int argc, char **argv)
220 {
221 const char *jpeg_path = nullptr;
222 int size = 0;
223 aml_config config;
224 tensor_info *inptr;
225 tensor_info *outptr;
226 void *qcontext = nullptr;
227
228 memset(&config, 0, sizeof(aml_config));
229 memset(&inData, 0, sizeof(nn_input));
230 FILE *fp, *File;
231
232 #ifdef NBG_FROM_MEMORY
233 fp = fopen(argv[1], "rb");
234 if (fp == nullptr) {
235 printf("open %s fail\n", argv[1]);
236 return nullptr;
237 }
238 fseek(fp, 0, SEEK_END);
239 size = static_cast<int>(ftell(fp));
240 rewind(fp);
241 config.pdata = (char *)calloc(1, size);
242 if (config.pdata == nullptr) {
243 printf("malloc nbg memory fail\n");
244 return nullptr;
245 }
246 fread((void *)config.pdata, 1, size, fp);
247 config.nbgType = NN_NBG_MEMORY; // load nbg from memory
248 config.length = size;
249 fclose(fp);
250
251 #else
252 config.path = (const char *)argv[1];
253 config.nbgType = NN_NBG_FILE; // load nbg from file
254 #endif
255
256 printf("the input type should be %d*%d*%d\n", WIDTH, HIGH, CHANNEL);
257 input_width = WIDTH;
258 input_high = HIGH;
259
260 config.modelType = DARKNET;
261 qcontext = aml_module_create(&config);
262 if (qcontext == nullptr) {
263 printf("amlnn_init is fail\n");
264 return nullptr;
265 }
266 inData.input_index = 0; // this value is index of input,begin from 0
267
268 inData.size = WIDTH * HIGH * CHANNEL;
269
270 inData.input_type = RGB24_RAW_DATA;
271
272 if (config.nbgType == NN_NBG_MEMORY && config.pdata != nullptr) {
273 free((void *)config.pdata);
274 }
275 return qcontext;
276 }
277
destroy_network(void * qcontext)278 int destroy_network(void *qcontext)
279 {
280 if (outbuf)
281 aml_util_freeAlignedBuffer(outbuf);
282 if (inbuf)
283 aml_util_freeAlignedBuffer(inbuf);
284
285 int ret = aml_module_destroy(qcontext);
286 return ret;
287 }
288 #ifdef USE_OPENCV
resize_input_data(unsigned char * indata,unsigned char * outdata)289 int resize_input_data(unsigned char *indata, unsigned char *outdata)
290 {
291 cv::Mat inImage = cv::Mat(display_high, display_width, CV_8UC3);
292 cv::Mat dstImage = cv::Mat(input_high, input_width, CV_8UC3);
293 inImage.data = indata;
294 dstImage.data = outdata;
295 cv::resize(inImage, dstImage, dstImage.size());
296 return 0;
297 }
298 #endif
net_thread_func(void * args)299 void *net_thread_func(void *args)
300 {
301 jpath = (char *)args;
302 int ret = 0;
303 #ifdef USE_OPENCV
304 unsigned char *dup_rgbbuf = nullptr;
305 unsigned char *input_data = nullptr;
306 char cmd[128];
307 char img_name[64];
308 char *ptr;
309 #endif
310 int newWidth = 640;
311 int newHeight = 640;
312 // 调用函数,不需要获取返回值
313 rawdata = get_jpeg_rawData(jpath, input_width, input_high);
314 ret = run_network(context, rawdata, AML_IN_PICTURE, nullptr);
315
316 ret = destroy_network(context);
317 if (ret != 0) {
318 printf("aml_module_destroy error\n");
319 }
320 return nullptr;
321 }
322
main(int argc,char ** argv)323 int main(int argc, char **argv)
324 {
325 int ret = 0;
326 pthread_t tid;
327 void *pic_path = argv[2];
328
329 context = init_network(argc, argv);
330 if (0 != pthread_create(&tid, nullptr, net_thread_func, pic_path)) {
331 fprintf(stderr, "Couldn't create thread func\n");
332 return -1;
333 }
334
335 ret = pthread_join(tid, nullptr);
336
337 return ret;
338 }
339