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

    物体检测LinuxSDK集成文档-C++

    简介

    本文档介绍EasyEdge/EasyDL的Linux CPP SDK的使用方法。

    • 网络类型支持: - 图像分类 - 物体检测 - 图像分割
    • 硬件支持:

      • CPU: aarch64 armv7hf
      • ASIC: Hisilicon NNIE1.1 on aarch64(Hi3559AV100/Hi3559CV100等)
      • ASIC: Hisilicon NNIE1.2 on armv7l(Hi3519AV100/Hi3559V200等)
      • Intel Movidius MyRIAD2 / MyRIAD X on x86_64
      • Intel Movidius MyRIAD2 / MyRIAD X on armv7l(树莓派3b+)
      • Intel Movidius MyRIAD2 / MyRIAD X on aarch64
      • 比特大陆 Bitmain SE50 (BM1684)
      • 瑞芯微 RK3399Pro
    • 操作系统支持:

      • Linux (Ubuntu, Centos, Debian等)
      • 海思HiLinux
      • 树莓派Raspbian
      • 瑞芯微Firefly

    性能数据参考算法性能及适配硬件

    Release Notes

    时间 版本 说明
    2021.03.09 1.2.0 http server服务支持图片通过base64格式调用
    2021.01.27 1.1.0 EasyDL经典版分类高性能模型升级;部分SDK不再需要单独安装OpenCV;新增RKNPU预测引擎支持;新增高通骁龙GPU预测引擎支持
    2020.12.18 1.0.0 1.0版本发布!安全加固升级、性能优化、引擎升级、接口优化等多项更新
    2020.10.29 0.5.7 优化多线程预测细节
    2020.09.17 0.5.6 支持linux aarch64架构的硬件接入intel神经计算棒预测;支持比特大陆计算盒SE50 BM1684
    2020.08.11 0.5.5 支持树莓派接入intel神经计算棒预测
    2020.06.23 0.5.4 arm引擎升级
    2020.05.15 0.5.3 支持EasyDL 专业版新增模型 ;支持树莓派(armv7hf, aarch64)
    2020.04.16 0.5.2 Jetson系列SDK支持多线程infer
    2020.02.23 0.5.0 新增支持人脸口罩模型;Jetson SDK支持批量图片推理; ARM支持图像分割
    2020.01.16 0.4.7 上线海思NNIE1.2,支持EasyEdge以及EasyDL;ARM引擎升级;增加推荐阈值支持
    2019.12.26 0.4.6 海思NNIE支持EasyDL专业版
    2019.11.02 0.4.5 移除curl依赖;支持自动编译OpenCV;支持EasyDL 专业版 Yolov3; 支持EasyDL经典版高精度物体检测模型升级
    2019.10.25 0.4.4 ARM引擎升级,性能提升30%; 支持EasyDL专业版模型
    2019.09.23 0.4.3 增加海思NNIE加速芯片支持
    2019.08.30 0.4.2 ARM引擎升级;支持分类高性能与高精度模型
    2019.07.25 0.4.1 引擎升级,性能提升
    2019.06.11 0.3.3 paddle引擎升级;性能提升
    2019.05.16 0.3.2 新增armv7l支持
    2019.04.25 0.3.1 优化硬件支持
    2019.03.29 0.3.0 ARM64 支持;效果提升
    2019.02.20 0.2.1 paddle引擎支持;效果提升
    2018.11.30 0.1.0 第一版!

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

    快速开始

    SDK在以下环境中测试通过

    • aarch64(arm64), Ubuntu 16.04, gcc 5.3 (RK3399)
    • Hi3559AV100, aarch64, Ubuntu 16.04, gcc 5.3
    • Hi3519AV100, armv7l , HiLinux 4.9.37, (Hi3519AV100R001C02SPC020)
    • armv7hf, Raspbian, (Raspberry 3b)
    • aarch64, Raspbian, (Raspberry 4b)
    • armv7l, Raspbian, (Raspberry 3b+)
    • Bitmain se50 BM1684, Debian 9
    • Rockchip rk3399pro, Ubuntu 18.04

    安装依赖

    依赖包括

    • cmake 3+
    • gcc 5.4 以上(需包含 GLIBCXX_3.4.22) ,gcc / glibc版本请以实际SDK ldd的结果为准
    • opencv3.4.5 (可选)
    • opencv4.3.0 (可选)
    • openvino 2020.3.1LTS版本 (可选)

    依赖说明:树莓派

    树莓派Raspberry默认为armv7hf系统,使用SDK包中名称中包含armv7hf_ARM_的tar包。如果是aarch64系统,使用SDK包中名称中包含aarch64_ARM_的tar包。

    在安装前可通过以下命令查看是32位还是64位 :

    # 以下是32位的结果
    cat /proc/device-tree/model
    Raspberry Pi 3 Model B Plus Rev 1.3
    
    getconf LONG_BIT
    32
    
    uname -m
    armv7l

    依赖说明:Intel Movidius MyRIAD2 / MyRIAD X on x86_64

    需要安装OpenVINO™ toolkit,参考openvino toolkit下载并安装2020.3.1LTS版本。

    依赖说明:Intel Movidius MyRIAD2 / MyRIAD X on armv7l(树莓派3b+)

    需要安装OpenVINO™ toolkit,参考openvino toolkit 文档安装 2020.3.1LTS版本

    依赖说明:Intel Movidius MyRIAD2 / MyRIAD X on Linux aarch64

    不用单独安装OpenVINO™ toolkit 预测引擎。 需要自行安装OpenCV4.3.0,并在使用SDK时指定4.3.0版本OpenCV的路径OpenCV源码编译安装地址

    依赖说明:比特大陆SE计算盒

    需要安装BMNNSDK2.2,并在CMakeList.txt中指定SDK安装地址:

    # 这里修改并填入所使用的bmnnsdk路径
    set(EDGE_BMSDK_ROOT "{这里填写sdk路径}")

    依赖说明:海思开发板

    海思开发板需要根据海思SDK文档配置开运行环境和编译环境,SDK和opencv都需要在该编译环境中编译。 NNIE1.2用arm-himix200-linux交叉编译好的opencv,下载链接:https://pan.baidu.com/s/13QW0ReeWx4ZwgYg4lretyw 密码:yq0s。下载后修改SDK CMakesList.txt

    使用序列号激活

    在控制台获取的序列号请通过global_controller()->set_licence_key("")方法设置。

    具体请参考SDK自带的Demo.cpp文件的使用方法。

    测试Demo

    模型资源文件默认已经打包在开发者下载的SDK包中。

    Demo工程直接编译即可运行。

    请先将tar包整体拷贝到具体运行的设备中,再解压缩编译; 对于硬件使用为: -Intel Movidius MyRIAD2 / MyRIAD X on Linux aarch64,在编译前指定4.3.0版本OpenCV的路径: export OpenCV_DIR={opencv_install_prefix}/lib/cmake/opencv4

    • Intel Movidius MyRIAD2 / MyRIAD X on x86_64 / armv7l(树莓派3b+),在编译前执行以下命令: source /opt/intel/openvino/bin/setupvars.sh

    部分SDK中已经包含预先编译的二进制, bin/easyedge_demo, bin/easyedge_serving,配置LD_LIBRARY_PATH后,可直接运行: LD_LIBRARY_PATH=../lib ./bin/easyedge_serving

    请在官网获取序列号,填写在demo.cpp

    编译运行:

    cd demo
    mkdir build && cd build
    cmake .. && make
    ./easyedge_demo {模型RES文件夹}  {测试图片路径}
    # 如果是NNIE引擎,使用sudo运行
    sudo ./easyedge_demo {模型RES文件夹}  {测试图片路径}

    如果希望SDK自动编译安装所需要的OpenCV库,修改cmake的optionEDGE_BUILD_OPENCVON即可。 SDK会自动从网络下载opencv源码,并编译需要的module、链接。注意,此功能必须需联网。

    cmake -DEDGE_BUILD_OPENCV=ON .. && make -j16

    若需自定义library search path或者gcc路径,修改CMakeList.txt即可。

    对于硬件使用为Intel Movidius MyRIAD2 / MyRIAD X on Linux aarch64的,如果要使用英特尔2代神经计算棒Intel® Neural Compute Stick 2,找到设备需要执行以下命令添加USB Rules:

    cp ${CPP_SDK_DIR}/openvino/97-myriad-usbboot.rules  /etc/udev/rules.d/
    sudo udevadm control --reload-rules
    sudo udevadm trigger
    sudo ldconfig

    demo运行效果:

     > ./easyedge_demo ../../../../RES 2.jpeg
    2019-02-13 16:46:12,659 INFO [EasyEdge] [easyedge.cpp:34] 140606189016192 Baidu EasyEdge Linux Development Kit 0.2.1(20190213)
    2019-02-13 16:46:14,083 INFO [EasyEdge] [paddlev2_edge_predictor.cpp:60] 140606189016192 Allocate graph success.
    2019-02-13 16:46:14,326 DEBUG [EasyEdge] [paddlev2_edge_predictor.cpp:143] 140606189016192 Inference costs 168 ms
    1, 1:txt_frame, p:0.994905 loc: 0.168161, 0.153654, 0.920856, 0.779621
    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 = {模型文件目录};
    
        // step 2: 创建并初始化Predictor;这这里选择合适的引擎
        auto predictor = global_controller()->CreateEdgePredictor(config);
    
        auto img = cv::imread({图片路径});
        // step 3: 预测图像
        std::vector<EdgeResultData> result2;
        predictor->infer(img, result2);

    对于口罩检测模型,将 EdgePredictorConfig config修改为PaddleMultiStageConfig config即可。

    口罩检测模型请注意输入图片中人脸大小建议保持在 88到9696像素之间,可根据场景远近程度缩放图片后再传入SDK。

    SDK参数配置

    SDK的参数通过EdgePredictorConfig::set_configglobal_controller()->set_config配置。set_config的所有key在easyedge_xxxx_config.h中。其中

    • PREDICTOR前缀的key是不同模型相关的配置,通过EdgePredictorConfig::set_config设置
    • CONTROLLER前缀的key是整个SDK的全局配置,通过global_controller()->set_config设置

    以序列号为例,KEY的说明如下:

    /**
     * @brief 序列号设置;序列号不设置留空时,SDK将会自动尝试使用本地已经激活成功的有效期内的序列号
     * 值类型:string
     * 默认值:空
     */
    static constexpr auto PREDICTOR_KEY_SERIAL_NUM = "PREDICTOR_KEY_SERIAL_NUM";

    使用方法如下:

    EdgePredictorConfig config;
    config.model_dir = ...;
    config.set_config(params::PREDICTOR_KEY_SERIAL_NUM, "1DB7-1111-1111-D27D");

    具体支持的运行参数可以参考开发工具包中的头文件的详细说明。

    初始化

    • 接口
    auto predictor = global_controller()->CreateEdgePredictor(config);
    predictor->init();

    若返回非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;

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

    • 返回格式

    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 * 图片高度 = 检测框的右下角的纵坐标

    关于图像分割mask

    cv::Mat mask为图像掩码的二维数组
    {
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
      {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
      {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
      {0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    }
    其中1代表为目标区域,0代表非目标区域

    关于图像分割mask_rle

    该字段返回了mask的游程编码,解析方式可参考 http demo

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

    设置序列号

    请在网页控制台中申请序列号,并在init初始化前设置。 LinuxSDK 首次使用需联网授权。

    EdgePredictorConfig config;
    config.set_config(easyedge::params::PREDICTOR_KEY_SERIAL_NUM, "this-is-serial-num");

    日志配置

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

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

    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,选择图片来进行测试。

    http 请求方式一:不使用图片base64格式

    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 请求方法二:使用图片base64格式

    HTTP方法:POST Header如下:

    参数
    Content-Type application/json

    Body请求填写

    • 分类网络: body 中请求示例
    {
    	"image": "<base64数据>"
    	"top_num": 5
    }

    body中参数详情 参数 | 是否必选 | 类型 | 可选值范围 | 说明 --- | --- | --- | --- | --- image | 是 | string | - | 图像数据,base64编码,要求base64图片编码后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/png/bmp格式 注意去掉头部 top_num | 否 | number | - | 返回分类数量,不填该参数,则默认返回全部分类结果

    • 检测和分割网络: Body请求示例:
    {
    	"image": "<base64数据>"
    }

    body中参数详情: 参数 | 是否必选 | 类型 | 可选值范围 | 说明 --- | --- | --- | --- | --- image | 是 | string | - | 图像数据,base64编码,要求base64图片编码后大小不超过4M,最短边至少15px,最长边最大4096px,支持jpg/png/bmp格式 注意去掉头部 threshold | 否 | number | - | 默认为推荐阈值,也可自行根据需要进行设置

    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
            }
          ]
    }

    其他配置

    1. 日志名称、HTTP 网页标题设置

    通过global_controller的set_config方法设置:

    global_controller()->set_config(easyedge::params::KEY_LOG_BRAND, "MY_BRAND");

    效果如下: 图片

    FAQ

    1. 如何处理一些 undefined reference / error while loading shared libraries?

    如:./easyedge_demo: error while loading shared libraries: libeasyedge.so.1: cannot open shared object file: No such file or directory 这是因为二进制运行时ld无法找到依赖的库。如果是正确cmake && make 的程序,会自动处理好链接,一般不会出现此类问题。

    遇到该问题时,请找到具体的库的位置,设置LD_LIBRARY_PATH。

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

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

    3. 如何将我的模型运行为一个http服务?

    目前cpp sdk暂未集成http运行方式; 0.4.7版本之后,可以通过start_http_server方法开启http服务。

    4. 运行NNIE引擎报permission denied

    日志显示:

    open sys: Permission denied
    open err
    : Permission denied
    open err
    : Permission denied

    请使用sudo在root下运行。

    5. 运行SDK报错 Authorization failed

    情况一:日志显示 Http perform failed: null respond

    在新的硬件上首次运行,必须联网激活。

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

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

    情况二:日志显示failed to get/check device id(xxx)或者Device fingerprint mismatch(xxx)

    此类情况一般是设备指纹发生了变更,包括(但不局限于)以下可能的情况:

    • MAC地址变化
    • 磁盘变更
    • BIOS重刷

    以及系统相关信息。

    遇到这类情况,请确保硬件无变更,如果想更换序列号,请先删除 ~/.baidu/easyedge 目录,再重新激活。

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

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

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

    7. 运行NNIE引擎报错 std::bad_alloc

    检查开发板可用内存,一些比较大的网络占用内存较多,推荐内存500M以上

    8. 运行二进制时,提示 libverify.so cannot open shared object file

    可能cmake没有正确设置rpath, 可以设置LD_LIBRARY_PATH为sdk的lib文件夹后,再运行:

    LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../lib ./easyedge_demo

    9. 编译时报错:file format not recognized

    可能是因为在复制SDK时文件信息丢失。请将整个压缩包复制到目标设备中,再解压缩、编译

    上一篇
    Windows集成文档
    下一篇
    Linux集成文档-Python