Toybrick

关于caffe转的rknn模型c++代码无法显示结果

ylc123

注册会员

积分
146
发表于 2020-6-11 15:01:42    查看: 6043|回复: 3 | [复制链接]    打印 | 显示全部楼层
你好,我自己的caffe模型转换好后,用py测试结果正确。
用咱们提供的rknn_ssd.cpp代码测试咱们自己的mobilenet ssd结果也是正常的,但是:
(1)修改rknn_ssd.cpp里面的类别个数,以及模型路径等去测试咱们提供的caffe文件夹中的vgg ssd时候不会显示任何结果;
(2)修改rknn_ssd.cpp里面的类别个数,以及模型路径等却测试我自己的mobilenet ssd结果也完全不搭边。
(3)我看咱们这个rknn_ssd.cpp代码是TensorFlow文件夹中的mobilenet ssd的测试demo,是否caffe的模型不能用?
(4)可以的话,麻烦可否一下以下几个宏的具体含义。
        #define NUM_RESULTS 2183            prior box个数/4?
        #define NUM_CLASSES 21                类别个数

        #define Y_SCALE 10.0f
        #define X_SCALE 10.0f
        #define H_SCALE 5.0f
        #define W_SCALE 5.0f
代码如下:
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <fstream>
  5. #include <iostream>
  6. #include <sys/time.h>

  7. #include "rknn_api.h"
  8. #include "opencv2/core/core.hpp"
  9. #include "opencv2/imgproc/imgproc.hpp"
  10. #include "opencv2/highgui/highgui.hpp"

  11. #include <time.h>

  12. using namespace std;
  13. using namespace cv;

  14. #define NUM_RESULTS         2183
  15. #define NUM_CLASSES         21

  16. #define Y_SCALE  10.0f
  17. #define X_SCALE  10.0f
  18. #define H_SCALE  5.0f
  19. #define W_SCALE  5.0f

  20. Scalar colorArray[10] = {
  21.         Scalar(139,   0,   0, 255),
  22.         Scalar(139,   0, 139, 255),
  23.         Scalar(  0,   0, 139, 255),
  24.         Scalar(  0, 100,   0, 255),
  25.         Scalar(139, 139,   0, 255),
  26.         Scalar(209, 206,   0, 255),
  27.         Scalar(  0, 127, 255, 255),
  28.         Scalar(139,  61,  72, 255),
  29.         Scalar(  0, 255,   0, 255),
  30.         Scalar(255,   0,   0, 255),
  31. };

  32. float MIN_SCORE = 0.7f;

  33. float NMS_THRESHOLD = 0.45f;


  34. int loadLabelName(string locationFilename, string* labels) {
  35.     ifstream fin(locationFilename);
  36.     string line;
  37.     int lineNum = 0;
  38.     while(getline(fin, line))
  39.     {
  40.         labels[lineNum] = line;
  41.         lineNum++;
  42.     }
  43.     return 0;
  44. }

  45. int loadCoderOptions(string locationFilename, float (*boxPriors)[NUM_RESULTS])
  46. {
  47.     const char *d = ", ";
  48.     ifstream fin(locationFilename);
  49.     string line;
  50.     int lineNum = 0;
  51.     while(getline(fin, line))
  52.     {
  53.         char *line_str = const_cast<char *>(line.c_str());
  54.         char *p;
  55.         p = strtok(line_str, d);
  56.         int priorIndex = 0;
  57.         while (p) {
  58.             float number = static_cast<float>(atof(p));
  59.             boxPriors[lineNum][priorIndex++] = number;
  60.             p=strtok(nullptr, d);
  61.         }
  62.         if (priorIndex != NUM_RESULTS) {
  63.             return -1;
  64.         }
  65.         lineNum++;
  66.     }
  67.     return 0;

  68. }

  69. float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, float ymax1) {
  70.     float w = max(0.f, min(xmax0, xmax1) - max(xmin0, xmin1));
  71.     float h = max(0.f, min(ymax0, ymax1) - max(ymin0, ymin1));
  72.     float i = w * h;
  73.     float u = (xmax0 - xmin0) * (ymax0 - ymin0) + (xmax1 - xmin1) * (ymax1 - ymin1) - i;
  74.     return u <= 0.f ? 0.f : (i / u);
  75. }

  76. float expit(float x) {
  77.     return (float) (1.0 / (1.0 + exp(-x)));
  78. }

  79. void decodeCenterSizeBoxes(float* predictions, float (*boxPriors)[NUM_RESULTS]) {

  80.     for (int i = 0; i < NUM_RESULTS; ++i) {
  81.         float ycenter = predictions[i*4+0] / Y_SCALE * boxPriors[2][i] + boxPriors[0][i];
  82.         float xcenter = predictions[i*4+1] / X_SCALE * boxPriors[3][i] + boxPriors[1][i];
  83.         float h = (float) exp(predictions[i*4 + 2] / H_SCALE) * boxPriors[2][i];
  84.         float w = (float) exp(predictions[i*4 + 3] / W_SCALE) * boxPriors[3][i];

  85.         float ymin = ycenter - h / 2.0f;
  86.         float xmin = xcenter - w / 2.0f;
  87.         float ymax = ycenter + h / 2.0f;
  88.         float xmax = xcenter + w / 2.0f;

  89.         predictions[i*4 + 0] = ymin;
  90.         predictions[i*4 + 1] = xmin;
  91.         predictions[i*4 + 2] = ymax;
  92.         predictions[i*4 + 3] = xmax;
  93.     }
  94. }

  95. int scaleToInputSize(float * outputClasses, int (*output)[NUM_RESULTS], int numClasses)
  96. {
  97.     int validCount = 0;
  98.     // Scale them back to the input size.
  99.     for (int i = 0; i < NUM_RESULTS; ++i) {
  100.         float topClassScore = static_cast<float>(-1000.0);
  101.         int topClassScoreIndex = -1;

  102.         // Skip the first catch-all class.
  103.         for (int j = 1; j < numClasses; ++j) {
  104.             float score = expit(outputClasses[i*numClasses+j]);
  105.             if (score > topClassScore) {
  106.                 topClassScoreIndex = j;
  107.                 topClassScore = score;
  108.             }
  109.         }

  110.         if (topClassScore >= MIN_SCORE) {
  111.             output[0][validCount] = i;
  112.             output[1][validCount] = topClassScoreIndex;
  113.             ++validCount;
  114.         }
  115.     }

  116.     return validCount;
  117. }

  118. int nms(int validCount, float* outputLocations, int (*output)[NUM_RESULTS])
  119. {
  120.     for (int i=0; i < validCount; ++i) {
  121.         if (output[0][i] == -1) {
  122.             continue;
  123.         }
  124.         int n = output[0][i];
  125.         for (int j=i + 1; j<validCount; ++j) {
  126.             int m = output[0][j];
  127.             if (m == -1) {
  128.                 continue;
  129.             }
  130.             float xmin0 = outputLocations[n*4 + 1];
  131.             float ymin0 = outputLocations[n*4 + 0];
  132.             float xmax0 = outputLocations[n*4 + 3];
  133.             float ymax0 = outputLocations[n*4 + 2];

  134.             float xmin1 = outputLocations[m*4 + 1];
  135.             float ymin1 = outputLocations[m*4 + 0];
  136.             float xmax1 = outputLocations[m*4 + 3];
  137.             float ymax1 = outputLocations[m*4 + 2];

  138.             float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1);

  139.             if (iou >= NMS_THRESHOLD) {
  140.                 output[0][j] = -1;
  141.             }
  142.         }
  143.     }

  144.     return 0;
  145. }

  146. int main(int argc, char** argv)
  147. {
  148.     const char *img_path = "./vgg_ssd/road_300x300.jpg";
  149.     const char *model_path = "./vgg_ssd/vgg_ssd.rknn";
  150.     const char *label_path = "./vgg_ssd/label.txt";
  151.     const char *box_priors_path = "./vgg_ssd/mbox_priorbox_97.txt";

  152.     //const char *img_path = "/tmp/road.bmp";
  153.     //const char *model_path = "/tmp/mobilenet_ssd.rknn";
  154.     //const char *label_path = "/tmp/coco_labels_list.txt";
  155.     //const char *box_priors_path = "/tmp/box_priors.txt";

  156.     const int img_width = 300;
  157.     const int img_height = 300;
  158.     const int img_channels = 3;
  159.     const int input_index = 0;      // node name "Preprocessor/sub"

  160.     const int output_elems1 = NUM_RESULTS * 4;
  161.     const uint32_t output_size1 = output_elems1 * sizeof(float);
  162.     const int output_index1 = 0;    // node name "concat"

  163.     const int output_elems2 = NUM_RESULTS * NUM_CLASSES;
  164.     const uint32_t output_size2 = output_elems2 * sizeof(float);
  165.     const int output_index2 = 1;    // node name "concat_1"

  166.     // Load image
  167.     cv::Mat img = cv::imread(img_path, 1);
  168.     if(!img.data) {
  169.         printf("cv::imread %s fail!\n", img_path);
  170.         return -1;
  171.     }
  172.     if(img.cols != img_width || img.rows != img_height)
  173.         cv::resize(img, img, cv::Size(img_width, img_height), (0, 0), (0, 0), cv::INTER_LINEAR);

  174.     // Load model
  175.     FILE *fp = fopen(model_path, "rb");
  176.     if(fp == NULL) {
  177.         printf("fopen %s fail!\n", model_path);
  178.         return -1;
  179.     }
  180.     fseek(fp, 0, SEEK_END);
  181.     int model_len = ftell(fp);
  182.     void *model = malloc(model_len);
  183.     fseek(fp, 0, SEEK_SET);
  184.     if(model_len != fread(model, 1, model_len, fp)) {
  185.         printf("fread %s fail!\n", model_path);
  186.         free(model);
  187.         return -1;
  188.     }

  189.     // Start Inference
  190.     rknn_input inputs[1];
  191.     rknn_output outputs[2];
  192.     rknn_tensor_attr outputs_attr[2];

  193.     int ret = 0;
  194.     rknn_context ctx = 0;

  195.     ret = rknn_init(&ctx, model, model_len, RKNN_FLAG_PRIOR_MEDIUM);
  196.     if(ret < 0) {
  197.         printf("rknn_init fail! ret=%d\n", ret);
  198.         goto Error;
  199.     }

  200.     outputs_attr[0].index = 0;
  201.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[0]), sizeof(outputs_attr[0]));
  202.     if(ret < 0) {
  203.         printf("rknn_query fail! ret=%d\n", ret);
  204.         goto Error;
  205.     }

  206.     outputs_attr[1].index = 1;
  207.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[1]), sizeof(outputs_attr[1]));
  208.     if(ret < 0) {
  209.         printf("rknn_query fail! ret=%d\n", ret);
  210.         goto Error;
  211.     }

  212.     inputs[0].index = input_index;
  213.     inputs[0].buf = img.data;
  214.     inputs[0].size = img_width * img_height * img_channels;
  215.     inputs[0].pass_through = false;
  216.     inputs[0].type = RKNN_TENSOR_UINT8;
  217.     inputs[0].fmt = RKNN_TENSOR_NHWC;
  218.     ret = rknn_inputs_set(ctx, 1, inputs);
  219.     if(ret < 0) {
  220.         printf("rknn_input_set fail! ret=%d\n", ret);
  221.         goto Error;
  222.     }

  223.     ret = rknn_run(ctx, nullptr);
  224.     if(ret < 0) {
  225.         printf("rknn_run fail! ret=%d\n", ret);
  226.         goto Error;
  227.     }

  228.     outputs[0].want_float = true;
  229.     outputs[0].is_prealloc = false;
  230.     outputs[1].want_float = true;
  231.     outputs[1].is_prealloc = false;
  232.      

  233.     clock_t start,finish;
  234.     double totaltime;
  235.     start = clock();
  236.     ret = rknn_outputs_get(ctx, 2, outputs, nullptr);
  237.     finish=clock();
  238.     totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
  239.     cout<<"程序的inference时间为"<<totaltime<<"秒!"<<endl;


  240.     if(ret < 0) {
  241.         printf("rknn_outputs_get fail! ret=%d\n", ret);
  242.         goto Error;
  243.     }
  244.      
  245.      
  246.     // Process output
  247.     if(outputs[0].size == outputs_attr[0].n_elems*sizeof(float) && outputs[1].size == outputs_attr[1].n_elems*sizeof(float))
  248.     {
  249.         float boxPriors[4][NUM_RESULTS];
  250.         string labels[91];

  251.         /* load label and boxPriors */
  252.         loadLabelName(label_path, labels);
  253.         loadCoderOptions(box_priors_path, boxPriors);

  254.         float* predictions = (float*)outputs[0].buf;
  255.         float* outputClasses = (float*)outputs[1].buf;

  256.         int output[2][NUM_RESULTS];

  257.         /* transform */
  258.         decodeCenterSizeBoxes(predictions, boxPriors);

  259.         start = clock();
  260.         int validCount = scaleToInputSize(outputClasses ,output, NUM_CLASSES);
  261.         finish=clock();
  262.         totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
  263.         cout<<"程序的scaleToInputSize时间为"<<totaltime<<"秒!"<<endl;


  264.         printf("validCount: %d\n", validCount);

  265.         if (validCount < 100) {
  266.             /* detect nest box */
  267.             start = clock();
  268.             nms(validCount, predictions, output);
  269.             finish=clock();
  270.             totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
  271.             cout<<"程序的nms时间为"<<totaltime<<"秒!"<<endl;




  272.             start = clock();
  273.             Mat rgba = imread(img_path, CV_LOAD_IMAGE_UNCHANGED);
  274.             cv::resize(rgba, rgba, cv::Size(300, 300), (0, 0), (0, 0), cv::INTER_LINEAR);
  275.             finish=clock();
  276.             totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
  277.             cout<<"程序的imread时间为"<<totaltime<<"秒!"<<endl;
  278.             
  279.             start = clock();
  280.             /* box valid detect target */
  281.             for (int i = 0; i < validCount; ++i) {
  282.                 if (output[0][i] == -1) {
  283.                     continue;
  284.                 }
  285.                 int n = output[0][i];
  286.                 int topClassScoreIndex = output[1][i];

  287.                 int x1 = static_cast<int>(predictions[n * 4 + 1] * rgba.cols);
  288.                 int y1 = static_cast<int>(predictions[n * 4 + 0] * rgba.rows);
  289.                 int x2 = static_cast<int>(predictions[n * 4 + 3] * rgba.cols);
  290.                 int y2 = static_cast<int>(predictions[n * 4 + 2] * rgba.rows);

  291.                 string label = labels[topClassScoreIndex];

  292.                 std::cout << label << "\t@ (" << x1 << ", " << y1 << ") (" << x2 << ", " << y2 << ")" << "\n";

  293.                 rectangle(rgba, Point(x1, y1), Point(x2, y2), colorArray[topClassScoreIndex%10], 3);
  294.                 putText(rgba, label, Point(x1, y1 - 12), 1, 2, Scalar(0, 255, 0, 255));
  295.             }
  296.             imwrite("out.jpg", rgba);
  297.             //printf("write out.jpg succ!\n");
  298.             finish=clock();
  299.             totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
  300.             cout<<"程序的draw时间为"<<totaltime<<"秒!"<<endl;

  301.         } else {
  302.             printf("validCount too much!\n");
  303.         }
  304.     }
  305.     else
  306.     {
  307.         printf("rknn_outputs_get fail! get outputs_size = [%d, %d], but expect [%lu, %lu]!\n",
  308.             outputs[0].size, outputs[1].size, outputs_attr[0].n_elems*sizeof(float), outputs_attr[1].n_elems*sizeof(float));
  309.     }
  310.    
  311.    
  312.     rknn_outputs_release(ctx, 2, outputs);

  313. Error:
  314.     if(ctx)             rknn_destroy(ctx);
  315.     if(model)           free(model);
  316.     if(fp)              fclose(fp);
  317.     return 0;
  318. }
复制代码


回复

使用道具 举报

troy

版主

积分
2346
发表于 2020-6-12 11:59:25 | 显示全部楼层
你的Python代码可以的话,那你对模型的输出格式和后处理有一定的概念,有几个点可以确认一下。
1.目前最新的rknn-toolkit,输出结果时,应该是有保留结果信息的,你可以在Python打印出来看一下,你的模型和mobilenet-ssd输出的格式不一定一致。
2.后处理不是简单套进去就可以,mobilenet-ssd只是提供参考,具体的后处理你要参考你Python的写法。
3.你可以在C里面把outputs的数据n_elems打印出来,跟你Python代码的结果对比一下。
回复

使用道具 举报

ylc123

注册会员

积分
146
 楼主| 发表于 2020-6-12 16:27:30 | 显示全部楼层
troy 发表于 2020-6-12 11:59
你的Python代码可以的话,那你对模型的输出格式和后处理有一定的概念,有几个点可以确认一下。
1.目前最新 ...

谢谢回复。自己已经解决。
回复

使用道具 举报

aslang

新手上路

积分
24
发表于 2020-10-9 14:13:07 | 显示全部楼层
ylc123 发表于 2020-6-12 16:27
谢谢回复。自己已经解决。

你好,请问是怎么解决的?我也遇到这个问题了,能请教一下吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

产品中心 购买渠道 开源社区 Wiki教程 资料下载 关于Toybrick


快速回复 返回顶部 返回列表