ModelBox开发体验Day03之应用开发初体验
- 上一节实践进行了开发板系统安装和开发环境配置,本节主要进行简单的应用开发实践
- 实践代码:https://github.com/sunxiaobei/modelbox_gallery
开发准备
前置
- 安装VS Code,Remote-SSH插件
安装HiLens Agent
- 在HiLens管理控制台专业版的设备管理板块点击右上角的“注册设备”按钮
-
下载固件和证书文件
-
安装HiLens Agent(开发板需联网),将上一步下载的HiLens_Device_Agent拷贝到开发板上(拖动文件到VS Code界面中即可),执行命令安装Agent服务:
tar -xvf [Agent安装包名称]
bash install_manual.sh
-
Agent安装过程中将自动下载RK系列的npu驱动,为后面的AI应用开发提供运行环境。
-
安装完成后在开发板的
/usr/local/rk_drivers
目录下将会看到超过2MB大小的librknnrt.so
文件:
ll /usr/local/rk_drivers
- 如果没有该文件或者文件大小不对,可在
rknpu2
的github页面手动下载该文件并拷贝到对应路径。
wget https://github.com/rockchip-linux/rknpu2/tree/master/runtime/RK356X/Linux/librknn_api/aarch64/librknnrt.so
- 注册设备(开发板需联网),将前面下载的与设备名称同名的证书文件拷贝到开发板上(拖动文件到VS Code界面中即可):
#hdactl register_bind -p [证书文件名称]
hdactl register_bind -p sunxiaobei-modelbox.tar.gz
- 激活设备,购买服务并激活
下载ModelBox sdk
- 在HiLens管理控制台专业版的技能开发-工具/插件板块下载RK系列的ModelBox sdk:
- 将sdk拷贝到开发板上(拖动文件到VS Code界面中即可),解压可得到sdk如下:
tar -xf modelbox-rk-aarch64-1.0.9.6.tar.gz
- 其中
modelbox-rk-aarch64
文件夹即为sdk,包含modelbox运行环境、内置的功能单元等,create.py
为创建modelbox工程、创建功能单元、编译运行等的辅助工具。进入sdk目录,执行create.py
可看到辅助工具的用法介绍(需使用python3.8版本进行编码开发):
cd modelbox-rk-aarch64-1.0.9.6/
./create.py
安装Git并创建代码库
- 安装Git
# 安装
sudo apt install git
# 输入Y
git --version
# 配置Git
git config --global user.name SunXiaobei
git config --global user.email youxiang@qq.com
git config --list
#配置服务器
ssh-keygen -t rsa -C youxiang@qq.com
#复制公钥到服务器 配置
#测试
ssh -T git@github.com
git clone git@github.com:sunxiaobei/modelbox.git
- 创建GitHub代码库:https://github.com/sunxiaobei/modelbox_gallery
开发Hello World应用
- 用Python开发一个最简单的ModelBox应用:打开一个视频文件,在画面左上方写上“Hello World”,再输出到另一个视频文件中
- 代码tag:v0.2 hello_world
(1)创建工程
- 使用
create.py
创建hello_world
工程
#版本管理, 打个原始标签
git tag -a v0.1 -m 'init'
git push origin --tags
# 创建demo
./create.py -t server -n hello_world
# commit
git add .
git commit -m 'create hello_world'
-
如果执行过程中
dos2unix
报错,请使用sudo apt-get install dos2unix
安装 -
sudo apt-get install dos2unix
可以看到,第一次创建工程时,在modelbox sdk目录下,自动生成了workspace
文件夹,此文件夹将作为modelbox应用的默认目录。workspace
目录下创建了hello_world
工程:
(2)创建功能单元
为hello_world
工程创建python的draw_text
功能单元:
#创建功能单元
./create.py -t python -n draw_text -p hello_world
# commit
git add .
git commit -m 'create draw_text'
(3)修改功能单元
pip install opencv-python
draw_text.toml
中配置该功能单元的名称、类别、输入输出端口等信息,当前不用修改;draw_text.py
中描述了该功能单元的处理逻辑,这里我们增加OpenCV与NumPy包的引用(需要事先用pip install opencv-python
命令安装OpenCV与NumPy的Python库),修改其中的process
函数如下:
import cv2
import numpy as np
import _flowunit as modelbox
…
def process(self, data_context):
# Process the data
in_data = data_context.input("in_1")
out_data = data_context.output("out_1")
# draw_text process code.
# Remove the following code and add your own code here.
for buffer_img in in_data:
width = buffer_img.get('width')
height = buffer_img.get('height')
channel = buffer_img.get('channel')
img_data = np.array(buffer_img.as_object(), copy=False)
img_data = img_data.reshape((height, width, channel))
cv2.putText(img_data, 'Hello World', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
out_buffer = self.create_buffer(img_data)
out_buffer.copy_meta(buffer_img)
out_data.push_back(out_buffer)
return modelbox.Status.StatusCode.STATUS_SUCCESS
git add .
git commit -m 'modify draw_text'
(4)修改流程图
hello_world
工程graph
目录下默认生成了一个hello_world.toml
流程图,修改其中的流程定义graphconf如下:
graphconf = """digraph hello_world {
node [shape=Mrecord];
queue_size = 4
batch_size = 1
input1[type=input]
data_source_parser[type=flowunit, flowunit=data_source_parser, device=cpu, deviceid=0]
video_demuxer[type=flowunit, flowunit=video_demuxer, device=cpu, deviceid=0]
video_decoder[type=flowunit, flowunit=video_decoder, device=rknpu, deviceid=0, pix_fmt=bgr]
draw_text[type=flowunit, flowunit=draw_text, device=cpu, deviceid=0]
video_out[type=flowunit, flowunit=video_out, device=rknpu, deviceid=0]
input1:input -> data_source_parser:in_data
data_source_parser:out_video_url -> video_demuxer:in_video_url
video_demuxer:out_video_packet -> video_decoder:in_video_packet
video_decoder:out_video_frame -> draw_text:in_1
draw_text:out_1 -> video_out:in_video_frame
}"""
git add .
git commit -m 'modify graph'
(5)配置输入和输出
我们需要准备一个mp4文件拷贝到hello_world
工程中,将sdk目录下的solution/car_det/common/data/car_test_video.mp4
拷贝到hello_world
工程目录的data
文件夹下,然后打开工程目录下bin/mock_task.toml
文件,修改其中的任务输入和任务输出配置为如下内容:
# 任务输入,mock模拟目前仅支持一路rtsp或者本地url
# rtsp摄像头,type = "rtsp", url里面写入rtsp地址
# 其它用"url",比如可以是本地文件地址, 或者httpserver的地址,(摄像头 url = "0")
[input]
type = "url"
url = "../data/car_test_video.mp4"
# 任务输出,目前仅支持"webhook", 和本地输出"local"(输出到屏幕,url="0", 输出到rtsp,填写rtsp地址)
# (local 还可以输出到本地文件,这个时候注意,文件可以是相对路径,是相对这个mock_task.toml文件本身)
[output]
type = "local"
url = "../hilens_data_dir/hello.mp4"
git add .
git commit -m 'modify config'
(6)构建工程
在hello_world
工程路径下执行build_project.sh
进行工程构建:
cd workspace/hello_world/
./build_project.sh
- 如果执行过程中
dos2unix
报错,请使用sudo apt-get install dos2unix
安装:
sudo apt-get install dos2unix
(7)运行应用
执行bin/main.sh
运行应用(如果执行过程中报错,可用sudo su
切换到root用户再运行):
sudo su root
./bin/main.sh
git add .
git commit -m 'run hello_world'
git tag -a 'v0.2' -m 'hello_world'
git push
git push origin --tags
出现Task SUCCEEDED
日志即表示这个图运行结束了,工程目录下的hilens_data_dir
文件夹下将会生成视频文件hello.mp4
,可以下载到PC端查看。
- No module named ‘cv2’
pip install opencv-python
#bash: pip: command not found
sudo apt-get install python3-pip
注意:如果没有为系统安装桌面环境,运行应用时可能会报错缺少某些库,可以先安装对应的库再运行。
- 缺少
libatomic.so.1
库:
sudo apt-get update && sudo apt-get install -y libatomic1
- 缺少
libcurl.so.4
库:
sudo apt-get install -y libcurl4
- 缺少
libGL.so.1
库:
sudo apt-get install -y libgl1
另外,如果运行日志中有类似下面这样的报错,可以忽略,这是应用在尝试与云侧通信校验license,但当前我们是在本地测试,不需要这类校验:
[ERROR][iva_auth_info_updater.cc:29 ] IvaManager::SetIAMAuthInfo Not enough meassage. userId and (domain_id or vas_x_role_name) is empty.
读取摄像头视频
- 代码tag:v0.3 camera
(1)生成视频流应用的流程图
- 代码tag:v0.2 hello_world
除了使用视频文件进行测试,ModelBox
还支持输入实时视频流,接下来我们试试在USB摄像头的实时画面上写“Hello World”,这个功能需要用到上面介绍的ModelBox PC Tool
工具。
cp graph/hello_world.toml graph/hello_world_camera.toml
使用cp graph/hello_world.toml graph/hello_world_camera.toml
命令生成新的流程图,修改hello_world_camera.toml
中的流程定义graphconf如下,可以对比它与hello_world.toml
的区别:
graphconf = """digraph hello_world {
node [shape=Mrecord];
queue_size = 4
batch_size = 1
input1[type=input]
data_source_parser[type=flowunit, flowunit=data_source_parser, device=cpu, deviceid=0]
local_camera[type=flowunit, flowunit=local_camera, device=rknpu, deviceid=0, pix_fmt=bgr, cam_width=1280, cam_height=720]
draw_text[type=flowunit, flowunit=draw_text, device=cpu, deviceid=0]
video_out[type=flowunit, flowunit=video_out, device=rknpu, deviceid=0]
input1:input -> data_source_parser:in_data
data_source_parser:out_video_url -> local_camera:in_camera_packet
local_camera:out_camera_frame -> draw_text:in_1
draw_text:out_1 -> video_out:in_video_frame
}"""
(2)修改输入和输出配置
打开工程目录下bin/mock_task.toml
文件,修改其中的任务输入和任务输出配置为如下内容:
# 任务输入,mock模拟目前仅支持一路rtsp或者本地url
# rtsp摄像头,type = "rtsp", url里面写入rtsp地址
# 其它用"url",比如可以是本地文件地址, 或者httpserver的地址,(摄像头 url = "0")
[input]
type = "url"
url = "0"
# 任务输出,目前仅支持"webhook", 和本地输出"local"(输出到屏幕,url="0", 输出到rtsp,填写rtsp地址)
# (local 还可以输出到本地文件,这个时候注意,文件可以是相对路径,是相对这个mock_task.toml文件本身)
[output]
type = "local"
url = "rtsp://192.168.2.2:8554/outstream"
注意,output
条目下url
配置中的ip是PC的ip地址,如果之前是用ModelBox PC Tool
配置静态ip的方式设置的网络,那PC的ip地址就是192.168.2.2
,否则需要做相应修改。
(3)运行应用
将USB摄像头插到开发板上,双击任务栏上的ModelBox PC Tool
工具图标弹出主界面,在Step2界面上选择“使用开发板侧视频流”,点击“启动推流”,推流服务将启动,ModelBox PC Tool
工具也会再次最小化到任务栏上:
在VS Code
Terminal中执行bin/main.sh camera
运行应用:
bin/main.sh camera
git add .
git commit -m 'run camera'
git tag -a 'v0.3' -m 'camera'
git push
git push origin --tags
开发第一个AI应用
-
代码tag:v1.0 car_det
-
车辆检测应用:打开一个视频文件,使用检测模型检测出画面中车辆并画框,再输出到另一个视频文件中。本应用作为模板案例已内置在sdk中,不需要另外下载。
(1)创建工程
使用车辆检测模板创建car_det
工程(注意与创建hello_world
工程的区别):
./create.py -t server -n car_det -s car_det
git add .
git commit -m 'create car_test'
(2)查看推理功能单元
- 应用使用到模型推理,需要用到推理功能单元,可以看到,在
car_det
工程目录的model
文件夹下,存在yolox_infer
推理功能单元文件夹,里面有yolox模型文件(yolox_nano_288x512.rknn
)和模型配置文件(yolox_infer.toml
),模型配置文件如下:
# Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved.
[base]
name = "yolox_infer"
device = "rknpu"
version = "1.0.0"
description = "car detection"
entry = "./yolox_nano_288x512.rknn" # model file path, use relative path
type = "inference"
virtual_type = "rknpu2" # inference engine type: rockchip now support rknpu, rknpu2(if exist)
group_type = "Inference" # flowunit group attribution, do not change
is_input_contiguous = "false" # input data attribution, do not change
# input port description, suporrt multiple input ports
[input]
[input.input1]
name = "input"
type = "uint8"
device = "rknpu"
# output port description, suporrt multiple output ports
[output]
[output.output1]
name = "output"
type = "float"
-
可以看到该模型有1个输入节点,1个输出节点。需要注意其中的
virtual_type
配置与npu类别有关,RK3568需配置为rknpu2
;输入节点的device
配置建议设为与该推理功能单元的上一个功能单元相同。ModelBox内置了rknn推理引擎和推理逻辑,开发者只需要准备好模型、编辑好配置文件,即可使用该模型进行推理,无需编写推理代码。 -
如果想要创建另外的推理功能单元,可以使用如下命令,推理功能单元默认创建在工程目录的
model
文件夹下:
./create.py -t infer -n my_model -p car_det
git add .
git commit -m 'create new model'
- 案例使用的车辆检测模型是由PyTorch框架训练得到,可以使用rknn-toolkit2工具将它转换为RK3568支持的模型格式,RK3568模型转换验证案例可学习模型转换过程。
(3)查看其他功能单元
- 车辆检测模型推理后需要做一些后处理操作得到检测框,再把检测框添加到原始画面中,我们已经准备好了对应的功能单元
yolox_post
和draw_car_bbox
:
(4)查看执行脚本
car_det
工程graph
目录下带有多个流程图,配置文件modelbox.conf
中的flow_path
参数指定了技能运行时的流程图路径:
flow_path = "${APP_ROOT}/graph/car_det${HILENS_GRAPH_TYPE}.toml"
- 新版本环境变量改了
其中环境变量${APP_ROOT}
在运行技能时将自动替换为当前工程的实际路径,而${HILENS_GRAPH_TYPE}
可以在执行bin/main.sh
脚本时输入流程图后缀名作为参数指定当前运行哪个图,打开该脚本看到相关参数内容为:
if [ "$1" = "default" -o "$1" = "" ]; then
export HILENS_GRAPH_TYPE=
else
export HILENS_GRAPH_TYPE=_$1
fi
默认执行与工程同名的流程图car_det.toml
,如果输入bin/main.sh http
即执行car_det_http.toml
。
(5)查看默认流程图
与工程同名的car_det.toml
流程图中的流程定义graphconf如下:
graphconf = """digraph car_det {
node [shape=Mrecord]
queue_size = 4
batch_size = 1
input1[type=input]
data_source_parser[type=flowunit, flowunit=data_source_parser, device=cpu, deviceid=0]
video_demuxer[type=flowunit, flowunit=video_demuxer, device=cpu, deviceid=0]
video_decoder[type=flowunit, flowunit=video_decoder, device=rknpu, deviceid=0, pix_fmt=bgr]
image_resize[type=flowunit, flowunit=resize, device=rknpu, deviceid=0, image_width=512, image_height=288]
car_detection[type=flowunit, flowunit=yolox_infer, device=rknpu, deviceid=0]
yolox_post[type=flowunit, flowunit=yolox_post, device=cpu, deviceid=0]
draw_car_bbox[type=flowunit, flowunit=draw_car_bbox, device=cpu, deviceid=0]
video_out[type=flowunit, flowunit=video_out, device=rknpu, deviceid=0]
input1:input -> data_source_parser:in_data
data_source_parser:out_video_url -> video_demuxer:in_video_url
video_demuxer:out_video_packet -> video_decoder:in_video_packet
video_decoder:out_video_frame -> image_resize:in_image
image_resize:out_image -> car_detection:input
car_detection:output -> yolox_post:in_feat
video_decoder:out_video_frame -> draw_car_bbox:in_image
yolox_post:out_data -> draw_car_bbox:in_bbox
draw_car_bbox:out_image -> video_out:in_video_frame
}"""
- 原文错误
查看任务配置文件bin/mock_task.toml
,可以看到其中的任务输入和任务输出配置为如下内容:
# 任务输入,mock模拟目前仅支持一路rtsp或者本地url
# rtsp摄像头,type = "rtsp", url里面写入rtsp地址
# 其它用"url",比如可以是本地文件地址, 或者httpserver的地址,(摄像头 url = "0")
[input]
type = "url"
url = "../data/car_test_video.mp4"
# 任务输出,目前仅支持"webhook", 和本地输出"local"(输出到屏幕,url="0", 输出到rtsp,填写rtsp地址)
# (local 还可以输出到本地文件,这个时候注意,文件可以是相对路径,是相对这个mock_task.toml文件本身)
[output]
type = "local"
url = "../hilens_data_dir/car_test_result.mp4"
该流程图使用data/car_test_video.mp4
文件进行车辆检测,检测结果绘制后保存为hilens_data_dir/car_test_result.mp4
文件。
(6)运行默认应用
在car_det
工程路径下执行build_project.sh
进行工程构建:
cd workspace/car_test/
./build_project.sh
切换到root
账号,执行bin/main.sh
运行应用,运行结束后在hilens_data_dir
目录下生成了car_test_result.mp4
文件,可以下载到PC端查看。
sudo su root
bin/main.sh
git add .
git commit -m 'run car_det'
git push
git tag -a 'v1.0' -m 'car_det'
git push origin --tags
开发HTTP版车辆检测
- 代码tag:v1.1 car_det_http
(1)查看HTTP流程图
除了开发视频推理类应用,我们还可以使用ModelBox开发HTTP服务类应用,打开car_det/graph/car_det_http.toml
,看到流程定义graphconf如下:
graphconf = """digraph car_det {
node [shape=Mrecord];
queue_size = 4
batch_size = 1
input1[type=input]
httpserver_sync_receive[type=flowunit, flowunit=httpserver_sync_receive_v2, device=cpu, deviceid=0, time_out_ms=5000, endpoint="http://0.0.0.0:8083/v1/car_det", max_requests=100]
image_decoder[type=flowunit, flowunit=image_decoder, device=rknpu, deviceid=0, key="image_base64"]
image_resize[type=flowunit, flowunit=resize, device=rknpu, deviceid=0, image_width=512, image_height=288]
car_detection[type=flowunit, flowunit=yolox_infer, device=rknpu, deviceid=0]
yolox_post[type=flowunit, flowunit=yolox_post, device=cpu, deviceid=0]
httpserver_sync_reply[type=flowunit, flowunit=httpserver_sync_reply_v2, device=cpu, deviceid=0]
input1:input -> httpserver_sync_receive:in_url
httpserver_sync_receive:out_request_info -> image_decoder:in_encoded_image
image_decoder:out_image -> image_resize:in_image
image_resize:out_image -> car_detection:input
car_detection:output -> yolox_post:in_feat
yolox_post:out_data -> httpserver_sync_reply:in_reply_info
}"""
- 原教程多了符号
该流程图从HTTP请求中接收一张图片进行车辆检测,并返回检测结果。
(2)运行HTTP应用
- 使用root账号运行
car_det_http.toml
流程图(注意命令后的http参数):
sudo su root
./bin/main.sh http
看到Start server at http...
字样的日志即表示HTTP服务已启动,等待调用。
(3)调用HTTP服务
在car_det/data
目录下HTTP调用的测试脚本test_http.py
和测试图片car_test_pic.jpg
,可以看到默认是在本机发起调用请求:
…
if __name__ == "__main__":
port = 8083
ip = "127.0.0.1"
url = "/v1/car_det"
img_path = "./car_test_pic.jpg"
test_image(img_path, ip, port, url)
- 在VS Code中打开另一个终端,执行该脚本,将在
car_det/data
下生成测试图片的推理结果car_test_pic.jpg
:
cd modelbox/workspace/car_det/data/
python test_http.py
- 当然,也可以将测试脚本和图片拷贝到PC上,并将
test_http.py
中的ip变量修改为开发板的ip进行远程调用测试。
git add .
git commit -m
git push 'car_det_http'
git tag -a 'v1.1' -m 'car_det_http'
git push origin --tag
小结
- 本小节实践了应用开发的案例,为了方便调试拆成了四个阶段,分别为Hello World应用,摄像头启用,车辆检测项目,车辆检测HTTP项目。通过这次的实践,基本上手了开发板的案例开发过程。相关实践代码也放到Github上。
参考文献:
- 点赞
- 收藏
- 关注作者
评论(0)