ModelBox开发指南 - 使用条件功能单元实现单人人体关键点检测
ModelBox开发指南 - 条件功能单元
本文将使用一个单人人体关键点检测的案例,介绍ModelBox中条件功能单元的特性,案例效果如下所示:
本案例所需资源(代码、模型、测试数据等)已做成模板放到华为云上,查看和下载模板可以使用如下命令:
- Windows PC版本请使用
solution.bat
工具:
PS ███\modelbox>: .\solution.bat -l
...
Solutions name:
...
single_person_pose_yolox_alpha_pose
...
结果中的single_person_pose_yolox_alpha_pose即为单人人体关键点检测模板,可使用如下命令下载模板:
PS ███\modelbox>: .\solution.bat -s single_person_pose_yolox_alpha_pose
...
- Linux开发板版本请使用
solution.py
脚本:
rock@rock-3a:~/███/modelbox$ ./solution.py -l
...
Solutions name:
...
single_person_pose_yolox_alpha_pose
...
结果中的single_person_pose_yolox_alpha_pose即为单人人体关键点检测模板,可使用如下命令下载模板:
rock@rock-3a:~/███/modelbox$ ./solution.py -s single_person_pose_yolox_alpha_pose
...
solution.bat
/solution.py
工具的参数中,-l
代表list
,即列出当前已有的模板名称;-s
代表solution-name
,即下载对应名称的模板。下载下来的模板资源,将存放在ModelBox
核心库的solution
目录下。
如果对ModelBox AI应用开发还不熟悉,请先阅读ModelBox 端云协同AI开发套件(RK3568)上手指南,或者ModelBox 端云协同AI开发套件(博时特EC02)上手指南。
模型准备
本案例使用了两个模型:一是人体关键点检测模型AlphaPose
,这是一个两阶段的模型(或者叫自上而下
的人体关键点检测模型),需要搭配人体检测模型使用;另一个就是人体检测模型YOLOX
,与ModelBox sdk中自带的car_det
模板使用的模型相同。在下载的资源包中,已经包含了转换好的rknn模型或者onnx模型,可以在对应的平台上直接使用。当然,开发者也可以直接使用car_det
模板中的YOLOX
模型。
YOLOX
原始模型的训练工程可参考此项目,AlphaPose
的训练工程可参考此项目,感兴趣的开发者可使用这些项目自行训练模型。
如果想体验rknn模型的转换过程,rknpu版本可参考RK1808模型转换验证案例,rknpu2版本可参考RK3568模型转换验证案例。
应用开发
打开VS Code,连接到ModelBox sdk所在目录或者远程开发板,开始进行单人人体关键点检测应用开发。下面以RK3568(rknpu2)版本为例进行说明,其他版本与之类似。
1)创建工程
使用create.py
创建single_person_pose
工程(Windows PC版本请使用create.bat
):
rock@rock-3a:~/███/modelbox$ ./create.py -t server -n single_person_pose -s single_person_pose_yolox_alpha_pose
sdk version is modelbox-rk-aarch64
success: create single_person_pose in /home/rock/███/modelbox/workspace
将会用单人人体关键点检测模板创建出一个single_person_pose工程。
2)查看条件功能单元
条件功能单元,它根据当前帧的检测结果中是否包含人体检测框,形成两个输出分支。它在工程目录的etc/flowunit/ped_condition
文件夹下:
打开ped_condition.toml
配置文件,可以看到功能单元属性部分:
# 工作模式,以下配置项默认全为false,表示通用功能单元;且配置项之前互斥,即最多只能设置其中一个为true
stream = false # 是否是Stream类型功能单元
condition = true # 是否是条件功能单元,此处设置为true,即表示ped_condition是一个条件功能单元
collapse = false # 是否是合并功能单元
expand = false # 是否是展开功能单元
这些属性全部为false时表示通用功能单元,通用功能单元在处理完数据后,会产生一到多个输出,后续功能单元在承接时,必须接收它的所有输出数据(当然接收后可以只处理其中一部分输出)。
ped_condition
功能单元属性部分的condition
属性设置成了true
,即ped_condition
被设置成一个条件功能单元。查看ped_condition.toml
配置文件中的输出配置部分,可以看到有两个输出节点,分别代表检测到人体和未检测到人体两种状态:
# 输出端口描述
[output]
[output.output1] # 检测到人体时的输出数据
name = "has_pedestrian" # 原图 + 人体检测框(检测框以属性方式附加在原图上)
type = "uint8" # 原图数据格式为 uint8
[output.output2] # 未检测到人体时的输出数据
name = "no_pedestrian" # 原图
type = "uint8" # 原图数据格式为 uint8
打开ped_condition.py
,查看其process
函数,可以看到条件功能单元的输出是如何编码的:
def process(self, data_context):
# 从DataContext中获取输入输出BufferList对象
in_image = data_context.input("in_image")
in_bbox = data_context.input("in_bbox")
has_ped = data_context.output("has_pedestrian")
no_ped = data_context.output("no_pedestrian")
# 循环处理每一个输入Buffer数据(实际上条件功能单元的batch size为1,此处循环中只有1条数据)
for buffer_img, buffer_bbox in zip(in_image, in_bbox):
# 获取输入Buffer的属性信息
width = buffer_img.get('width')
height = buffer_img.get('height')
channel = buffer_img.get('channel')
# 将输入Buffer转换为numpy对象
img_data = np.array(buffer_img.as_object(), copy=False)
img_data = img_data.reshape((height, width, channel))
# 字符串数据可以直接用as_object函数转换
bbox_str = buffer_bbox.as_object()
# 解码出人体检测框数据
ped_bboxes = self.decode_ped_bboxes(bbox_str, (height, width))
# 此处是将输入Buffer直接作为输出Buffer向后传递
# 此时Buffer的Data、Meta等全部内容都将保留,无需构建Buffer、设置Meta
if ped_bboxes: # 检测到人体时的输出分支
buffer_img.set("bboxes", list(itertools.chain(*ped_bboxes))) # 将人体检测框作为属性附在输出Buffer上
has_ped.push_back(buffer_img)
else: # 未检测到人体时的输出分支
no_ped.push_back(buffer_img)
# 返回成功标志,ModelBox框架会将数据发送到后续的功能单元
return modelbox.Status.StatusCode.STATUS_SUCCESS
这里也可以看到一个输出数据的设置技巧,在检测到人体时,我们是将人体检测框作为一个属性附在图片上,这样这个分支只需要一个输出。
关于条件功能单元的更细致介绍,详见ModelBox介绍。
3)其他功能单元
人体关键点检测的模型推理功能单元,在工程目录的model/pose_infer
文件夹中:
然后是人体图像裁剪、人体关键点后处理、关键点画图等模块,分别对应crop_ped_image
、single_pose_post
、draw_single_pose
等通用功能单元:
4)查看流程图
工程的默认流程图为graph/single_person_pose.toml
(以RK3568开发板版本为例):
# Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
[driver]
# 功能单元的扫描路径,包含在[]中,多个路径使用,分隔
# ${HILENS_APP_ROOT} 表示当前应用的实际路径
# ${HILENS_MB_SDK_PATH} 表示ModelBox核心库的实际路径
dir = [
"${HILENS_APP_ROOT}/etc/flowunit",
"${HILENS_APP_ROOT}/etc/flowunit/cpp",
"${HILENS_APP_ROOT}/model",
"${HILENS_MB_SDK_PATH}/flowunit",
]
skip-default = true
[profile]
# 通过配置profile和trace开关启用应用的性能统计
profile = false # 是否记录profile信息,每隔60s记录一次统计信息
trace = false # 是否记录trace信息,在任务执行过程中和结束时,输出统计信息
dir = "${HILENS_DATA_DIR}/mb_profile" # profile/trace信息的保存位置
[flow]
desc = "single person pose estimation example using yolox and alpha-pose for local video or rtsp video stream" # 应用的简单描述
[graph]
format = "graphviz" # 流程图的格式,当前仅支持graphviz
graphconf = """digraph single_person_pose {
node [shape=Mrecord]
queue_size = 4
batch_size = 1
# 定义节点,即功能单元及其属性
input1[type=input, flowunit=input, device=cpu, deviceid=0]
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]
ped_detection[type=flowunit, flowunit=yolox_infer, device=rknpu, deviceid=0]
yolox_post[type=flowunit, flowunit=yolox_post, device=cpu, deviceid=0]
ped_condition[type=flowunit, flowunit=ped_condition, device=cpu, deviceid=0]
crop_ped_image[type=flowunit, flowunit=crop_ped_image, device=cpu, deviceid=0]
pose_detection[type=flowunit, flowunit=pose_infer, device=rknpu, deviceid=0]
single_pose_post[type=flowunit, flowunit=single_pose_post, device=cpu, deviceid=0]
draw_single_pose[type=flowunit, flowunit=draw_single_pose, 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 -> ped_detection:input
ped_detection:output -> yolox_post:in_feat
yolox_post:out_data -> ped_condition:in_bbox
video_decoder:out_video_frame -> ped_condition:in_image
ped_condition:no_pedestrian -> video_out:in_video_frame
ped_condition:has_pedestrian -> crop_ped_image:in_data
crop_ped_image:roi_image -> pose_detection:input
pose_detection:output -> single_pose_post:in_feat
ped_condition:has_pedestrian -> draw_single_pose:in_image
single_pose_post:out_data -> draw_single_pose:in_pose
draw_single_pose:out_image -> video_out:in_video_frame
}"""
该流程图对于某个视频流,经过视频解码、图像缩放、人体检测与后处理、人体检测结果判定、人体图像裁剪、单人人体关键点检测与后处理、关键点画图等一系列操作后,将结果保存下来。
图中,可以看到条件功能单元ped_condition
的两个输出分别对接到不同的功能单元,在未检测到人体时,no_pedestrian
分支的输出直接对接到video_out
进行视频编码。
工程的任务配置文件bin/mock_task.toml
中设置了输入输出源,内容为:
# 任务输入配置,当前支持以下几种输入方式:
# 1. rtsp摄像头或rtsp视频流:type="rtsp", url="rtsp://xxx.xxx"
# 2. 设备自带摄像头或者USB摄像头:type="url",url="${摄像头编号}" (需配合local_camera功能单元使用)
# 3. 本地视频文件:type="url",url="${视频文件路径}" (请使用${HILENS_APP_ROOT}宏,表示当前应用的实际路径)
# 4. http服务:type="url", url="http://xxx.xxx"(指的是任务作为http服务启动,此处需填写对外暴露的http服务地址,需配合httpserver类的功能单元使用)
[input]
type = "url"
# url = "0"
url = "${HILENS_APP_ROOT}/data/single_person_pose.mp4"
# 任务输出配置,当前支持以下几种输出方式:
# 1. rtsp视频流:type="local", url="rtsp://xxx.xxx"
# 2. 本地屏幕:type="local", url="0:xxx" (设备需要接显示器,系统需要带桌面)
# 3. 本地视频文件:type="local",url="${视频文件路径}" (请使用${HILENS_APP_ROOT}宏,表示当前应用的实际路径)
# 4. http服务:type="webhook", url="http://xxx.xxx"(指的是任务产生的数据上报给某个http服务,此处需填写上传的http服务地址)
[output]
type = "local"
# url = "0:single_person_pose"
url = "${HILENS_APP_ROOT}/hilens_data_dir/single_person_pose_result.mp4"
测试视频为data/single_human_pose.mp4
,流程图使用这一视频进单人人体关键点检测,检测结果绘制后保存为hilens_data_dir/single_human_pose_result.mp4
文件。
5)运行应用
在工程路径下执行build_project.sh
进行工程构建(以RK3568开发板版本为例):
rock@rock-3a:~/███/modelbox/workspace/single_person_pose$ ./build_project.sh
build success: you can run main.sh in ./bin folder
rock@rock-3a:~/███/modelbox/workspace/single_person_pose$
执行bin/main.sh
(Windows PC版本请使用bin\main.bat
)运行应用,运行结束后在hilens_data_dir
目录下生成了single_human_pose_result.mp4
文件,可以下载到PC端查看。
- 点赞
- 收藏
- 关注作者
评论(0)