C++示例
-
1.2 detection示例目录结构
- 连接设备
-
3.1 本地图片预测
3.2 USB摄像头视频预测
- C++接口调用
示例介绍
本示例是通过调用paddlelite预测库实现模型的快速部署,用户可以通过示例掌握EdgeBoard软核基本框架以及EdgeBoard中模型部署的基本流程,以及在示例中运行自己的模型,实现模型快速部署,加速项目落地,PaddleLiteSample工程路径为:home/root/workspace/PaddleLiteSample
,考虑到简单通用性,EdgeBoard示例运行方法基本统一,示例工程内有两个文件夹,classification工程用于部署图像分类模型,detection工程用于部署物体检测模型,且为每个模型提供了配置文件(json文件),部署模型时需从配置文件中读取模型和图片信息,加载并执行。
系统包含的示例列表如下:
示例名称 | 说明 |
---|---|
classification | 图像分类模型示例工程,可以实现图片预测和usb摄像头视频预测 |
detection | 物体检测模型示例工程,可以实现图片预测和usb摄像头视频预测 |
示例工程目录结构
classification示例目录结构
├── CMakeLists.txt // cmake 工程配置文件。
├── include //头文件
| ├── commom.h
├── configs // 配置文件目录
│ ├── Inceptionv2
│ │ └─ zebra.json //Inceptionv2配置文件(万分类-预置斑马识别)
│ ├── Inceptionv3
│ │ └─ zebra.json //Inceptionv3配置文件(千分类-预置斑马识别)
│ ├── mobilenetv1
│ │ └─ zebra.json //mobilenetv1配置文件(千分类-预置斑马识别)
│ └── resnet50
│ └─ drink.json //resnet50配置文件(三分类-预置矿泉水识别)
├── lib //(动态库放入系统内/usr/local/lib/paddle_lite/目录,此处为空文件夹)
├── models // 模型文件目录
│ ├── Inceptionv2
│ ├── Inceptionv3
│ ├── mobilenetv1
│ └── resnet50
│── src
│ ├── json.hpp // json 解析库
│ ├── video_detection.cpp // 视频推理示例
| ├── image_detection.cpp // 图片推理示例
└── README.md
detection示例目录结构
├── CMakeLists.txt // cmake 工程配置文件。
├── include //头文件
| ├── commom.h
├── configs // 配置文件目录
│ ├── mobilenet-ssd
│ │ └─ screw.json //mobilenetssd_300配置文件(螺丝螺母检测)
│ ├── mobilenet-ssd-640
│ │ └─ screw.json //mobilenetssd_640配置文件(螺丝螺母检测)
│ └── vgg-ssd
│ | └─ screw.json //vggssd_300配置文件(螺丝螺母检测)
│ └── yolov3
│ └─ screw.json //yolov3_608配置文件(螺丝螺母检测)
|
├── lib //动态库放入系统内/usr/local/lib/paddle_lite/目录,此处为空文件夹
|
├── models // 模型文件目录
│ ├── mobilenet-ssd
│ ├── mobilenet-ssd-640
│ ├── vgg-ssd
│ └── yolov3
│── src
│ ├── json.hpp // json 解析库
│ ├── video_detection.cpp // 视频推理示例
| ├── image_detection.cpp // 图片推理示例
└── README.md
运行示例
考虑到简单通用性,EdgeBoard示例运行方法基本统一,即为每个模型提供配置文件(json文件),从配置文件中读取模型和图片信息,加载并执行。每个实例工程内有对应的配置文件目录,所以运行示例时需要指定相应的配置文件。
配置文件内容示例
{
"model":"../models/yolov3",
"combined_model":true,
"video_device":"/dev/video0",
"input_width":608,
"input_height":608,
"image":"../models/yolov3/1.jpg",
"mean":[123.675, 116.28, 103.53],
"scale":[0.0171248, 0.017507, 0.0174292],
"format":"RGB",
"threshold":0.3,
"network_type":"YOLOV3"
}
配置文件参数说明
key | value |
---|---|
model | 模型目录存放的位置 |
combined_model | 是否为融合的模型,只有两个文件的是融合模型 |
video_device | usb摄像头识别到的设备节点 |
input_width | 输入网络的图片尺寸 输入图片会缩放到该大小 |
input_height | 输入网络的图片尺寸 |
image | 进行检测的图片输入 |
mean | 平均值 |
scale | 输入网络前预算处理为 ( x - mean ) * scale |
format | 网络所需要的格式,OpenCV默认是BGR |
threshold | 阈值 |
network_type | 神经网络类型 |
本地图片预测
图片预测的步骤如下:
1、连接设备
2、加载驱动,系统启动后加载一次即可(系统默认已自启动,此步骤可省略)
3、编译示例
4、执行图片预测可执行文件
classification模型本地图片预测
classification模型本地图片预测步骤如下:
1、连接设备
2、加载驱动,系统启动后加载一次即可(系统默认已自启动,此步骤可省略)
insmod /home/root/workspace/driver/fpgadrv.ko
3、进入classification示例工程,编译示例
//进入classification工程目录
cd /home/root/workspace/PaddleLiteSample/classification
// 如果没有build目录,创建一个
mkdir build
//打开build目录
cd build
// 调用cmake 创建 Makefile
cmake ..
// 编译工程。
make
编译完成,build目录下会生成如下几个文件:
image_classify 读取本地图片推理示例
video_classify 读取摄像头数据进行推理,要连接USB Camera才能使用。如需显示结果还要连接DP显示器或者HDMI显示器或者VGA显示器等。
注意:使用系统自带的PaddleLiteSample,已默认编译,用户可直接进入build目录使用对应的可执行文件
4、执行示例
cd /home/root/workspace/PaddleLiteSample/classification/build
./image_classify {json文件路径}
例如:
调用resnet模型进行图片预测
./image_classify ../configs/resnet50/drink.json
执行结果:
detection模型本地图片预测
detection模型本地图片预测步骤如下:
1、连接设备
2、加载驱动,系统启动后加载一次即可(系统默认已自启动,此步骤可省略)
insmod /home/root/workspace/driver/fpgadrv.ko
3、进入示例工程,编译示例
//进入yolov3工程目录
cd /home/root/workspace/PaddleLiteSample/detection
// 如果没有build目录,创建一个
mkdir build
//打开build目录
cd build
// 调用cmake 创建 Makefile
cmake ..
// 编译工程。
make
4、执行示例
cd /home/root/workspace/PaddleLiteSample/detection/build
./image_detect {json文件路径}
例如:
调用yolov3模型进行图片预测
./image_detect ../config/yolov3/screw.json
执行结果:
结果图片:
USB摄像头视频预测
使用USB摄像头预测步骤如下:
1、USB摄像头和显示器连接EdgeBoard,USB摄像头和显示器注意事项请参考视频输入和输出
2、连接设备
3、系统启动后,进入系统命令窗口,打开显示器桌面
//打开显示器命令
startx
4、加载驱动,系统启动后加载一次即可(系统默认已自启动,此步骤可省略)
insmod /home/root/workspace/driver/fpgadrv.ko
5、编译示例(如在图片预测时已全部编译,可忽略)
6、运行示例
图片分类模型视频预测:
cd /home/root/workspace/PaddleLiteSample/classification/build
./video_classify {json文件路径}
例如:调用resnet50模型进行视频预测
./video_classify ../configs/resnet50/drink.json
物体检测模型视频预测:
cd /home/root/workspace/PaddleLiteSample/detection/build
./video_detection {json文件路径}
例如:调用yolov3模型进行视频预测
./video_detection ../configs/yolov3/screw.json
网络摄像头视频预测(仅FZ9D适用)
目前仅FZ9D设备,出厂自带了网络摄像头视频预测示例,其他型号请使用usb摄像头进行视频预测
FZ9D自带的demo示例与其他型号略有不同,除支持usb摄像头输入外,还支持网络摄像头的视频输入和HDMI视频输入
FZ9D 示例工程目录结构如下:
├── PaddleLiteSample。
| ├── ip_camera //网络摄像头视频预测目录
│ | ├──classification //分类模型预测
│ | ├──detection //检测模型预测
│ | └─ tool //HI3536配置工具
│ | ├──video_ctl //HI3536配置程序可执行文件
│ | └─-configs //HI3516配置文件
| ├── usb_camera //usb摄像头视频预测目录
│ ├──classification
│ └──detection
由于FZ9D使用网络摄像头需要经过hi3536解码,所以需要通过主芯片zu9配置hi3536与网络摄像头的参数,使用tool工具可灵活配置其相关参数,configs/video.json配置文件如下:
configs/video.json
{
"cmd":[
{"FormatResolution":"<out-0:1920x1080@30,yuv422>"},
{"SplitWindow":"<div-0:1>"},
{"netWork":"<mac:23:50:95:da:65:ee,ip:192.168.1.101,netmask:255.255.255.0,gw:192.168.1.1>"},
{"videoSource":"<win-101:rtsp://admin:eb123456@192.168.1.64/>"}
]
}
video.json参数 | 值 |
---|---|
FormatResolution | 设置分辨率和色彩空间(暂不支持其他值) |
SplitWindow | 设置分屏(暂不支持其他值) |
netWork | 设置hi3536的mac和ip地址等网络参数 |
videoSource | 设置网络摄像头的rtsp视频流地址 |
操作步骤:
-
首次使用
- 连接网络摄像头和3536网口(H-ETH)在同一个局域网下;
- 进入FZ9D系统,初次使用或网络发生变化时需要修改HI3536的配置文件(文件路径
/home/root/workspace/PaddleLiteSample/ip_camera/tool/configs/video.json
),修改完成后在tool路径下执行./video_ctl
,程序会自动将configs/video.json中的命令发送给hi3536; - 然后接上显示器,打开显示器桌面,执行视频预测程序
- 后续使用,无需修改hi3536配置,可直接接入配置好的摄像头进行视频分析
图像分类模型调用示例
startx //打开显示器桌面
cd /home/root/workspace/PaddleLiteSample/ip_camera/classificaion/build //进入可执行文件目录
./video_classification ../config/Inceptionv3/zebra.json //执行Inceptionv3模型视频预测程序
目标检测模型调用示例
startx //打开显示器桌面
cd /home/root/workspace/PaddleLiteSample/ip_camera/detection/build //进入可执行文件目录
./video_detection ../config/yolov3/screw.json //执行yolov3模型视频预测程序
HDMI输入视频预测(仅FZ9D适用)
FZ9D接入HDMI视频源后,通过hi3536解码,再进入fpga中进行图像分析,示例工程与网络摄像头工程相同
操作步骤:
1、修改自启动脚本/etc/init.d/eb.sh
,将hdmi驱动hdmi_b.out改为hdmi_a.out,并重启设备
# HDMI chip burn
cd /home/root/workspace/firmware/
chmod +x hdmi_a.out
./hdmi_a.out
2、连接HDMI视频源设备和FZ9D,同时FZ9D连接显示器
3、执行视频预测程序
图像分类模型调用示例
startx //打开显示器桌面
cd /home/root/workspace/PaddleLiteSample/ip_camera/classificaion/build //进入可执行文件目录
./video_classification ../config/Inceptionv3/zebra.json //执行Inceptionv3模型视频预测程序
目标检测模型调用示例
startx //打开显示器桌面
cd /home/root/workspace/PaddleLiteSample/ip_camera/detection/build //进入可执行文件目录
./video_detection ../config/yolov3/screw.json //执行yolov3模型视频预测程序
C++接口调用
具体详情请查看API文档 C++接口文档
C++ API
CreatePaddlePredictor
template <typename ConfigT>
std::shared_ptr<PaddlePredictor> CreatePaddlePredictor(const ConfigT&);
CreatePaddlePredictor用来根据CxxConfig构建预测器。
示例:
CxxConfig
class CxxConfig;
CxxConfig用来配置构建CxxPredictor的配置信息,如protobuf格式的模型地址、能耗模式、工作线程数、place信息等等。
示例:
//构造places, FPGA使用以下几个places。
std::vector<Place> valid_places({
Place{TARGET(kFPGA), PRECISION(kFP16), DATALAYOUT(kNHWC)},
Place{TARGET(kHost), PRECISION(kFloat)},
Place{TARGET(kARM), PRECISION(kFloat)},
});
//构造模型加载参数
paddle::lite_api::CxxConfig config;
std::string model = value["model"];
bool combined = true;
std::string model_dir = model;
if (combined) {
//设置组合模型路径(两个文件)
config.set_model_file(model_dir + "/model");
config.set_param_file(model_dir + "/params");
} else {
//设置模型目录路径,适用于一堆文件的模型
config.set_model_dir(model_dir);
}
config.set_valid_places(valid_places);
// 创建PaddleLite实例
auto predictor = paddle::lite_api::CreatePaddlePredictor(config);
PaddlePredictor
PaddlePredictor是Paddle-Lite的预测器,由CreatePaddlePredictor根据CxxConfig进行创建。用户可以根据PaddlePredictor提供的接口设置输入数据、执行模型预测、获取输出以及获得当前使用lib的版本信息等。
//获取第0个输入tensor,有多个输入时,可根据相应下标获取
auto input = predictor->GetInput(0);
//调整输入大小
input->Resize({1, 3, height, width});
//获取tensor数据指针
auto* in_data = input->mutable_data<float>();
//图片读入相应数组当中
read_image(value, in_data);
//推理
predictor->Run();
//获取结果tensor,有多个结果时,可根据相应下标获取
auto output = predictor->GetOutput(0);
//获取结果数据
float *data = output->mutable_data<float>();
Tensor
Tensor是Paddle-Lite的数据组织形式,用于对底层数据进行封装并提供接口对数据进行操作,包括设置Shape、数据、LoD信息等。
注意:用户应使用PaddlePredictor的GetInput和GetOuput接口获取输入/输出的Tensor。
// 通过调用Resize调整Tensor纬度
input->Resize({1, 3, height, width})
//通过SetLoD设置lod信息。
input->SetLod(lod);
//-----------------------------------------
// 获取数出tensor
auto output = predictor->GetOutput(0);
//获取结果数据
float *data = output->mutable_data<float>();
//tensor->shape()返回Tensor维度信息。
int size = output->shape()[0];