xref: /OK3568_Linux_fs/external/rknpu2/examples/rknn_mobilenet_demo/src/main.cc (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // Copyright (c) 2021 by Rockchip Electronics Co., Ltd. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 /*-------------------------------------------
16                 Includes
17 -------------------------------------------*/
18 #include "opencv2/core/core.hpp"
19 #include "opencv2/imgcodecs.hpp"
20 #include "opencv2/imgproc.hpp"
21 #include "rknn_api.h"
22 
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/time.h>
27 
28 #include <fstream>
29 #include <iostream>
30 
31 using namespace std;
32 using namespace cv;
33 
34 /*-------------------------------------------
35                   Functions
36 -------------------------------------------*/
37 
dump_tensor_attr(rknn_tensor_attr * attr)38 static void dump_tensor_attr(rknn_tensor_attr* attr)
39 {
40   printf("  index=%d, name=%s, n_dims=%d, dims=[%d, %d, %d, %d], n_elems=%d, size=%d, fmt=%s, type=%s, qnt_type=%s, "
41          "zp=%d, scale=%f\n",
42          attr->index, attr->name, attr->n_dims, attr->dims[0], attr->dims[1], attr->dims[2], attr->dims[3],
43          attr->n_elems, attr->size, get_format_string(attr->fmt), get_type_string(attr->type),
44          get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale);
45 }
46 
load_model(const char * filename,int * model_size)47 static unsigned char* load_model(const char* filename, int* model_size)
48 {
49   FILE* fp = fopen(filename, "rb");
50   if (fp == nullptr) {
51     printf("fopen %s fail!\n", filename);
52     return NULL;
53   }
54   fseek(fp, 0, SEEK_END);
55   int            model_len = ftell(fp);
56   unsigned char* model     = (unsigned char*)malloc(model_len);
57   fseek(fp, 0, SEEK_SET);
58   if (model_len != fread(model, 1, model_len, fp)) {
59     printf("fread %s fail!\n", filename);
60     free(model);
61     return NULL;
62   }
63   *model_size = model_len;
64   if (fp) {
65     fclose(fp);
66   }
67   return model;
68 }
69 
rknn_GetTop(float * pfProb,float * pfMaxProb,uint32_t * pMaxClass,uint32_t outputCount,uint32_t topNum)70 static int rknn_GetTop(float* pfProb, float* pfMaxProb, uint32_t* pMaxClass, uint32_t outputCount, uint32_t topNum)
71 {
72   uint32_t i, j;
73 
74 #define MAX_TOP_NUM 20
75   if (topNum > MAX_TOP_NUM)
76     return 0;
77 
78   memset(pfMaxProb, 0, sizeof(float) * topNum);
79   memset(pMaxClass, 0xff, sizeof(float) * topNum);
80 
81   for (j = 0; j < topNum; j++) {
82     for (i = 0; i < outputCount; i++) {
83       if ((i == *(pMaxClass + 0)) || (i == *(pMaxClass + 1)) || (i == *(pMaxClass + 2)) || (i == *(pMaxClass + 3)) ||
84           (i == *(pMaxClass + 4))) {
85         continue;
86       }
87 
88       if (pfProb[i] > *(pfMaxProb + j)) {
89         *(pfMaxProb + j) = pfProb[i];
90         *(pMaxClass + j) = i;
91       }
92     }
93   }
94 
95   return 1;
96 }
97 
98 /*-------------------------------------------
99                   Main Function
100 -------------------------------------------*/
main(int argc,char ** argv)101 int main(int argc, char** argv)
102 {
103   const int MODEL_IN_WIDTH    = 224;
104   const int MODEL_IN_HEIGHT   = 224;
105   const int MODEL_IN_CHANNELS = 3;
106 
107   rknn_context ctx = 0;
108   int            ret;
109   int            model_len = 0;
110   unsigned char* model;
111 
112   const char* model_path = argv[1];
113   const char* img_path   = argv[2];
114 
115   if (argc != 3) {
116     printf("Usage: %s <rknn model> <image_path> \n", argv[0]);
117     return -1;
118   }
119 
120   // Load image
121   cv::Mat orig_img = imread(img_path, cv::IMREAD_COLOR);
122   if (!orig_img.data) {
123     printf("cv::imread %s fail!\n", img_path);
124     return -1;
125   }
126 
127   cv::Mat orig_img_rgb;
128   cv::cvtColor(orig_img, orig_img_rgb, cv::COLOR_BGR2RGB);
129 
130   cv::Mat img = orig_img_rgb.clone();
131   if (orig_img.cols != MODEL_IN_WIDTH || orig_img.rows != MODEL_IN_HEIGHT) {
132     printf("resize %d %d to %d %d\n", orig_img.cols, orig_img.rows, MODEL_IN_WIDTH, MODEL_IN_HEIGHT);
133     cv::resize(orig_img, img, cv::Size(MODEL_IN_WIDTH, MODEL_IN_HEIGHT), 0, 0, cv::INTER_LINEAR);
134   }
135 
136   // Load RKNN Model
137   model = load_model(model_path, &model_len);
138   ret   = rknn_init(&ctx, model, model_len, 0, NULL);
139   if (ret < 0) {
140     printf("rknn_init fail! ret=%d\n", ret);
141     return -1;
142   }
143 
144   // Get Model Input Output Info
145   rknn_input_output_num io_num;
146   ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num));
147   if (ret != RKNN_SUCC) {
148     printf("rknn_query fail! ret=%d\n", ret);
149     return -1;
150   }
151   printf("model input num: %d, output num: %d\n", io_num.n_input, io_num.n_output);
152 
153   printf("input tensors:\n");
154   rknn_tensor_attr input_attrs[io_num.n_input];
155   memset(input_attrs, 0, sizeof(input_attrs));
156   for (int i = 0; i < io_num.n_input; i++) {
157     input_attrs[i].index = i;
158     ret                  = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr));
159     if (ret != RKNN_SUCC) {
160       printf("rknn_query fail! ret=%d\n", ret);
161       return -1;
162     }
163     dump_tensor_attr(&(input_attrs[i]));
164   }
165 
166   printf("output tensors:\n");
167   rknn_tensor_attr output_attrs[io_num.n_output];
168   memset(output_attrs, 0, sizeof(output_attrs));
169   for (int i = 0; i < io_num.n_output; i++) {
170     output_attrs[i].index = i;
171     ret                   = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr));
172     if (ret != RKNN_SUCC) {
173       printf("rknn_query fail! ret=%d\n", ret);
174       return -1;
175     }
176     dump_tensor_attr(&(output_attrs[i]));
177   }
178 
179   // Set Input Data
180   rknn_input inputs[1];
181   memset(inputs, 0, sizeof(inputs));
182   inputs[0].index = 0;
183   inputs[0].type  = RKNN_TENSOR_UINT8;
184   inputs[0].size  = img.cols * img.rows * img.channels() * sizeof(uint8_t);
185   inputs[0].fmt   = RKNN_TENSOR_NHWC;
186   inputs[0].buf   = img.data;
187 
188   ret = rknn_inputs_set(ctx, io_num.n_input, inputs);
189   if (ret < 0) {
190     printf("rknn_input_set fail! ret=%d\n", ret);
191     return -1;
192   }
193 
194   // Run
195   printf("rknn_run\n");
196   ret = rknn_run(ctx, nullptr);
197   if (ret < 0) {
198     printf("rknn_run fail! ret=%d\n", ret);
199     return -1;
200   }
201 
202   // Get Output
203   rknn_output outputs[1];
204   memset(outputs, 0, sizeof(outputs));
205   outputs[0].want_float = 1;
206   ret                   = rknn_outputs_get(ctx, 1, outputs, NULL);
207   if (ret < 0) {
208     printf("rknn_outputs_get fail! ret=%d\n", ret);
209     return -1;
210   }
211 
212   // Post Process
213   for (int i = 0; i < io_num.n_output; i++) {
214     uint32_t MaxClass[5];
215     float    fMaxProb[5];
216     float*   buffer = (float*)outputs[i].buf;
217     uint32_t sz     = outputs[i].size / 4;
218 
219     rknn_GetTop(buffer, fMaxProb, MaxClass, sz, 5);
220 
221     printf(" --- Top5 ---\n");
222     for (int i = 0; i < 5; i++) {
223       printf("%3d: %8.6f\n", MaxClass[i], fMaxProb[i]);
224     }
225   }
226 
227   // Release rknn_outputs
228   rknn_outputs_release(ctx, 1, outputs);
229 
230   // Release
231   if (ctx > 0)
232   {
233     rknn_destroy(ctx);
234   }
235   if (model) {
236     free(model);
237   }
238   return 0;
239 }
240