TensorRT5.1入门 introductory_parser_samples

.
  这个demo是在c++上运行的一个onnx转tensorRT的示例,跑的是mnist,本来觉得小demo不填坑了,但是直接用python+pytorch生成的.onnx文件在自己写的onnx转tensorRT中,结果不太对,所以回来刚一波这个小demo
  这个demo非常简单(可惜我c++太菜),只有四个方法和一个main组成。
  这个demo除了读取onnx文件,以及对应的解析器等之外,基本上和读取caffe的.prototxt是一样的,这里只是为了深究一波他的ppm图片处理以及output值的问题。

处理pgm图

readPGMFile()

    srand(unsigned(time(nullptr)));
    uint8_t fileData[INPUT_H * INPUT_W];
    int num = rand() % 10;
    readPGMFile(locateFile(std::to_string(num) + ".pgm", gArgs.dataDirs), fileData);

这里就是pgm图的读取部分的main内代码,locateFile方法返回的是该图片的绝对路径,eg:"/home/boyun/TensorRT-5.1.5.0/data/mnist/6.pgm"

// simple PGM (portable greyscale map) reader
void readPGMFile(const std::string& fileName, uint8_t buffer[INPUT_H * INPUT_W])
{
   readPGMFile(fileName, buffer, INPUT_H, INPUT_W);
}

使用的是common.h中的readPGMFile方法。

inline void readPGMFile(const std::string& fileName, uint8_t* buffer, int inH, int inW)
{
    std::ifstream infile(fileName, std::ifstream::binary);
    assert(infile.is_open() && "Attempting to read from a file that is not open.");
    std::string magic, h, w, max;
    infile >> magic >> h >> w >> max;
    infile.seekg(1, infile.cur);
    infile.read(reinterpret_cast<char*>(buffer), inH * inW);
}

读pgm就不得不提pgm的图片格式pgm,即pgm
用ifstream infile读取fileName,然后用 infile+">>"析取器,读取pgm开头的四个string类型(上一行的链接有讲)

infile.seekg()是对输入文件定位的方法,两个参数,第一个参数是偏移量,第二个是基地址。对于第一个参数,可以是正负数值,正的标示向后偏移,负的表示向前偏移。
第二个参数可以是: ios::beg(表示输入流开始位置), ios::cur(输入流当前位置), ios::end(输入流结束位置),

所以,函数中的这句指的是基地址为文件当前位置,偏移地址为1,也是指针定位在文件当前位置的后1位置。
后面接.read()方法,就是从流中读取inH*inW长度的文件,存到buffer中。
这个readPGMFile方法就是读取了pgm的数据放到了fileData中,供以后使用。

做归一化处理

    float data[INPUT_H * INPUT_W];
    for (int i = 0; i < INPUT_H * INPUT_W; i++)
        data[i] = 1.0 - float(fileData[i] / 255.0);

做对应像素的归一化处理。
输入inference的data如下所示:
TensorRT5.1入门 introductory_parser_samples_第1张图片

onnx的解析器

auto parser = nvonnxparser::createParser(*network, gLogger.getTRTLogger());
    if ( !parser->parseFromFile( locateFile(modelFile, gArgs.dataDirs).c_str(), static_cast<int>(gLogger.getReportableSeverity()) ) )
    {
        gLogError << "Failure while parsing ONNX file" << std::endl;
        return false;
    }

build过程中,和caffe转的时候不同的是,这里用到了nvonnxparser命名空间下的createParser方法;然后利用parseFromFile方法解析onnx文件。
runtime过程,是调用进程相关的方法,这里留坑doinference

推断之后产生结果

直接从doinference中产出的prob数据如下所示:
TensorRT5.1入门 introductory_parser_samples_第2张图片

   float val{0.0f};
   int idx{0};

   //Calculate Softmax
   float sum{0.0f};
   for (int i = 0; i < OUTPUT_SIZE; i++)
   {
       prob[i] = exp(prob[i]);
       sum += prob[i];
   }

   gLogInfo << "Output:\n";
   for (int i = 0; i < OUTPUT_SIZE; i++)
   {
       prob[i] /= sum;
       val = std::max(val, prob[i]);
       if (val == prob[i])
           idx = i;

       gLogInfo << " Prob " << i << "  " << std::fixed << std::setw(5) << std::setprecision(4) << prob[i] << " "
                << "Class " << i << ": " << std::string(int(std::floor(prob[i] * 10 + 0.5f)), '*') << "\n";
   }

由上图所致,输出的结果为最后一个全连接层输出,1*10的大小以float类型数组保存。
以上的后处理主要是求softmax。

这个demo很好理解,主要是为别的博文填坑。

你可能感兴趣的:(DL,TensorRT)