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

Linux-Python-SDK

简介

本文档介绍Linux-Python版飞桨开源模型SDK的使用方法。

  • 硬件支持:

    • Linux x86_64 CPU
    • Linux x86_64 Nvidia GPU
    • Linux armv8 CPU
  • 语言支持:Python 3.5, 3.6, 3.7(ARM CPU暂支持Python3.6)

快速开始

文件结构说明

.EasyEdge-Linux-m43157-b97741-x86
├── RES  # 模型文件资源文件夹,可替换为其他模型
│   ├── conf.json
│   ├── label_list.txt
│   ├── model
│   ├── params
│   └── infer_cfg.json
├── ReadMe.txt
├── cpp  # C++ SDK
│   └── baidu_easyedge_linux_cpp_x86_64_CPU.Generic_gcc5.4_v1.4.0_20220325.tar.gz
└── python  # Python SDK
    ├── BaiduAI_EasyEdge_SDK-1.2.8-cp35-cp35m-linux_x86_64.whl
    ├── BaiduAI_EasyEdge_SDK-1.2.8-cp36-cp36m-linux_x86_64.whl
    ├── BaiduAI_EasyEdge_SDK-1.2.8-cp37-cp37m-linux_x86_64.whl
    ├── infer_demo
    │   ├──  demo_x86_cpu.py
    │   └──  demo_serving.py
    ├── tensor_demo
    │   └──  demo_x86_cpu.py

Python SDK文件结构如下:

python  # Linux x86_64 CPU Python SDK
    ├── BaiduAI_EasyEdge_SDK-1.2.8-cp35-cp35m-linux_x86_64.whl # EasyEdge Python Wheel 包, 二次开发可使用
    ├── BaiduAI_EasyEdge_SDK-1.2.8-cp36-cp36m-linux_x86_64.whl
    ├── BaiduAI_EasyEdge_SDK-1.2.8-cp37-cp37m-linux_x86_64.whl
    ├── infer_demo # demo体验完整文件
    │   ├──  demo_x86_cpu.py # 包含前后处理的端到端推理demo文件
    │   └──  demo_serving.py # 提供http服务的demo文件
    ├── tensor_demo # tensor in/out demo文件
    │   └──  demo_x86_cpu.py

安装依赖

安装paddlepaddle

x86_64 CPU 预测时安装:

python3 -m pip install paddlepaddle==2.2.2 -i https://mirror.baidu.com/pypi/simple 

x86_64 Nvidia GPU 预测时安装:

python3 -m pip install paddlepaddle-gpu==2.2.2.post101 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html # CUDA10.1的PaddlePaddle
python3 -m pip install paddlepaddle-gpu==2.2.2 -i https://mirror.baidu.com/pypi/simple # CUDA10.2的PaddlePaddle
python3 -m pip install paddlepaddle-gpu==2.2.2.post110 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html # CUDA11.0的PaddlePaddle
python3 -m pip install paddlepaddle-gpu==2.2.2.post111 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html # CUDA11.1的PaddlePaddle
python3 -m pip install paddlepaddle-gpu==2.2.2.post112 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html # CUDA11.2的PaddlePaddle

使用 NVIDIA GPU 预测时,必须满足:

  1. 机器已安装 cuda, cudnn
  2. 已正确安装对应 cuda 版本的paddle 版本
  3. 通过设置环境变量FLAGS_fraction_of_gpu_memory_to_use设置合理的初始内存使用比例

armv8 CPU预测时安装:

python3 -m pip install http://aipe-easyedge-public.bj.bcebos.com/easydeploy/paddlelite-2.11-cp36-cp36m-linux_aarch64.whl 

安装EasyEdge Python Wheel 包

x86_64 CPUx86_64 Nvidia GPU

python3 -m pip install -U BaiduAI_EasyEdge_SDK-{版本号}-cp36-cp36m-linux_x86_64.whl

armv8 CPU

python3 -m pip install -U BaiduAI_EasyEdge_SDK-{版本号}-cp36-cp36m-linux_aarch64.whl

具体名称以 SDK 包中的 whl 为准。

测试Demo

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

1. 预测图像

使用infer_demo文件夹下的demo文件

python3 demo_x86_cpu.py {模型RES文件夹}  {测试图片路径}

运行效果示例:

2. 启动HTTP预测服务

输入对应的模型文件夹(默认为RES)、序列号、设备ip和指定端口号,运行:

python3 demo_serving.py {模型RES文件夹} {serial_key} {host, default 0.0.0.0} {port, default 24401}

启动后,日志中会显示

HTTP is now serving at 0.0.0.0:24401

字样。此时,开发者可以打开浏览器,http://{设备ip}:24401,选择图片来进行测试。也可以参考demo_serving.pyhttp_client_test()函数请求http服务进行推理。

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

SDK二次开发使用说明

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

基础流程

❗注意,请优先参考SDK中自带demo的使用流程和说明。遇到错误,请优先参考文件中的注释、解释、日志说明。

infer_demo/demo_xx_xx.py

# 引入EasyEdge运行库
import BaiduAI.EasyEdge as edge

# 创建并初始化一个预测Progam;选择合适的引擎
pred = edge.Program()
pred.init(model_dir={RES文件夹路径}, device=edge.Device.CPU, engine=edge.Engine.PADDLE_FLUID) # x86_64 CPU
# pred.init(model_dir=_model_dir, device=edge.Device.GPU, engine=edge.Engine.PADDLE_FLUID) # x86_64 Nvidia GPU
# pred.init(model_dir=_model_dir, device=edge.Device.CPU, engine=edge.Engine.PADDLE_LITE) # armv8 CPU

# 预测图像
res = pred.infer_image({numpy.ndarray的图片})

# 关闭结束预测Progam
pred.close()

infer_demo/demo_serving.py

import BaiduAI.EasyEdge as edge
from BaiduAI.EasyEdge.serving import Serving

# 创建并初始化Http服务
server = Serving(model_dir={RES文件夹路径}, license=serial_key)

# 运行Http服务
# 请参考同级目录下demo_xx_xx.py里:
# pred.init(model_dir=xx, device=xx, engine=xx, device_id=xx)
# 对以下参数device\device_id和engine进行修改
server.run(host=host, port=port, device=edge.Device.CPU, engine=edge.Engine.PADDLE_FLUID) # x86_64 CPU
# server.run(host=host, port=port, device=edge.Device.GPU, engine=edge.Engine.PADDLE_FLUID) # x86_64 Nvidia GPU
# server.run(host=host, port=port, device=edge.Device.CPU, engine=edge.Engine.PADDLE_LITE) # armv8 CPU

初始化

  • 接口
    def init(self,
          model_dir,
          device=Device.CPU,
          engine=Engine.PADDLE_FLUID,
          config_file='conf.json',
          preprocess_file='preprocess_args.json',
          model_file='model',
          params_file='params',
          label_file='label_list.txt',
          infer_cfg_file='infer_cfg.json',
          device_id=0,
          thread_num=1
          ):
       """
       Args:
           model_dir: str
           device: BaiduAI.EasyEdge.Device,比如:Device.CPU
           engine: BaiduAI.EasyEdge.Engine, 比如: Engine.PADDLE_FLUID
           config_file: str
           preprocess_file: str
           model_file: str
           params_file: str
           label_file: str 标签文件
           infer_cfg_file: 包含预处理、后处理信息的文件
		device_id: int 设备ID
           thread_num: int CPU的线程数

       Raises:
           RuntimeError, IOError
       Returns:
           bool: True if success
       """

若返回不是True,请查看输出日志排查错误原因。

SDK参数配置

使用 CPU 预测时,可以通过在 init 中设置 thread_num 使用多线程预测。如:

pred.init(model_dir=_model_dir, device=edge.Device.CPU, engine=edge.Engine.PADDLE_FLUID, thread_num=4)

使用 GPU 预测时,可以通过在 init 中设置 device_id 指定需要的GPU device id。如:

pred.init(model_dir=_model_dir, device=edge.Device.GPU, engine=edge.Engine.PADDLE_FLUID, device_id=0)

预测图像

  • 接口
    def infer_image(self, img,
                   threshold=0.3,
                   channel_order='HWC',
                   color_format='BGR',
                   data_type='numpy'):
       """

       Args:
           img: np.ndarray or bytes
           threshold: float
               only return result with confidence larger than threshold
           channel_order: string
               channel order HWC or CHW
           color_format: string
               color format order RGB or BGR
           data_type: string
               仅在图像分割时有意义。 'numpy' or 'string'
               'numpy': 返回已解析的mask
               'string': 返回未解析的mask游程编码
           
       Returns:
           list

       """
  • 返回格式: [dict1, dict2, ...]
字段 类型 取值 说明
confidence float 0~1 分类或检测的置信度
label string 分类或检测的类别
index number 分类或检测的类别
x1, y1 float 0~1 物体检测,矩形的左上角坐标 (相对长宽的比例值)
x2, y2 float 0~1 物体检测,矩形的右下角坐标(相对长宽的比例值)
mask string/numpy.ndarray 图像分割的mask

关于矩形坐标

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

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

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

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

可以参考 demo 文件中使用 opencv 绘制矩形的逻辑。

结果示例

i) 图像分类

{
    "index": 736,
    "label": "table",
    "confidence": 0.9
}

ii) 物体检测

{
    "index": 8,
    "label": "cat",
    "confidence": 1.0,
    "x1": 0.21289,
    "y1": 0.12671,
    "x2": 0.91504,
    "y2": 0.91211,
}

iii) 图像分割

{
	"name": "cat",
    "score": 1.0,
    "location": {
    	"left": ..., 
    	"top": ..., 
    	"width": ...,
    	"height": ...,
    },
    "mask": ...
}

mask字段中,data_type为numpy时,返回图像掩码的二维数组

{
  {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代表非目标区域

data_type为string时,mask的游程编码,解析方式可参考 demo

TensorIn/Out 推理

TensorIn/Out 推理不会对输入数据做预处理、后处理,开发者一般使用普通推理接口即可。 流程参考:使用tensor_demo/demo_xx_xx.py

 fetch_tensors = pred.forward(feed_tensors)

日志配置

设置 EasyEdge Log。

import BaiduAI.EasyEdge as edge
import logging
edge.Log.set_level(logging.INFO)
# edge.Log.set_level(logging.DEBUG)

http服务

1. 开启http服务

http服务的启动使用demo_serving.py文件

class Serving(object):
    """
        SDK local serving
    """

    def __init__(self, model_dir, license='', model_filename='model', params_filename='params'):

        self.program = None
        self.model_dir = model_dir
        self.model_filename = model_filename
        self.params_filename = params_filename
        self.program_lock = threading.Lock()
        self.license_key = license
        # 只有ObjectTracking会初始化video_processor
        self.video_processor = None
    
     def run(self, host, port, device, engine=Engine.PADDLE_FLUID, service_id=0, device_id=0, **kwargs):
      """
          Args:
              host : str
              port : str
              device : BaiduAI.EasyEdge.Device,比如:Device.CPU
	          engine : BaiduAI.EasyEdge.Engine, 比如: Engine.PADDLE_FLUID
      """
        self.run_serving_with_flask(host, port, device, engine, service_id, device_id, **kwargs)

2. 请求http服务

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

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

URL中的get参数:

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

HTTP POST Body即为图片的二进制内容

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()

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,
            "mask": "...",  // 图像分割模型字段
            "trackId": 0,  // 目标追踪模型字段
        },
        
      ]
}

关于矩形坐标

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

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

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

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

关于分割模型

其中,mask为分割模型的游程编码,解析方式可参考 demo

模型替换说明

SDK中RES文件夹为模型文件夹,开发者可以按要求整理自定义模型的RES文件,运行时指定新的RES即可。

  • model: 模型网络结构文件,对应Paddle1.x的__model__,Paddle2.x的model.pdmodel
  • params: 模型网络参数文件,对应Paddle1.x的__params__,Paddle2.x的model.pdiparams
  • label_list.txt: label文件
  • infer_cfg.json:模型推理的预处理、后处理配置文件,具体说明如下

其中,非标记【必须】的可不填

{
    "version": 1,
    "model_info": { 
        "best_threshold": 0.3,   // 默认0.3
        "model_kind": 1, // 【必须】 1-分类,2-检测,6-实例分割,12-追踪,14-语义分割,401-人脸,402-姿态,10001-决策
    },
    "pre_process": { // 【必须】
        // 归一化, 预处理会把图像 (origin_img - mean) * scale 
        "skip_norm": false, // 默认为false, 如果设置为true,不做mean scale处理
        "mean": [123, 123, 123],  // 【必须】
        "scale": [0.017, 0.017, 0.017],  // 【必须】
        "color_format": "RGB", // BGR 【必须】
        "channel_order": "CHW", // HWC
        // 大小相关
        "resize": [300, 300],  // w, h 【必须】
        "rescale_mode": "keep_size", // 默认keep_size, keep_ratio, keep_ratio2, keep_raw_size, warp_affine
        "max_size": 1366, // keep_ratio 用。如果没有提供,则用 resize[0]
        "target_size": 800,  // keep_ratio 用。如果没有提供,则用 resize[1]
        "raw_size_range": [100, 10000], // keep_raw_size 用
        "warp_affine_keep_res": // warp_affine模式使用,默认为false
        "center_crop_size": [224, 224]// w, h, 如果需要做center_crop,则提供,否则,无需提供该字段
        "padding": false,
        "padding_mode": "padding_align32",  // 【非必须】默认padding_align32, 其他可指定:padding_fill_size
        "padding_fill_size": [416, 416], // 【非必须】仅padding_fill_size模式下需要提供, [fill_size_w, fill_size_h], 这里padding fill对齐paddle detection实现,在bottom和right方向实现补齐
        "padding_fill_value": [114, 114, 114] // 【非必须】仅padding_fill_size模式下需要提供
        // 其他
        "letterbox": true,
     },
    "post_process": {
        "box_normed": true, // 默认为true, 如果为false 则表示该模型的box坐标输出不是归一化的
    }
}

预处理的顺序如下:(没有的流程自动略过)

  1. 灰度图 -> rgb图变换
  2. resize 尺寸变换
  3. center_crop
  4. rgb/bgr变换
  5. padding_fill_size
  6. letterbox(画个厚边框,填上黑色)
  7. chw/hwc变换
  8. 归一化:mean, scale
  9. padding_align32

rescale_mode说明:

  • keep_size: 将图片缩放到resize指定的大小
  • keep_ratio:将图片按比例缩放,长边不超过max_size,短边不超过target_size
  • keep_raw_size:保持原图尺寸,但必须在raw_size_range之间
  • warp_affine: 仿射变换,可以设置warp_affine_keep_res指定是否keep_res,在keep_res为false场景下,宽高通过resize字段指定

FAQ

Q: 运行时报错 "非法指令" 或 " illegal instruction"

A: 可能是 CPU 缺少 avx 指令集支持,请在paddle官网下载 noavx 版本覆盖安装

Q: NVIDIA GPU预测时,报错显存不足:

A: 如以下错误字样:

paddle.fluid.core.EnforceNotMet: Enforce failed. Expected allocating <= available, but received allocating:20998686233 > available:19587333888.
Insufficient GPU memory to allocation. at [/paddle/paddle/fluid/platform/gpu_info.cc:170]

请在运行 Python 前设置环境变量,通过export FLAGS_fraction_of_gpu_memory_to_use=0.3来限制SDK初始使用的显存量,0.3表示初始使用30%的显存。如果设置的初始显存较小,SDK 会自动尝试 allocate 更多的显存。

Q: 我想使用多线程预测,怎么做?

A: 如果需要多线程预测,可以每个线程启动一个Progam实例,进行预测。 demo.py文件中有相关示例代码。

注意: 对于CPU预测,SDK内部是可以使用多线程,最大化硬件利用率。参考init的thread_num参数。

Q: 在armv8 CPU上执行python demo脚本报错:"Illegal instruction(core dumped) error"

A: 在运行python demo脚本前, export OPENBLAS_CORETYPE=ARMV8

上一篇
Linux-CPP-SDK
下一篇
Windows-SDK