3.3.2. C++代码解析

3.3.2.1. Case 0: 使用 opencv 解码和数据预处理

在该示例中,我们封装了一个函数,完成目标检测的任务,如下:

/**
* @brief Load a bmodel and do inference.
*
* @param bmodel_path  Path to bmodel
* @param input_path   Path to input file
* @param tpu_id       ID of TPU to use
* @param loops        Number of loops to run
* @param compare_path Path to correct result file
* @return Program state
*     @retval true  Success
*     @retval false Failure
*/
bool inference(
     const std::string& bmodel_path,
     const std::string& input_path,
     int                tpu_id,
     int                loops,
     const std::string& compare_path);

在该函数中,我们通过循环处理同一张图像或者视频的连续帧来模拟真实的目标检测业务。

// pipeline of inference
for (int i = 0; i < loops; ++i) {
  // read an image from a image file or a video file
  cv::Mat frame;
  if (!decoder->read(frame)) {
    break;
  }
  // preprocess
  cv::Mat img1(input_shape[2], input_shape[3], is_fp32 ? CV_32FC3 : CV_8SC3);
  preprocessor.process(frame, img1);
  mat_to_tensor_(img1, in);
  // inference
  engine.process(graph_name, input_tensors, input_shapes, output_tensors);
  auto real_output_shape = engine.get_output_shape(graph_name, output_name);
  // postprocess
  float* output_data = reinterpret_cast<float*>(out.sys_data());
  std::vector<DetectRect> dets;
  postprocessor.process(dets, output_data, real_output_shape,
                        frame.cols, frame.rows);
  // ...
}

在该示例程序中,我们使用了 opencv 进行图像/视频的解码和预处理, CvDecoder、PreProcess 类中均封装了 opencv 的相关 API。

PreProcessor preprocessor(scale);

// ...

CvDecoder* decoder = CvDecoder::create(input_path);

3.3.2.2. Case 1: 使用 bm-ffmpeg 解码、使用 bmcv 做预处理

在该示例程序中,我们使用 bm-ffmpeg 做解码,bmcv 库做预处理。 我们已经在 SAIL 封装了 bm-ffmpeg 与 bmcv 的 API,因此用户无需关注其底层实现。

如下,你可以将 sail::Decoder 看成是 cv::VideoCapture,将 sail::BMImage 看成 cv::Mat;

// init decoder.
// use bm-ffmpeg to decode video. default output format is compressed NV12
sail::Decoder decoder(input_path, true, tpu_id);
bool status = true;
// pipeline of inference
for (int i = 0; i < loops; ++i) {
  // read an image from a image file or a video file
  sail::BMImage img0 = decoder.read(handle);

  // do something...

}

3.3.2.3. Case 2: case 1 的 4N 模式

case 2 的流程与 case 1 几乎一致,但其 bmodel 的 batch 维度是 4。 因此,需要 4 张图像或者 4 帧视频一起处理。

当 bmodel 的 batch 为 4 的倍数时,可以发挥出 TPU 上 int8 算力的最大性能。

3.3.2.4. Case 3: 使用 bm-opencv 进行解码和预处理

Case 3 只适用于SOC模式。 在SOC模式下调用bm-opencv和在PCIE模式下调用opencv的方法基本一致。

3.3.2.5. Case 4: 使用 bm-opencv 解码、使用 bmcv 做预处理

Case 4 只适用于SOC模式。 在SOC模式下调用bm-opencv和在PCIE模式下调用opencv的方法基本一致。