流程编排开发方式

本章节介绍的样例适用于Atlas 推理系列产品Atlas 200I/500 A2 推理产品

样例介绍

下面以Atlas 推理系列产品为例,通过Vision SDK图像分类案例,介绍如何使用Vision SDK流程编排方式开发推理应用。案例使用YoloV3模型对图片进行分类并最后输出分类结果。样例取用TensorFlow框架YoloV3模型。

准备工作

  1. 请先完成Vision SDK安装部署后,再进行快速入门样例。

    表1 环境要求软件依赖

    软件依赖名称

    推荐版本

    获取链接

    操作系统

    请参见支持的硬件和操作系统

    -

    系统依赖

    -

    Ubuntu系统CentOS系统

    CANN开发套件包

    8.0.0

    CANN获取链接

    npu-driver驱动包

    Ascend HDK 24.1.0

    1. 选择Ascend Inference Solution中的24.1.RC3版本,查看版本配套表。
    2. 按硬件产品打开下载链接,进入配套Ascend HDK版本下载地址,获取对应NPU软件。
    3. 安装驱动与固件请参见相关硬件产品配套的《驱动和固件安装升级指南》。

    npu-firmware固件包

    Ascend HDK 24.1.0

  2. 获取样例代码。

    请访问获取链接,获取样例代码压缩包。

  3. 登录已安装Vision SDK的开发环境并将样例代码压缩包上传。
  4. 解压样例代码压缩包,进入解压后的目录,命令参考如下。

    1
    2
    unzip pipelineSample.zip 
    cd pipelineSample
    

    样例代码目录结构参考如下。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    |-- pipelineSample
    |   |-- data
    |   |   |-- dog1_1024_683.jpg            //测试图片
    |   |-- models                        //存放模型目录
    |   |   |-- yolov3_tf_bs1_fp16.cfg     //模型配置文件
    |   |   |-- aipp_yolov3_416_416.aippconfig  //yolov3 om模型aipp转换文件
    |   |   |-- yolov3.names   //模型输出类别名称文件
    |   |-- pipeline                     //存放pipeline文件
    |   |   |-- Sample.pipeline        //pipeline文件
    |   |-- src
    |   |   |-- CMakeLists.txt              //CMakeLists文件
    |   |   |-- main.cpp                    //主函数,图片分类功能的实现文件
    |   |-- README.md
    |   |-- run.sh                   //运行程序的脚本,运行前建议使用dos2unix工具执行dos2uinx run.sh命令,对脚本进行格式化处理
    

  5. 参考4解压目录中“README.md”的“准备模型”章节,准备用于推理的yolov3_tf.pb模型。

  6. 准备用于推理的图片数据。

    用户需使用自行获取的图片进行测试(请将获取的图片名称更名为与样例代码的图片名字一致,如dog1_1024_683.jpg),以下图片为展示用途。

    图1 典型样本图片

编排pipeline文件

编排pipeline文件是使用Vision SDK开发应用最核心的任务,图像分类应用可拆解为一系列的业务流程,通过编辑pipeline文件,调用Vision SDK插件库完成推理业务,本文的pipeline文件内容以图2中所示的业务流程进行样例配置编排。

图2 业务流程编排

样例如下所示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
{
  "objectdetection": {                // 修改"objectdetection" 为当前业务推理流程的名称
    "stream_config": {
      "deviceId": "0"                // "deviceId" 表示要使用的芯片的ID号
    },
    "appsrc0": {                     // "appsrc0" 表示输入元件名称
      "props": {                     // "props"指元件属性
        "blocksize": "409600"        // 每个buffer读取的大小
      },
      "factory": "appsrc",           // "factory" 定义该元件类型
      "next": "mxpi_imagedecoder0"   // "next" 填写连接的下游元件--图像解码元件
    },
    "mxpi_imagedecoder0": {          // 图像解码元件名称,0表示编号,如果一个流程中要使用多个图像解码元件,可以依次按照0、1、2...命名
      "props": {
        "handleMethod": "ascend"     // 解码方法为ascend
      },
      "factory": "mxpi_imagedecoder",    // 使用图像解码插件
      "next": "mxpi_imageresize0"    // "next" 填写连接的下游元件--图像缩放元件
    },
    "mxpi_imageresize0": {           // 图像缩放元件名称
      "props": {
        "handleMethod": "ascend",    // 解码方法为ascend
        "resizeHeight": "416",       // 指定缩放后的高
        "resizeWidth": "416",,        // 指定缩放后的宽
        "resizeType": "Resizer_Stretch"      // 缩放方式为拉伸缩放
      },
      "factory": "mxpi_imageresize",     // 使用图像缩放插件
      "next": "mxpi_tensorinfer0"     // "next" 填写连接的下游元件--模型推理元件
    },
    "mxpi_tensorinfer0": {                                   // 模型推理元件名称
      "props": {                                             // "props"指元件属性,可以加载指定目录中的文件
        "dataSource": "mxpi_imageresize0",              // "dataSource"填写连接的上游元件--图像缩放元件
        "modelPath": "../models/yolov3_tf_bs1_fp16.om",    // "modelPath" 属性定义了推理业务使用的模型,用户需要根据获取的模型修改文件名
        "waitingTime": "2000",                               // 多batch模型可容忍的等待组BATCH时间
        "outputDeviceId": "-1"                               // 内存拷贝到指定位置,设为-1则拷贝至Host侧
      },
      "factory": "mxpi_tensorinfer",                         // 使用模型推理插件
      "next": "mxpi_objectdetection0"                     // "next"填写连接的下游元件--模型后处理元件
    },
    "mxpi_objectdetection0": {                            // 模型后处理元件名称
      "props": {                                             // "props"指元件属性,可以加载指定目录中的文件
        "dataSource": "mxpi_tensorinfer0",                   // "dataSource"填写连接的上游元件--模型推理元件
        "postProcessConfigPath": "../models/yolov3_tf_bs1_fp16.cfg",//     "postProcessConfigPath" 指定模型后处理配置文件
        "labelPath": "../models/yolov3.names",    // "labelPath" 指定模型输出的类别名称文件
        "postProcessLibPath": "libyolov3postprocess.so"    // "postProcessLibPath" 指定模型后处理依赖的动态库
      },
      "factory": "mxpi_objectpostprocessor",                  // 使用模型后处理插件
      "next": "mxpi_dataserialize0"                          // "next" 填写连接的下游元件--序列化元件
    },
    "mxpi_dataserialize0": {                                 // 序列化元件名称
      "props": {
        "outputDataKeys": "mxpi_objectdetection0"         // "outputDataKeys" 指定需要输出的数据的索引
      },
      "factory": "mxpi_dataserialize",                       // 使用序列化插件
      "next": "appsink0"                                     // "next" 填写连接的下游元件--输出元件
    },
    "appsink0": {                                            // 输出元件名称
      "props": {
        "blocksize": "4096000"                               // 每个buffer读取的大小
      },
      "factory": "appsink"                                   // 使用输出插件
    }
  }
}

pipeline文件中的注释仅用于辅助理解,在编写pipeline文件时,请删除其中的注释文字,否则会导致文件解析失败。

在这段pipeline中,有以下关键概念:

代码解析

“pipelineSample/src”目录中的“main.cpp”文件为应用程序源码。

在本样例中,关键步骤与代码参考如下,不可以直接拷贝编译运行,需要根据实际情况修改pipeline文件路径、输入图片路径、Stream名称,Stream名称需要与pipeline文件中的业务推理流程的名称匹配,如上述pipeline文件的业务推理流程的名称为“classification”。完整样例代码请参考样例文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
int main(int argc, char* argv[])
 {
    // 1.解析pipeline文件
    std::string pipelineConfigPath = "../pipeline/Sample.pipeline";  // 修改pipeline文件路径  
    std::string pipelineConfig = ReadPipeline(pipelineConfigPath);
    if (pipelineConfig == "") {
        LogError << "Read pipeline failed.";
        return APP_ERR_COMM_INIT_FAIL;
    }
    // 2.初始化stream manager
    MxStream::MxStreamManager mxStreamManager;
    APP_ERROR ret = mxStreamManager.InitManager();
    if (ret != APP_ERR_OK) {
        LogError << GetError(ret) << "Failed to init Stream manager.";
        return ret;
    }
    // 3.创建stream
    ret = mxStreamManager.CreateMultipleStreams(pipelineConfig);
    if (ret != APP_ERR_OK) {
        LogError << GetError(ret) << "Failed to create Stream.";
        mxStreamManager.DestroyAllStreams();
        return ret;
    }
    // 4.读取待推理图片
    MxStream::MxstDataInput dataBuffer;
    ret = ReadFile("../data/dog1_1024_683.jpg", dataBuffer);    // 修改输入图片路径
    if (ret != APP_ERR_OK) {
        LogError << GetError(ret) << "Failed to read image file.";
        mxStreamManager.DestroyAllStreams();
        return ret;
    }
    std::string streamName = "objectdetection";    // 修改业务推理流程的名称
    int inPluginId = 0;
    // 5.发送待推理图片至stream
    ret = mxStreamManager.SendData(streamName, inPluginId, dataBuffer);
    if (ret != APP_ERR_OK) {
        LogError << GetError(ret) << "Failed to send data to stream.";
        delete dataBuffer.dataPtr;
        dataBuffer.dataPtr = nullptr;
        mxStreamManager.DestroyAllStreams();
        return ret;
    }
    // 6.获取推理结果
    MxStream::MxstDataOutput* output = mxStreamManager.GetResult(streamName, inPluginId);
    if (output == nullptr) {
        LogError << "Failed to get pipeline output.";
        delete dataBuffer.dataPtr;
        dataBuffer.dataPtr = nullptr;
        mxStreamManager.DestroyAllStreams();
        return ret;
    }
    std::string result = std::string((char *)output->dataPtr, output->dataSize);
    std::cout << "Results:" << result << std::endl;
    // 7.销毁stream,并释放资源
    mxStreamManager.DestroyAllStreams();
    delete dataBuffer.dataPtr;
    dataBuffer.dataPtr = nullptr;
    delete output;
    return 0;
 }

编译和运行应用

  1. 登录已安装Vision SDK的开发环境,进入“pipelineSample/src”目录。
  2. 配置环境变量(以CANN的默认安装路径“/usr/local/Ascend/ascend-toolkit”Vision SDK的安装路径/home/mxVision-{version}为例)。

    1
    2
    source /usr/local/Ascend/ascend-toolkit/set_env.sh
    source /home/mxVision-{version}/set_env.sh
    

  3. 运行应用,执行编译脚本。

    1
    2
    chmod +x run.sh
    ./run.sh
    

    终端上屏显的结果如下,“classId”表示类别号、“className”表示类名称,“confidence”表示该分类的最大置信度:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    Results:{
        "MxpiObject":[{"classVec":[{
            "classId":16,
            "className":"dog",
            "confidence":0.994434595,
            "headerVec":[]}],
        "x0":113.476166,
        "x1":882.497559,
        "y0":127.61911,
        "y1":595.543884
        }]
    }