开放能力
开发平台
行业应用
生态合作
开发与教学
资讯 社区 控制台
技术能力
语音技术
图像技术
文字识别
人脸与人体识别
视频技术
AR与VR
自然语言处理
知识图谱
数据智能
场景方案
部署方案
行业应用
智能教育
智能医疗
智能零售
智能工业
企业服务
智能政务
智能农业
信息服务
智能园区
智能硬件
EasyDL零门槛AI开发平台

    物体检测Jetson专用SDK集成文档

    简介

    本文档介绍EasyEdge/EasyDL的Jetson SDK的使用方法。Jetson SDK支持的硬件包括Jetson nano,Jetson TX2,Jetson AGX Xavier和Jetson Xavier NX。您可在AI市场了解Jetson相关系列产品,同时可以在软硬一体方案了解部署方案。

    模型支持:

    • EasyDL图像:图像分类高精度,图像分类高性能,物体检测高精度,物体检测均衡,物体检测高性能。
    • BML:

      • 公开数据集预训练模型:SSD-MobileNetV1,YOLOv3-DarkNet,YOLOv3-MobileNetV1,ResNet50,ResNet101,SE-ResNeXt50,SE-ResNeXt101,MobileNetV2,EfficientNetB0_small,EfficientNetB4,MobileNetV3_large_x1_0,ResNet18_vd,SE_ResNet18_vd,Xception71。
      • 百度超大规模数据集预训练模型:YOLOv3-DarkNet,MobileNetV3_large_x1_0,ResNet50_vd,ResNet101_vd。
    • EasyEdge:EasyEdge支持的模型较多,详见查看模型网络适配硬件。若模型不在此列表,可以尝试使用自定义网络生成端计算组件。

    软件版本支持

    使用EasyDL的Jetson系列SDK需要安装指定版本的JetPack和相关组件。所支持的JetPack版本会随着SDK版本的升级和新版本JetPack的推出而不断的更新。在使用SDK前请务必保证软件版本满足此处声明版本。目前所支持的JetPack版本包括:

    • JetPack4.4
    • JetPack4.2.2

    安装JetPack时请务必安装对应的组件:

    • 使用SDK Manager安装JetPack需要勾选TensorRT、OpenCV、CUDA、cuDNN等选项。
    • 使用SD Card Image方式(仅对Jetson Nano和Jetson Xavier NX有效)则无需关心组件问题,默认会全部安装。

    Release Notes

    时间 版本 说明
    2021.03.09 1.2.1 EasyEdge新增一系列模型的支持;性能优化
    2021.01.27 1.1.0 EasyDL经典版高性能分类模型升级;
    EasyDL经典版检测模型新增均衡选项;
    EasyEdge平台新增Jetson系列端计算组件的生成;
    问题修复
    2020.12.18 1.0.0 接口升级和一些性能优化
    2020.08.11 0.5.5 部分模型预测速度提升
    2020.06.23 0.5.4 支持JetPack4.4DP,支持EasyDL专业版更多模型
    2020.05.15 0.5.3 专项硬件适配SDK支持Jetson系列

    2020-12-18: 【接口升级】 参数配置接口从1.0.0版本开始已升级为新接口,以前的方式被置为deprecated,并将在未来的版本中移除。请尽快考虑升级为新的接口方式,具体使用方式可以参考下文介绍以及demo工程示例,谢谢。

    快速开始

    安装依赖

    本SDK适用于JetPack 4.2.2或JetPack4.4版本,请务必安装其中之一版本,并使用对应版本的SDK。 注意在安装JetPack时,需同时安装CUDA、cuDNN、OpenCV、TensorRT等组件。

    如已安装JetPack需要查询相关版本信息,请参考下文中的开发板信息查询与设置。

    使用序列号激活

    首先请在官网获取序列号。

    将获取到的序列号填写到demo文件中或以参数形式传入。

    编译并运行Demo

    模型资源文件默认已经打包在开发者下载的SDK包中。Demo工程直接编译即可运行。

    编译运行:

    cd demo
    mkdir build && cd build
    cmake ..
    make
    # make install 为可选,也可将lib所在路径添加为环境变量
    sudo make install
    sudo ldconfig
    ./easyedge_batch_inference {模型RES文件夹}  {测试图片路径或仅包含图片的文件夹路径} {序列号}

    demo运行示例:

    baidu@nano:~/ljay/easydl/sdk/demo/build$ ./easyedge_batch_inference ../../../../RES/ /ljay/images/mix008.jpeg
    2020-08-06 20:56:30,665 INFO [EasyEdge] 548125646864 Compiling model for fast inference, this may take a while (Acceleration)
    2020-08-06 20:57:58,427 INFO [EasyEdge] 548125646864 Optimized model saved to: /home/baidu/.baidu/easyedge/jetson/mcache/24110044320/m_cache, Don't remove it
    Results of image /ljay/images/mix008.jpeg: 
    2, kiwi, p:0.997594 loc: 0.352087, 0.56119, 0.625748, 0.868399
    2, kiwi, p:0.993221 loc: 0.45789, 0.0730294, 0.73641, 0.399429
    2, kiwi, p:0.992884 loc: 0.156876, 0.0598725, 0.3802, 0.394706
    1, tomato, p:0.992125 loc: 0.523592, 0.389156, 0.657738, 0.548069
    1, tomato, p:0.991821 loc: 0.665461, 0.419503, 0.805282, 0.573558
    1, tomato, p:0.989883 loc: 0.297427, 0.439999, 0.432197, 0.59325
    1, tomato, p:0.981654 loc: 0.383444, 0.248203, 0.506606, 0.400926
    1, tomato, p:0.971682 loc: 0.183775, 0.556587, 0.286996, 0.711361
    1, tomato, p:0.968722 loc: 0.379391, 0.0386965, 0.51672, 0.209681
    Done

    检测结果展示:

    测试Demo HTTP 服务

    编译demo完成之后,会同时生成一个http服务,运行

    # ./easyedge_serving {res_dir} {serial_key} {host, default 0.0.0.0} {port, default 24401}
     ./easyedge_serving ../../../../RES "1111-1111-1111-1111" 0.0.0.0  24401

    日志中会显示

    HTTP is now serving at 0.0.0.0:24401

    字样,此时,开发者可以打开浏览器,http://{设备ip}:24401,选择图片来进行测试。

    同时,可以调用HTTP接口来访问服务,具体参考下文接口说明。

    使用说明

    使用该方式,将运行库嵌入到开发者的程序当中。

    使用流程

    请优先参考Demo的使用流程。遇到错误,请优先参考文件中的注释解释,以及日志说明。

    // step 1: 配置模型运行参数
    EdgePredictorConfig config;
    config.model_dir = model_dir;
    config.set_config(params::PREDICTOR_KEY_SERIAL_NUM, serial_num);
    config.set_config(params::PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZE, 1);  // 优化的模型可以支持的最大batch_size,实际单次推理的图片数不能大于此值
    config.set_config(params::PREDICTOR_KEY_GTURBO_FP16, false);        // 置true开启fp16模式推理会更快,精度会略微降低,但取决于硬件是否支持fp16,不是所有模型都支持fp16,参阅文档
    config.set_config(params::PREDICTOR_KEY_GTURBO_COMPILE_LEVEL, 1);   // 编译模型的策略,如果当前设置的max_batch_size与历史编译存储的不同,则重新编译模型
    
    
    // step 2: 创建并初始化Predictor
    auto predictor = global_controller()->CreateEdgePredictor<EdgePredictorConfig>(config);
    if (predictor->init() != EDGE_OK) {
        exit(-1);
    }
    
    // step 3: 预测图像
    auto img = cv::imread({图片路径});
    std::vector<EdgeResultData> result;
    predictor->infer(img, result);

    初始化接口

    auto predictor = global_controller()->CreateEdgePredictor<EdgePredictorConfig>(config);
    if (predictor->init() != EDGE_OK) {
            exit(-1);
    }

    若返回非0,请查看输出日志排查错误原因。

    预测接口

    /**
     * @brief
     * 单图预测接口
     * @param image: must be BGR , HWC format (opencv default)
     * @param result
     * @return
     */
    virtual int infer(
            cv::Mat& image, std::vector<EdgeResultData>& result
    ) = 0;
    
    /**
     * @brief
     * 批量图片预测接口
     * @param image: must be BGR , HWC format (opencv default)
     * @param result
     * @return
     */
    virtual int infer(
            std::vector<cv::Mat>& image,
            std::vector<std::vector<EdgeResultData>>& results
    ) = 0;
    
    /**
      * @brief
      * 批量图片预测接口,带阈值
      * @related infer(cv::Mat & image, EdgeColorFormat origin_color_format, std::vector<EdgeResultData> &result, float threshold)
      */
    virtual int infer(
                std::vector<cv::Mat> &images,
                EdgeColorFormat origin_color_format,
                std::vector<std::vector<EdgeResultData>> &results,
                float threshold
    ) = 0;

    图片的格式务必为opencv默认的BGR, HWC格式。

    批量图片的预测接口的使用要求在调用 init 接口的时候设置一个有效的 max_batch_size,其含义见下方参数配置接口的介绍。

    参数配置接口

    参数配置通过结构体EdgePredictorConfig完成。

    struct EdgePredictorConfig {
        /**
         * @brief 模型资源文件夹路径
         */
        std::string model_dir;
    
        std::map<std::string, std::string> conf;
    
        EdgePredictorConfig();
    
        template<typename T>
        T get_config(const std::string &key, const T &default_value);
    
        template<typename T = std::string>
        T get_config(const std::string &key);
    
        template<typename T>
        const T *get_config(const std::string &key, const T *default_value);
    
        template<typename T>
        void set_config(const std::string &key, const T &value);
    
        template<typename T>
        void set_config(const std::string &key, const T *value);
    
        static EdgePredictorConfig default_config();
    };

    运行参数选项的配置以keyvalue的方式存储在类型为std::mapconf中,并且键值对的设置和获取可以通过EdgePredictorConfigset_configget_config函数完成。同时也支持以环境变量的方式设置键值对。 EdgePredictorConfig的具体使用方法可以参考开发工具包中的demo工程。

    针对Jetson开发工具包,目前EdgePredictorConfig的运行参数所支持的Key包括如下项:

    /**
     * @brief 当有同类型的多个设备的时候,使用哪一个设备,如:
     * GPU: 使用哪张GPU卡
     * EdgeBoard(VMX),Movidius NCS :使用哪一张加速卡
     * 值类型:int
     * 默认值:0
     */
    static constexpr auto PREDICTOR_KEY_DEVICE_ID = "PREDICTOR_KEY_DEVICE_ID";
    
    /**
     * @brief 生成最大 batch_size 为 max_batch_size 的优化模型,单次预测图片数量可以小于或等于此值
     * 值类型: int
     * 默认值:4
     */
    static constexpr auto PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZE = "PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZE";
    
    /**
     * @brief 设置device对应的GPU卡可以支持的最大并发量
     * 实际预测的时候对应GPU卡的最大并发量不超过这里设置的范围,否则预测请求会排队等待预测执行
     * 值类型: int
     * 默认值:1
     */
    static constexpr auto PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY = "PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY";
    
    /**
     * @brief 是否开启fp16模式预测,开启后预测速度会更快,但精度会略有降低。并且需要硬件支持fp16
     * 值类型: bool
     * 默认值:false
     */
    static constexpr auto PREDICTOR_KEY_GTURBO_FP16 = "PREDICTOR_KEY_GTURBO_FP16";
    
    /**
     * @brief 模型编译等级
     * 0:无论当前设置的max_batch_size是多少,仅使用历史编译产出(如果存在)
     * 1:如果当前max_batch_size与历史编译产出的max_batch_size不相等时,则重新编译模型(推荐)
     * 2:无论历史编译产出的max_batch_size为多少,均根据当前max_batch_size重新编译模型
     * 值类型: int
     * 默认值:1
     */
    static constexpr auto PREDICTOR_KEY_GTURBO_COMPILE_LEVEL = "PREDICTOR_KEY_GTURBO_COMPILE_LEVEL";
    
    /**
     * @brief GPU工作空间大小设置
     * workspace_size = workspace_prefix * (1 << workspace_offset)
     * workspace_offset: 10 = KB, 20 = MB, 30 = GB
     * 值类型: int
     * 默认值:WORKSPACE_PREFIX: 16, WORKSPACE_OFFSET: 20
     */
    static constexpr auto PREDICTOR_KEY_GTURBO_WORKSPACE_PREFIX = "PREDICTOR_KEY_GTURBO_WORKSPACE_PREFIX";
    static constexpr auto PREDICTOR_KEY_GTURBO_WORKSPACE_OFFSET = "PREDICTOR_KEY_GTURBO_WORKSPACE_OFFSET";
    
    /**
     * @brief 需要使用的dla core
     * 值类型: int
     * 默认值:-1(不使用)
     */
    static constexpr auto PREDICTOR_KEY_GTURBO_DLA_CORE = "PREDICTOR_KEY_GTURBO_DLA_CORE";
    
    /**
     * @brief 自定义缓存文件命名,默认即可
     * 值类型: string
     * 默认值: m_cache
     */
    static constexpr auto PREDICTOR_KEY_GTURBO_CACHE_NAME = "PREDICTOR_KEY_GTURBO_CACHE_NAME";
    
    /**
     * @brief 序列号设置;序列号不设置留空时,SDK将会自动尝试使用本地已经激活成功的有效期内的序列号
     * 值类型:string
     * 默认值:空
     */
    static constexpr auto PREDICTOR_KEY_SERIAL_NUM = "PREDICTOR_KEY_SERIAL_NUM";

    PREDICTOR_KEY_GTURBO_CACHE_NAME:首次加载模型会先对模型进行编译优化,通过此值可以设置优化后的产出文件名。

    PREDICTOR_KEY_GTURBO_WORKSPACE_PREFIXPREDICTOR_KEY_GTURBO_WORKSPACE_OFFSET:设置运行时可以被用来使用的最大临时显存。

    PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZE:此值用来控制批量图片预测可以支持的最大图片数,实际预测的时候单次预测图片数不可大于此值,但可以是不大于此值的任意图片数。

    PREDICTOR_KEY_DEVICE_ID:设置需要使用的 GPU 卡号,对于Jetson,此值无需更改。

    PREDICTOR_KEY_GTURBO_COMPILE_LEVEL:模型编译等级。通常模型的编译会比较慢,但编译产出是可以复用的。可以在第一次加载模型的时候设置合理的 max_batch_size 并在之后加载模型的时候直接使用历史编译产出。是否使用历史编译产出可以通过此值 compile_level 来控制,当此值为 0 时,表示忽略当前设置的 max_batch_size 而仅使用历史产出(无历史产出时则编译模型);当此值为 1 时,会比较历史产出和当前设置的 max_batch_size 是否相等,如不等,则重新编译;当此值为 2 时,无论如何都会重新编译模型。

    PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY:通过此值设置单张 GPU 卡上可以支持的最大 infer 并发量,其上限取决于硬件限制。init 接口会根据此值预分配 GPU 资源,建议结合实际使用控制此值,使用多少则设置多少。注意:此值的增加会降低单次 infer 的速度,建议优先考虑 batch inference。

    PREDICTOR_KEY_GTURBO_FP16:默认是 fp32 模式,置 true 可以开启 fp16 模式预测,预测速度会有所提升,但精度也会略微下降,权衡使用。注意:不是所有模型都支持 fp16 模式,也不是所有硬件都支持 fp16 模式。已知不支持fp16的模型包括:EasyDL图像分类高精度模型。

    日志配置

    设置 EdgeLogConfig 的相关参数。具体含义参考文件中的注释说明。

    EdgeLogConfig log_config;
    log_config.enable_debug = true;
    global_controller()->set_log_config(log_config);

    返回格式

    预测成功后,从 EdgeResultData中可以获取对应的分类信息、位置信息。

    struct EdgeResultData {
        int index;  // 分类结果的index
        std::string label;  // 分类结果的label
        float prob;  // 置信度
    
        // 物体检测或图像分割时才有
        float x1, y1, x2, y2;  // (x1, y1): 左上角, (x2, y2): 右下角; 均为0~1的长宽比例值。
    
        // 图像分割时才有
        cv::Mat mask;  // 0, 1 的mask
        std::string mask_rle;  // Run Length Encoding,游程编码的mask
    };

    关于矩形坐标

    x1 图片宽度 = 检测框的左上角的横坐标 y1 图片高度 = 检测框的左上角的纵坐标 x2 图片宽度 = 检测框的右下角的横坐标 y2 图片高度 = 检测框的右下角的纵坐标

    以上字段可以参考demo文件中使用opencv绘制的逻辑进行解析

    http服务

    1. 开启http服务

    http服务的启动参考demo_serving.cpp文件。

     /**
         * @brief 开启一个简单的demo http服务。
         * 该方法会block直到收到sigint/sigterm。
         * http服务里,图片的解码运行在cpu之上,可能会降低推理速度。
         * @tparam ConfigT
         * @param config
         * @param host
         * @param port
         * @param service_id service_id  user parameter, uri '/get/service_id' will respond this value with 'text/plain'
         * @param instance_num 实例数量,根据内存/显存/时延要求调整
         * @return
         */
        template<typename ConfigT>
        int start_http_server(
                const ConfigT &config,
                const std::string &host,
                int port,
                const std::string &service_id,
                int instance_num = 1);

    2. 请求http服务

    开发者可以打开浏览器,http://{设备ip}:24401,选择图片来进行测试。

    URL中的get参数:

    参数 说明 默认值
    threshold 阈值过滤, 0~1 如不提供,则会使用模型的推荐阈值

    HTTP POST Body即为图片的二进制内容(无需base64, 无需json)

    Python请求示例

    import requests
    
    with open('./1.jpg', 'rb') as f:
        img = f.read()
        result = requests.post(
    	    'http://127.0.0.1:24401/',
    	    params={'threshold': 0.1},
    	    data=img).json()

    Java请求示例参考这里

    http 返回数据

    字段 类型说明 其他
    error_code Number 0为成功,非0参考message获得具体错误信息
    results Array 内容为具体的识别结果。其中字段的具体含义请参考接口使用-返回格式一节
    cost_ms Number 预测耗时ms,不含网络交互时间

    返回示例

    {
        "cost_ms": 52,
        "error_code": 0,
        "results": [
            {
                "confidence": 0.94482421875,
                "index": 1,
                "label": "IronMan",
                "x1": 0.059185408055782318,
                "x2": 0.18795496225357056,
                "y1": 0.14762254059314728,
                "y2": 0.52510076761245728
            },
            {
                "confidence": 0.94091796875,
                "index": 1,
                "label": "IronMan",
                "x1": 0.79151463508605957,
                "x2": 0.92310667037963867,
                "y1": 0.045728668570518494,
                "y2": 0.42920106649398804
            }
          ]
    }

    多线程预测

    Jetson 系列 SDK 支持多线程预测,创建一个 predictor,并通过 PREDICTOR_KEY_GTURBO_MAX_CONCURRENCY 控制所支持的最大并发量,只需要 init 一次,多线程调用 infer 接口。需要注意的是多线程的启用会随着线程数的增加而降低单次 infer 的推理速度,建议优先使用 batch inference 或权衡考虑使用。

    已知问题

    1. 多线程时图片按线程分配不均 或 不同batch size的图片交叉调用infer接口时,部分结果错误

    A:EasyDL图像分类高精度模型在有些显卡上可能存在此问题,可以考虑填充假图片数据到图片比较少的线程或batch以使得infer间的图片绝对平均。

    2. 显存持续增长或遇到 terminate called after throwing an instance of 'std::runtime_error' what(): Failed to create object

    A:如果遇到此问题,请确认没有频繁调用 init 接口,通常调用 infer 接口即可满足需求。

    3. 开启 fp16 后,预测结果错误

    A:不是所有模型都支持 fp16 模式。目前已知的不支持fp16的模型包括:EasyDL图像分类高精度模型。目前不支持的将会在后面的版本陆续支持。

    4. 部分模型不支持序列化

    A:针对JetPack4.4版本,部分模型无法使用序列化,如已知的BML的MobileNetV1-SSD和物体检测高性能模型。需要每次加载模型的时候编译模型,过程会比较慢。此问题将在后续JetPack版本中修复。

    开发板信息查询与设置

    查询L4T或JetPack版本

    查询JetPack版本信息,可以通过下面这条命令先查询L4T的版本。

    # 在终端输入如下命令并回车
    $ head -n 1 /etc/nv_tegra_release
    # 就会输出类似如下结果
    $ # # R32 (release), REVISION: 4.3, GCID: 21589087, BOARD: t210ref, EABI: aarch64, DATE: Fri Jun 26 04:38:25 UTC 2020

    从输出的结果来看,板子当前的L4T版本为R32.4.3,对应JetPack4.4。 注意,L4T的版本不是JetPack的版本,一般可以从L4T的版本唯一对应到JetPack的版本,下面列出了最近几个版本的对应关系:

    L4T R32.4.3  -->  JetPack4.4
    L4T R32.4.2  -->  JetPack4.4DP
    L4T R32.2.1  -->  JetPack4.2.2
    L4T R32.2.0  -->  JetPack4.2.1

    功率模式设置与查询

    不同的功率模式下,执行AI推理的速度是不一样的,如果对速度需求很高,可以把功率开到最大,但记得加上小风扇散热~

    # 1. 运行下面这条命令可以查询开发板当前的运行功率模式
    $ sudo nvpmodel -q verbose
    # $ NV Power Mode: MAXN
    # $ 0
    # 如果输出为MAXN代表是最大功率模式
    
    # 2. 若需要把功率调到最大,运行下面这条命令
    $ sudo nvpmodel -m 0
    
    # 如果你进入了桌面系统,也可以在桌面右上角有个按钮可以切换模式
    
    # 3. 查询资源利用率
    $ sudo tegrastats

    FAQ

    1. EasyDL SDK与云服务效果不一致,如何处理?

    后续我们会消除这部分差异,如果开发者发现差异较大,可联系我们协助处理。

    2. 运行SDK报错 Authorization failed

    日志显示 Http perform failed: null respond 在新的硬件上首次运行,必须联网激活。

    SDK 能够接受HTTP_PROXY 的环境变量通过代理处理自己的网络请求。如

    export HTTP_PROXY="http://192.168.1.100:8888"
    ./easyedge_demo ...

    3. 使用libcurl请求http服务时,速度明显变慢

    这是因为libcurl请求continue导致server等待数据的问题,添加空的header即可

    headers = curl_slist_append(headers, "Expect:");

    4. 运行demo时报找不到libeasyedge_extension.so

    需要export libeasyedge_extension.so所在的路径,如路径为/home/work/baidu/cpp/lib,则需执行:

    export LD_LIBRARY_PATH=/home/work/baidu/cpp/lib:${LD_LIBRARY_PATH}

    或者在编译完后执行如下命令将lib文件安装到系统路径:

    sudo make install

    如不能安装,也可手动复制lib下的文件到/usr/local/lib下。

    5. 运行demo时报如下之一错误

    2020-12-17 16:15:07,924 INFO [EasyEdge] 547633188880 Compiling model for fast inference, this may take a while (Acceleration)
    Killed
    
    # 或
    
    2020-12-17 16:15:07,924 INFO [EasyEdge] 547633188880 Build graph failed

    请适当降低PREDICTOR_KEY_GTURBO_MAX_BATCH_SIZEPREDICTOR_KEY_GTURBO_MAX_CONCURRENCY的值后尝试。

    上一篇
    物体检测EdgeBoard(VMX)专用SDK集成文档
    下一篇
    物体检测常见问题