• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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