上云无忧 > 文档中心 > 百度智能云飞桨EasyDL零门槛AI开发平台桌面版 - Linux集成文档-C++
飞桨EasyDL零门槛AI开发平台
百度智能云飞桨EasyDL零门槛AI开发平台桌面版 - Linux集成文档-C++

文档简介:
本文档介绍EasyEdge/EasyDL的Linux CPP SDK的使用方法。 网络类型支持: - 图像分类 - 物体检测。 硬件支持: CPU: aarch64 armv7hf。 操作系统支持: Linux (Ubuntu, Centos, Debian等)。 海思HiLinux。 树莓派Raspbian/Debian。 瑞芯微Firefly。
*此产品及展示信息均由百度智能云官方提供。免费试用 咨询热线:400-826-7010,为您提供专业的售前咨询,让您快速了解云产品,助您轻松上云! 微信咨询
  免费试用、价格特惠

简介

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

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

    • CPU: aarch64 armv7hf
  • 操作系统支持:

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

Release Notes

时间 版本 说明
2021.8.23 1.0.0 第一版!

快速开始

安装依赖

依赖包括

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

依赖说明:树莓派

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

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

getconf LONG_BIT
32

测试Demo

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

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

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

对于硬件使用为: -Intel Movidius MyRIAD2 / MyRIAD X on Linux x86_64 / armv7hf / aarch64,在编译或运行demo程序前执行以下命令: source ${cpp_kit位置路径}/thirdparty/openvino/bin/setupvars.sh

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

编译运行:

cd src mkdir build && cd build
cmake .. && make ./easyedge_image_inference {模型RES文件夹} {测试图片路径}

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

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

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

对于硬件使用为Intel Movidius MyRIAD2 / MyRIAD X 的,如果宿主机找不到神经计算棒Intel® Neural Compute Stick,需要执行以下命令添加USB Rules:

cp ${cpp_kit位置路径}/thirdparty/openvino/deployment_tools/inference_engine/external/
97-myriad-usbboot.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger
sudo ldconfig

demo运行效果:

> ./easyedge_image_inference ../../../../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); 
// 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中开启配置 }

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

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

SDK参数配置

SDK的参数通过EdgePredictorConfig::set_config和global_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绘制的逻辑进行解析

预测视频

SDK 提供了支持摄像头读取、视频文件和网络视频流的解析工具类VideoDecoding,此类提供了获取视频帧数据的便利函数。通过VideoConfig结构体可以控制视频/摄像头的解析策略、抽帧策略、分辨率调整、结果视频存储等功能。对于抽取到的视频帧可以直接作为SDK infer 接口的参数进行预测。

  • 接口

classVideoDecoding:

/**
     * @brief 获取输入源的下一帧
     * @param frame_tensor
     * @return
     */
    virtual int next(FrameTensor &frame_tensor) = 0;

    /**
     * @brief 显示当前frame_tensor中的视频帧
     * @param frame_tensor
     * @return
     */
    virtual int display(const FrameTensor &frame_tensor) = 0;

    /**
     * @brief 将当前frame_tensor中的视频帧写为本地视频文件
     * @param frame_tensor
     * @return
     */
    virtual int save(FrameTensor &frame_tensor) = 0;

    /**
     * @brief 获取视频的fps属性
     * @return
     */
    virtual int get_fps() = 0;
     /**
      * @brief 获取视频的width属性
      * @return
      */
    virtual int get_width() = 0;

    /**
     * @brief 获取视频的height属性
     * @return
     */
    virtual int get_height() = 0;

struct VideoConfig

/**
 * @brief 视频源、抽帧策略、存储策略的设置选项
 */
struct VideoConfig {
    SourceType source_type;            // 输入源类型
    std::string source_value;          // 输入源地址,如视频文件路径、摄像头index、网络流地址
    int skip_frames{0};                // 设置跳帧,每隔skip_frames帧抽取一帧,并把该抽取帧的is_needed置为true
    int retrieve_all{false};           // 是否抽取所有frame以便于作为显示和存储,对于不满足skip_frames策略的frame,
把所抽取帧的is_needed置为false
    int input_fps{0};                  // 在采取抽帧之前设置视频的fps
    Resolution resolution{Resolution::kAuto}; // 采样分辨率,只对camera有效

    bool enable_display{false};
    std::string window_name{"EasyEdge"};
    bool display_all{false};           // 是否显示所有frame,若为false,仅显示根据skip_frames抽取的frame

    bool enable_save{false};
    std::string save_path;             // frame存储为视频文件的路径
    bool save_all{false};              // 是否存储所有frame,若为false,仅存储根据skip_frames抽取的frame

    std::map<std::string, std::string> conf;
};

  • source_type:输入源类型,支持视频文件、摄像头、网络视频流三种,值分别为1、2、3。
  • source_value: 若source_type为视频文件,该值为指向视频文件的完整路径;若source_type为摄像头,该值为摄像头的index,如对于/dev/video0的摄像头,则index为0;若source_type为网络视频流,则为该视频流的完整地址。
  • skip_frames:设置跳帧,每隔skip_frames帧抽取一帧,并把该抽取帧的is_needed置为true,标记为is_needed的帧是用来做预测的帧。反之,直接跳过该帧,不经过预测。
  • retrieve_all:若置该项为true,则无论是否设置跳帧,所有的帧都会被抽取返回,以作为显示或存储用。
  • input_fps:用于抽帧前设置fps。
  • resolution:设置摄像头采样的分辨率,其值请参考easyedge_video.h中的定义,注意该分辨率调整仅对输入源为摄像头时有效。
  • conf:高级选项。部分配置会通过该map来设置。

注意

1.如果使用VideoConfig的display功能,需要自行编译带有GTK选项的opencv,默认打包的opencv不包含此项。

2.使用摄像头抽帧时,如果通过resolution设置了分辨率调整,但是不起作用,请添加如下选项:

video_config.conf["backend"] = "2";

3.部分设备上的CSI摄像头尚未兼容,如遇到问题,可以通过工单、QQ交流群或微信交流群反馈。

具体接口调用流程,可以参考SDK中的demo_video_inference。

日志配置

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

其他配置

日志名称、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。

示例一:libverify.so.1: cannot open shared object file: No such file or directory 链接找不到libveirfy.so文件,一般可通过 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:../../lib 解决(实际冒号后面添加的路径以libverify.so文件所在的路径为准)

示例二:libopencv_videoio.so.4.5: cannot open shared object file: No such file or directory 链接找不到libopencv_videoio.so文件,一般可通过 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:../../thirdparty/opencv/lib 解决(实际冒号后面添加的路径以libopencv_videoio.so所在路径为准)

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

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

3. 运行NNIE引擎报permission denied

日志显示:

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

请使用sudo在root下运行。

4. 运行SDK报错 Authorization failed

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

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

export HTTP_PROXY="http://192.168.1.100:8888" ./easyedge_demo ...
  1. 情况二:日志显示failed to get/check device id(xxx)或者Device fingerprint mismatch(xxx) 此类情况一般是设备指纹发生了变更,包括(但不局限于)以下可能的情况:
  • MAC地址变化
  • 磁盘变更
  • BIOS重刷

以及系统相关信息。

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

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

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

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

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

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

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

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

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

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

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

相似文档
  • 本文档介绍Windows CPU SDK的使用方法。 网络类型支持:图像分类,物体检测。 硬件支持: Intel CPU * x86_64。 操作系统支持: 64位 Windows 7 及以上。 环境依赖(必须安装以下版本): .NET Framework 4.5。 Visual C++ Redistributable Packages for Visual Studio 2013。 Visual C++ Redistributable Packages for Visual Studio 2015。
  • 本文档主要说明定制化模型发布后获得的SDK如何使用,如有疑问可以通过以下方式联系我们: 在百度智能云控制台内提交工单。 前往官方论坛交流,与其他开发者进行互动。 SDK说明: SDK支持iOS、Android、Linux、Windows四种操作系统。以下为具体的系统、硬件环境支持:
  • Q:如果使用GPU环境进行训练? A:如果您的计算机有NVIDIA® GPU,且需要使用GPU环境进行训练,请确保满足以下条件: Windows 7/8/10/11: 需安装 CUDA 11.2 与 cuDNN v8.2.1。 Ubuntu 16.04/18.4/20.4: 需 CUDA 11.2 与 cuDNN v8.1.1。 CentOS 7: 需 CUDA 11.2 与 cuDNN v8.1.1。
  • 本文将会引导您将定制化模型售卖至AI市场中,具体的介绍与操作流程,您可以详细查看如下流程。 售卖市场介绍。 模型售卖的准备工作。 模型售卖的具体流程。 售卖市场介绍 : 您在EasyDL定制化训练出的模型可以在百度AI市场(aim.baidu.com ) 进行售卖。
  • 本文将会引导您将定制化API服务售卖至AI市场中,从而快速获得品牌曝光,并获得丰厚收入。接下来,您将了解如下内容: 售卖市场介绍。 API服务售卖的准备工作。 API服务售卖的具体流程。 售卖市场介绍: 您在EasyDL定制化训练出的模型可以在百度AI市场(aim.baidu.com) 进行售卖。
官方微信
联系客服
400-826-7010
7x24小时客服热线
分享
  • QQ好友
  • QQ空间
  • 微信
  • 微博
返回顶部