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

BML模型部署

BML模型部署

专项适配模型训练
专项适配模型发布
专项适配模型获取
专项适配模型部署
接口使用说明
http服务
其他配置
BML_SDK自动加载

BML 全功能AI开发平台是一个面向企业和个人开发者的机器学习集成开发环境,提供兼具效果与性能的卓越AI开发体验,有高性能的算力支持、强大的数据处理服务、高精度训练效果、丰富完善的开发方案、广泛适配的模型推理服务、全面丰富的交付方案诸多优势,为经典机器学习和深度学习提供了从数据处理、模型训练、模型管理到模型推理的全生命周期管理服务,帮助用户更快的构建、训练和部署模型。与EdgeBoard合作推出软硬一体方案。将EdgeBoard与BML模型深度适配,可应用于工业分拣、视频监控等多种设备端离线计算场景,让离线AI落地更轻松。

BML全功能开发平台主页:https://ai.baidu.com/bml/

BML使用文档请参考:https://ai.baidu.com/ai-doc/BML/Ekhvg0smz

BML中适用于Edgeboard的模型请参考:https://ai.baidu.com/bml/app/adapt?templateType=undefined&soc=edgeboard

专项适配模型训练

在模型训练时,新建任务后,在配置网络阶段,选择网络板块需选择Edgeboard支持的模型,在发布阶段才能发布适用于Edgeboard的SDK。

image-20210420144457310

专项适配模型发布

  • 发布模型

模型训练完成后,点击发布

  • 进入模型部署-EasyEdge本地部署,发布新服务

  • 在发布新服务页面,部署方式选择专项适配硬件,操作系统与硬件芯片选择Linux-Edgeboard(FZ),然后开始部署,等待部署完成。

专项适配模型获取

下载专用SDK

发布新服务后,点击服务详情,下载专用SDK。

获取专用序列号

EasyDL SDK需要专用序列号激活才可使用,并且购买账户需要和训练模型账户保持一致,序列号才可以顺利激活SDK。序列号获取方式有如下几种:

  • 从专项适配硬件详情页获取

如上图下载SDK页面,进入获取序列号。

  • 从订单中获取

用户可以通过AI市场订单详情查看对应版本的专项硬件适配服务,如下图所示:

img

如果连接中没有专用序列号,还请确认订单是否为EdgeBoard&EasyDL软硬一体方案,以及购买账户和模型训练账户是否是同一个。

  • 序列号购买和申请

如果获取序列号页面没有可用的序列号,可以进入百度智能云-BML全功能AI开发平台-专项硬件适配服务,购买永久授权序列号或者申请测试序列号。

在更换序列号、更换设备时,首次使用专项硬件SDK需要联网激活。激活成功之后,有效期内可离线使用。


专项适配模型部署

开发者从EasyDL训练模型之后,下载的SDK中,包含了简单易用的Demo和http服务接口。只需简单的几个步骤,即可快速部署运行EdgeBoard。

部署包中包含多版本SDK:

  • baidu*easyedge_linux_cpp_aarch64_EdgeBoardFZ1.5**:适用于EdgeBoard 1.8+内核
  • baidu*easyedge_linux_cpp_aarch64_EdgeBoardFZ1.4**:适用于EdgeBoard 1.4+内核

SDK文件结构如下:

EasyEdge-Linux-m43725-b121612-edgeboard/
├── RES #模型文件
│   ├── conf.json
│   ├── label_list.txt
│   ├── model
│   ├── params
│   └── preprocess_args.json
├── cpp 
│   ├── baidu_easyedge_linux_cpp_aarch64_EdgeBoardFZ1.4_gcc7.5_v1.3.0_20210602.zip
│   └── baidu_easyedge_linux_cpp_aarch64_EdgeBoardFZ1.5_gcc7.5_v1.3.0_20210602
│       ├── bin #demo可执行文件
│       ├── include #头文件
│       │   └── easyedge
│       ├── lib #动态库
│       ├── src #demo源文件
│       │   ├── CMakeLists.txt
│       │   ├── cmake
│       │   ├── common
│       │   ├── demo_image_inference #图像推理demo
│       │   ├── demo_serving #http服务demo
│       │   └── demo_video_inference #视频推理demo
│       └── thirdparty 
│           └── opencv

EdgeBoard环境搭建

  • 登录Edgeboard系统
  • 加载驱动,系统启动后加载一次即可(系统默认已自启动,此步骤可省略)

    insmod /home/root/workspace/driver/fpgadrv.ko

    若未加载驱动,可能报错:

    	Failed to to fpga device: -1
  • 设置系统时间(系统时间必须正确)

    date --set "2020-5-18 20:48:00"
  • 首次使用,需要联网激活SDK,激活成功之后,有效期内可离线使用
  • 设置EdgeBoard能够联网,参照连接外网方式

运行SDK

SDK激活方式是在联网状态下执行模型推理程序,激活后可以离线推理,运行SDK的方式可参考下文。

  • 解压

    请先将tar包整体拷贝到具体运行的设备中,再解压缩编译。

比如将SDK放到EdgeBoard的/home/root/目录,使用unzip以及tar命令解压zip包和tar.gz文件,

# 解压sdk
unzip EasyEdge-Linux-m8105-b33878-edgeboard.zip
# 解压tar.gz
cd cpp
tar xvf baidu_easyedge_linux_cpp_aarch64_EdgeBoardFZ1.5_gcc7.5_v1.2.2_20210412.tar.gz

  • 运行方式一

SDK中已经包含预先编译的二进制,如 bin/easyedge_image_inference, bin/easyedge_serving,配置LD_LIBRARY_PATH后,可直接运行:

# 设置LD_LIBRARY_PATH为SDK部署包中的lib目录
LD_LIBRARY_PATH=../lib 
# 执行easyedge_serving {RES资源文件夹路径} {序列号}
./bin/easyedge_serving  ../../../RES/ "1111-1111-1111-1111"
  • 运行方式二

    src编译

    #进入src目录,
    cd src
    mkdir build #创建build文件夹
    cd build #打开build文件夹
    rm -rf * #清空build文件夹
    cmake .. #调用cmake 创建Makefile
    make #编译工程

编译完成后,build文件夹下会产生demo_image_inference、demo_serving、demo_video_inference三个装有对应可执行文件的文件夹,进入对应文件夹目录,执行相应的功能,执行成功任意一个demo,就可以激活成功。

运行demo_image_inference

运行demo_image_inference前,需要提前拷贝一张测试图片到Edgeboard上,比如放到easydl sdk中的RES目录。

# 进入build文件夹
cd /home/root/cpp/baidu_easyedge_linux_cpp_aarch64_EdgeBoardFZ1.5_gcc7.5_v1.2.2_20210412/src/build/demo_image_inference
# 设置LD_LIBRARY_PATH为SDK部署包中的lib目录
export LD_LIBRARY_PATH=../../lib
# 执行easyedge_image_inference {RES资源文件夹路径} {测试图片路径} {序列号}
./easyedge_image_inference ../../../../../RES/ ../../../../../RES/1.jpeg "1111-1111-1111-1111"

打印信息中显示出预测结果,证明推理成功,首次执行也就激活成功。

运行demo_serving

SDK包含http服务功能

# 进入build文件夹
cd /home/root/cpp/baidu_easyedge_linux_cpp_aarch64_EdgeBoardFZ1.5_gcc7.5_v1.2.2_20210412/src/build/demo_serving
# ./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://{EdgeBoard计算盒ip地址}:24401/,例如:http://192.168.1.254:24401 ,在h5中测试模型效果。

img

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

运行demo_video_inference

SDK包含视频推理的demo,执行结果会以视频存储的方式将预测出的视频帧保存成build目录下的0.result.mp4文件。

# 进入build文件夹
cd /home/root/cpp/baidu_easyedge_linux_cpp_aarch64_EdgeBoardFZ1.5_gcc7.5_v1.2.2_20210412/src/build/demo_video_inference
# 执行方式:easyedge_image_inference {RES_dir} {video_type} {video_src} {serial_rum}
./easyedge_video_inference ../../../../../RES/ 1 /home/root/video.mp4 "1111-1111-1111-1111"

easyedge_image_inference参数定义:

RES_dir :模型存放目录

video-type:视频类型,1表示本地视频,视频位置写本地视频位置;2表示使用摄像头输入,目前只支持usb免驱摄像头,视频位置写摄像头的index,可在系统中执行ls /dev/video*查看插入的摄像头index,如果是/dev/video2,则视频位置写2。

video_src:视频位置,如果视频类型为1,写本地视频视频位置;如果视频类型为2,写摄像头index。

serial_rum:序列号,如果设备已激活,该参数可选。

注意: demo_video_inference功能暂不支持display,不支持接入minidp显示器实时显示。

接口使用说明

使用流程:

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

    // step 1: 配置模型资源目录
    EdgePredictorConfig config;
    config.model_dir = {模型文件目录};
    
    // step 2: 创建并初始化Predictor;在这里选择合适的引擎
    auto predictor = global_controller()->CreateEdgePredictor(config);


    // step 3-1: 预测图像
    auto img = cv::imread({图片路径});
    std::vector<EdgeResultData> results;
    predictor->infer(img, results);
	
	// step 3-2: 预测视频
	std::vector<EdgeResultData> results;
	FrameTensor frame_tensor;
    VideoConfig video_config;
    video_config.source_type = static_cast<SourceType>(video_type);  // source_type 定义参考头文件 easyedge_video.h
    video_config.source_value = video_src;
    /*
    ... more video_configs, 根据需要配置video_config的各选项
    */
    auto video_decoding = CreateVideoDecoding(video_config);
    while (video_decoding->next(frame_tensor) == EDGE_OK) {
        results.clear();
        if (frame_tensor.is_needed) {
            predictor->infer(frame_tensor.frame, results);
            render(frame_tensor.frame, results, predictor->model_info().kind);
        }
        //video_decoding->display(frame_tensor); // 显示当前frame,需在video_config中开启配置
        //video_decoding->save(frame_tensor); // 存储当前frame到视频,需在video_config中开启配置
    }

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");

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

相关配置均可以通过环境变量的方法来设置,对应的key名称加上前缀EDGE_即为环境变量的key。如序列号配置的环境变量key为EDGE_PREDICTOR_KEY_SERIAL_NUM,如指定CPU线程数的环境变量key为EDGE_PREDICTOR_KEY_CPU_THREADS_NUM。 注意:通过代码设置的配置会覆盖通过环境变量设置的值。

初始化

  • 接口
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;

 /**
  * @brief
  * GPU加速版批量图片推理接口
  * @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>>& 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的长宽比例值。

    // 图像分割的模型,该字段才有意义
    // 请注意:图像分割时,以下两个字段会比较大,使用完成之后请及时释放EdgeResultData
    cv::Mat mask;  // 0, 1 的mask
    std::string mask_rle;  // Run Length Encoding,游程编码的mask

    // 目标追踪模型,该字段才有意义
    int trackid;  // 轨迹id
    int frame;  // 处于视频中的第几帧
    EdgeTrackStat track_stat;  // 跟踪状态
};

*关于矩形坐标*

x1 * 图片宽度 = 检测框的左上角的横坐标

y1 * 图片高度 = 检测框的左上角的纵坐标

x2 * 图片宽度 = 检测框的右下角的横坐标

y2 * 图片高度 = 检测框的右下角的纵坐标

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 - 默认为推荐阈值,也可自行根据需要进行设置

3. 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::CONTROLLER_KEY_LOG_BRAND, "MY_BRAND");

效果如下: 图片

2. CPU线程数设置

CPU线程数可通过 EdgePredictorConfig::set_config配置

EdgePredictorConfig config;
config.set_config(easyedge::params::PREDICTOR_KEY_CPU_THREADS_NUM, 4);

BML_SDK自动加载

BML SDK与EasyDL SDK在Edgeboard上自动加载方式相同,如需开机自启SDK,可参考设置程序开机自启动中的『EasyDL sdk自动加载』部分。

上一篇
EasyDL模型部署
下一篇
PaddlePaddle模型部署