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 Includes
19 -------------------------------------------*/
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #include "vsi_nn_pub.h"
24
25 #include "vnn_global.h"
26 #include "vnn_yolov5s.h"
27
28 /*-------------------------------------------
29 Macros
30 -------------------------------------------*/
31
32 #define NEW_VXNODE(_node, _type, _in, _out, _uid) \
33 do { \
34 _node = vsi_nn_AddNode(graph, _type, _in, _out, NULL); \
35 if (NULL == (_node)) { \
36 goto error; \
37 } \
38 (_node)->uid = (uint32_t)(_uid); \
39 } while (0)
40
41 #define NEW_VIRTUAL_TENSOR(_id, _attr, _dtype) \
42 do { \
43 memset((_attr).size, 0, VSI_NN_MAX_DIM_NUM * sizeof(vsi_size_t)); \
44 (_attr).dim_num = VSI_NN_DIM_AUTO; \
45 (_attr).vtl = !VNN_APP_DEBUG; \
46 (_attr).is_const = FALSE; \
47 (_attr).dtype.vx_type = (_dtype); \
48 (_id) = vsi_nn_AddTensor(graph, VSI_NN_TENSOR_ID_AUTO, &(_attr), NULL); \
49 if (VSI_NN_TENSOR_ID_NA == (_id)) { \
50 goto error; \
51 } \
52 } while (0)
53
54 // Set const tensor dims out of this macro.
55 #define NEW_CONST_TENSOR(_id, _attr, _dtype, _ofst, _size) \
56 do { \
57 data = load_data(fp, (_ofst), (_size)); \
58 (_attr).vtl = FALSE; \
59 (_attr).is_const = TRUE; \
60 (_attr).dtype.vx_type = (_dtype); \
61 (_id) = vsi_nn_AddTensor(graph, VSI_NN_TENSOR_ID_AUTO, &(_attr), data); \
62 free(data); \
63 if (VSI_NN_TENSOR_ID_NA == (_id)) { \
64 goto error; \
65 } \
66 } while (0)
67
68 // Set generic tensor dims out of this macro.
69 #define NEW_NORM_TENSOR(_id, _attr, _dtype) \
70 do { \
71 (_attr).vtl = FALSE; \
72 (_attr).is_const = FALSE; \
73 (_attr).dtype.vx_type = (_dtype); \
74 (_id) = vsi_nn_AddTensor(graph, VSI_NN_TENSOR_ID_AUTO, &(_attr), NULL); \
75 if (VSI_NN_TENSOR_ID_NA == (_id)) { \
76 goto error; \
77 } \
78 } while (0)
79
80 // Set generic tensor dims out of this macro.
81 #define NEW_NORM_TENSOR_FROM_HANDLE(_id, _attr, _dtype) \
82 do { \
83 (_attr).vtl = FALSE; \
84 (_attr).is_const = FALSE; \
85 (_attr).dtype.vx_type = (_dtype); \
86 (_id) = vsi_nn_AddTensorFromHandle(graph, VSI_NN_TENSOR_ID_AUTO, &(_attr), NULL); \
87 if (VSI_NN_TENSOR_ID_NA == (_id)) { \
88 goto error; \
89 } \
90 } while (0)
91
92 #define NET_NODE_NUM (1)
93 #define NET_NORM_TENSOR_NUM (4)
94 #define NET_CONST_TENSOR_NUM (0)
95 #define NET_VIRTUAL_TENSOR_NUM (3)
96 #define NET_TOTAL_TENSOR_NUM (NET_NORM_TENSOR_NUM + NET_CONST_TENSOR_NUM + NET_VIRTUAL_TENSOR_NUM)
97
98 /*-------------------------------------------
99 Local Variables
100 -------------------------------------------*/
101
102 /*-------------------------------------------
103 Functions
104 -------------------------------------------*/
load_data(FILE * fp,size_t ofst,size_t sz)105 static uint8_t *load_data(FILE *fp, size_t ofst, size_t sz)
106 {
107 uint8_t *data;
108 int32_t ret;
109 data = NULL;
110 if (NULL == fp) {
111 return NULL;
112 }
113
114 ret = fseek(fp, ofst, SEEK_SET);
115 if (ret != 0) {
116 VSILOGE("blob seek failure.");
117 return NULL;
118 }
119
120 if (sz <= 0) {
121 // error
122 return NULL;
123 }
124 data = (uint8_t *)malloc(sz);
125 if (data == NULL) {
126 VSILOGE("buffer malloc failure.");
127 return NULL;
128 }
129 ret = fread(data, 1, sz, fp);
130 return data;
131 } /* load_data() */
132
vnn_CreateYolov5s(const char * data_file_name,vsi_nn_context_t in_ctx,const vsi_nn_preprocess_map_element_t * pre_process_map,uint32_t pre_process_map_count,const vsi_nn_postprocess_map_element_t * post_process_map,uint32_t post_process_map_count)133 vsi_nn_graph_t *vnn_CreateYolov5s(const char *data_file_name, vsi_nn_context_t in_ctx,
134 const vsi_nn_preprocess_map_element_t *pre_process_map,
135 uint32_t pre_process_map_count,
136 const vsi_nn_postprocess_map_element_t *post_process_map,
137 uint32_t post_process_map_count)
138 {
139 uint32_t _infinity = VSI_NN_FLOAT32_INF;
140 vsi_status status;
141 vsi_bool release_ctx;
142 vsi_nn_context_t ctx;
143 vsi_nn_graph_t *graph;
144 vsi_nn_node_t *node[NET_NODE_NUM];
145 vsi_nn_tensor_id_t norm_tensor[NET_NORM_TENSOR_NUM];
146
147 vsi_nn_tensor_attr_t attr;
148 FILE *fp;
149 uint8_t *data;
150 uint32_t i = 0L;
151 char *use_img_process_s;
152 int32_t enable_pre_post_process = 0L;
153 vsi_bool sort = FALSE;
154 vsi_bool inference_with_nbg = FALSE;
155 char *pos = NULL;
156
157 (void)(_infinity);
158 ctx = NULL;
159 graph = NULL;
160 status = VSI_FAILURE;
161 memset(&attr, 0, sizeof(attr));
162 memset(&node, 0, sizeof(vsi_nn_node_t *) * NET_NODE_NUM);
163
164 fp = fopen(data_file_name, "rb");
165 if (NULL == fp) {
166 VSILOGE("Open file %s failed.", data_file_name);
167 goto error;
168 }
169
170 pos = strstr((char *)data_file_name, ".nb");
171 if (pos && strcmp(pos, ".nb") == 0) {
172 inference_with_nbg = TRUE;
173 }
174
175 if (NULL == in_ctx) {
176 ctx = vsi_nn_CreateContext();
177 } else {
178 ctx = in_ctx;
179 }
180
181 use_img_process_s = getenv("VSI_USE_IMAGE_PROCESS");
182 if (use_img_process_s) {
183 enable_pre_post_process = atoi(use_img_process_s);
184 }
185
186 graph = vsi_nn_CreateGraph(ctx, NET_TOTAL_TENSOR_NUM, NET_NODE_NUM);
187 if (NULL == graph) {
188 VSILOGE("Create graph fail.");
189 goto error;
190 }
191 vsi_nn_SetGraphVersion(graph, VNN_VERSION_MAJOR, VNN_VERSION_MINOR, VNN_VERSION_PATCH);
192 vsi_nn_SetGraphInputs(graph, NULL, 1L);
193 vsi_nn_SetGraphOutputs(graph, NULL, 3L);
194
195 /*-----------------------------------------
196 Register client ops
197 -----------------------------------------*/
198
199 /*-----------------------------------------
200 Node definitions
201 -----------------------------------------*/
202 if (!inference_with_nbg) {
203
204 /*-----------------------------------------
205 lid - nbg_0
206 var - node[0]
207 name - nbg
208 operation - nbg
209 input - [640, 640, 3, 1]
210 output - [80, 80, 255, 1]
211 [40, 40, 255, 1]
212 [20, 20, 255, 1]
213 -----------------------------------------*/
214 NEW_VXNODE(node[0], VSI_NN_OP_NBG, 1, 3, 0);
215 node[0]->nn_param.nbg.type = VSI_NN_NBG_FILE;
216 node[0]->nn_param.nbg.url = data_file_name;
217
218 } else {
219 NEW_VXNODE(node[0], VSI_NN_OP_NBG, 1, 3, 0);
220 node[0]->nn_param.nbg.type = VSI_NN_NBG_FILE;
221 node[0]->nn_param.nbg.url = data_file_name;
222 }
223
224 /*-----------------------------------------
225 Tensor initialize
226 -----------------------------------------*/
227 attr.dtype.fmt = VSI_NN_DIM_FMT_NCHW;
228 /* @attach_Sigmoid_Sigmoid_146/out0_0:out0 */
229 attr.size[0L] = 80L;
230 attr.size[1L] = 80L;
231 attr.size[2L] = 255L;
232 attr.size[3L] = 1L;
233 attr.dim_num = 4L;
234 attr.dtype.scale = 0.0039130267687141895f;
235 attr.dtype.zero_point = 0L;
236 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
237 NEW_NORM_TENSOR(norm_tensor[0], attr, VSI_NN_TYPE_UINT8);
238
239 /* @attach_Sigmoid_Sigmoid_148/out0_1:out0 */
240 attr.size[0L] = 40L;
241 attr.size[1L] = 40L;
242 attr.size[2L] = 255L;
243 attr.size[3L] = 1L;
244 attr.dim_num = 4L;
245 attr.dtype.scale = 0.003908432554453611f;
246 attr.dtype.zero_point = 0L;
247 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
248 NEW_NORM_TENSOR(norm_tensor[1], attr, VSI_NN_TYPE_UINT8);
249
250 /* @attach_Sigmoid_Sigmoid_150/out0_2:out0 */
251 attr.size[0L] = 20L;
252 attr.size[1L] = 20L;
253 attr.size[2L] = 255L;
254 attr.size[3L] = 1L;
255 attr.dim_num = 4L;
256 attr.dtype.scale = 0.003916851710528135f;
257 attr.dtype.zero_point = 0L;
258 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
259 NEW_NORM_TENSOR(norm_tensor[2], attr, VSI_NN_TYPE_UINT8);
260
261 /* @images_152:out0 */
262 attr.size[0L] = 640L;
263 attr.size[1L] = 640L;
264 attr.size[2L] = 3L;
265 attr.size[3L] = 1L;
266 attr.dim_num = 4L;
267 attr.dtype.scale = 0.00390625f;
268 attr.dtype.zero_point = 0L;
269 attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
270 NEW_NORM_TENSOR(norm_tensor[3], attr, VSI_NN_TYPE_UINT8);
271
272 if (!inference_with_nbg) {
273 /*-----------------------------------------
274 Connection initialize
275 -----------------------------------------*/
276 node[0L]->input.tensors[0L] = norm_tensor[3L];
277 node[0L]->output.tensors[0L] = norm_tensor[0L];
278 node[0L]->output.tensors[1L] = norm_tensor[1L];
279 node[0L]->output.tensors[2L] = norm_tensor[2L];
280 /* nbg_0L */
281 } else {
282 node[0L]->output.tensors[0L] = norm_tensor[0L];
283 node[0L]->output.tensors[1L] = norm_tensor[1L];
284 node[0L]->output.tensors[2L] = norm_tensor[2L];
285 node[0L]->input.tensors[0L] = norm_tensor[3L];
286 }
287 graph->output.tensors[0L] = norm_tensor[0L];
288 graph->output.tensors[1L] = norm_tensor[1L];
289 graph->output.tensors[2L] = norm_tensor[2L];
290 graph->input.tensors[0L] = norm_tensor[3L];
291
292 if (enable_pre_post_process) {
293 sort = TRUE;
294 if (pre_process_map_count > 0) {
295 for (i = 0; i < pre_process_map_count; i++) {
296 status =
297 vsi_nn_AddGraphPreProcess(graph, pre_process_map[i].graph_input_idx,
298 pre_process_map[i].preprocesses, pre_process_map[i].preprocess_count);
299 TEST_CHECK_STATUS(status, error);
300 }
301 }
302
303 if (post_process_map_count > 0) {
304 for (i = 0; i < post_process_map_count; i++) {
305 status = vsi_nn_AddGraphPostProcess(graph, post_process_map[i].graph_output_idx,
306 post_process_map[i].postprocesses,
307 post_process_map[i].postprocess_count);
308 TEST_CHECK_STATUS(status, error);
309 }
310 }
311 }
312
313 status = vsi_nn_SetupGraph(graph, sort);
314 TEST_CHECK_STATUS(status, error);
315
316 if (VSI_FAILURE == status) {
317 goto error;
318 }
319
320 fclose(fp);
321
322 return graph;
323
324 error:
325 if (NULL != fp) {
326 fclose(fp);
327 }
328
329 release_ctx = (NULL == in_ctx);
330 vsi_nn_DumpGraphToJson(graph);
331 vnn_ReleaseYolov5s(graph, release_ctx);
332
333 return NULL;
334 } /* vsi_nn_CreateYolov5s() */
335
vnn_ReleaseYolov5s(vsi_nn_graph_t * graph,vsi_bool release_ctx)336 void vnn_ReleaseYolov5s(vsi_nn_graph_t *graph, vsi_bool release_ctx)
337 {
338 vsi_nn_context_t ctx;
339 if (NULL != graph) {
340 ctx = graph->ctx;
341 vsi_nn_ReleaseGraph(&graph);
342
343 /*-----------------------------------------
344 Unregister client ops
345 -----------------------------------------*/
346
347 if (release_ctx) {
348 vsi_nn_ReleaseContext(&ctx);
349 }
350 }
351 } /* vsi_nn_ReleaseYolov5s() */
352