基于头肩部检测的过线客流统计

基于,肩部,检测,过线,客流,统计 · 浏览次数 : 237

小编点评

**标题:华为云新鲜技术,高效人脸检测应用开发教程** **前言:** 华为云新鲜技术,华为云新鲜技术,高效人脸检测应用开发教程,介绍了华为云新鲜技术的应用,包括人脸检测应用,并提供开发教程,帮助开发者快速开发应用。 **一、基本概念:** - 人脸检测 - 统计 - 算法 **二、开发教程:** - 人脸检测应用开发教程 - 开发教程概述 **三、核心逻辑:** - 跟踪与过线判断 - 输入输出配置 **四、三方依赖库:** - PS ███ - .\\build_project.sh **五、环境配置:** - bin/mock_task.toml **六、使用引导脚本:** - run \\build_project.sh **七、结果展示:** - 人脸检测应用,生成人脸检测结果,包括头肩部、过线客流数量等。 **八、结论:** 华为云新鲜技术,高效人脸检测应用开发教程,帮助开发者快速开发人脸检测应用,并提供环境配置和使用引导脚本的说明。

正文

摘要:通过本教程,我们学习了另一类客流统计应用——过线客流统计,通常用于室内出入口,摄像头会架设在高处俯拍,使用头肩部检测可以减少人与人之间的遮挡。

本文分享自华为云社区《客流分析之基于头肩部检测的过线客流统计》,作者:HiLens_feige 。

1.基于头肩部检测的过线客流统计

除了划区域客流统计之外,另一类常见的客流统计场景是过线客流统计,本文介绍基于头肩部检测的过线客流统计技能:采用头肩部检测人形并进行跟踪,当头肩部中心点跨过事先划定的线段时,增加客流计数;过线前后的人形将使用不同颜色的框表示,画面中也会实时显示客流数量。

准备工作

本文将使用华为云ModelArts进行人形检测模型的训练,并使用ModelBox框架进行应用开发,使用前开发者需要完成如下准备工作:

  1. 参考 此教程 完成设备的注册;
  2. 参考 此教程 完成ModelBox SDK的安装。

 

2.技能开发

这个应用对应的ModelBox版本已经做成模板放在华为云OBS中,可以用sdk中的solution.bat工具下载,接下来我们给出该应用在ModelBox中的完整开发过程:

1)下载模板

执行.\solution.bat -l可看到当前公开的技能模板:

PS ███> .\solution.bat -l
...
Solutions name:
mask_det_yolo3
...
passenger_flow_head_det_yolo7

结果中的passenger_flow_head_det_yolo7即为基于头肩部检测的过线客流统计应用模板,可使用如下命令下载模板:

PS ███> .\solution.bat -s passenger_flow_head_det_yolo7
...

solution.bat工具的参数中,-l 代表list,即列出当前已有的模板名称;-s 代表solution-name,即下载对应名称的模板。下载下来的模板资源,将存放在ModelBox核心库的solution目录下。

2)创建工程

在ModelBox sdk目录下使用create.bat创建passenger_flow工程

PS ███> .\create.bat -t server -n passenger_flow -s passenger_flow_head_det_yolo7
sdk version is modelbox-xxx
success: create passenger_flow in ███\modelbox\workspace

create.bat工具的参数中,-t 表示创建事务的类别,包括工程(server)、Python功能单元(Python)、推理功能单元(infer)等;-n 代表name,即创建事务的名称;-s 代表solution-name,表示将使用后面参数值代表的模板创建工程,而不是创建空的工程。

workspace目录下将创建出passenger_flow工程,工程内容如下所示:

passenger_flow
|--bin
│  |--main.bat:应用执行入口
│  |--mock_task.toml:应用在本地执行时的输入输出配置,此应用默认使用本地视频文件为输入源,最终结果输出到另一本地视频文件,可根据需要修改
|--CMake:存放一些自定义CMake函数
|--data:存放应用运行所需要的图片、视频、文本、配置等数据
│  |--passenger_flow.mp4:客流统计测试用视频文件
│  |--simsun.ttc:中文字体库
|--dependence
│  |--modelbox_requirements.txt:应用运行依赖的外部库在此文件定义,本应用依赖pillow工具包
|--etc
│  |--flowunit:应用所需的功能单元存放在此目录
│  │  |--cpp:存放C++功能单元编译后的动态链接库,此应用没有C++功能单元
│  │  |--draw_passenger_bbox:客流画图功能单元
│  │  |--object_tracker:目标跟踪功能单元
│  │  |--yolov7_post:头肩部检测使用的是YOLO7模型,此处即为后处理功能单元
|--flowunit_cpp:存放C++功能单元的源代码,此应用没有C++功能单元
|--graph:存放流程图
│  |--passenger_flow.toml:默认流程图,使用本地视频文件作为输入源
│  |--modelbox.conf:modelbox相关配置
|--hilens_data_dir:存放应用输出的结果文件、日志、性能统计信息
|--model:推理功能单元目录
│  |--head_detection:头肩部检测推理功能单元
│  │  |--head_detection.toml:头肩部检测推理功能单元的配置文件
│  │  |--head_det_yolo7_lite_224x352.onnx:头肩部检测onnx模型
|--build_project.sh:应用构建脚本
|--CMakeLists.txt
|--rpm:打包rpm时生成的目录,将存放rpm包所需数据
|--rpm_copyothers.sh:rpm打包时的辅助脚本

3)查看流程图

passenger_flow工程graph目录下存放流程图,默认的流程图passenger_flow.toml与工程同名,其内容为(以Windows版ModelBox为例):

[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 = "passenger detection using head-shoulder detection with yolov7 for local video or rtsp video stream" # 应用的简单描述
[graph]
format = "graphviz" # 流程图的格式,当前仅支持graphviz
graphconf = """digraph passenger_flow {
    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=cpu, deviceid=0, pix_fmt="rgb"]
 resize[type=flowunit flowunit=resize device=cpu deviceid="0" image_width=352, image_height=224]
 color_transpose[type=flowunit flowunit=packed_planar_transpose device=cpu deviceid="0"]
 normalize[type=flowunit flowunit=normalize device=cpu deviceid="0" standard_deviation_inverse="0.0039215686,0.0039215686,0.0039215686"]
 head_detection[type=flowunit flowunit=head_detection device=cpu deviceid="0"]
    yolov7_post[type=flowunit flowunit=yolov7_post device=cpu deviceid="0"]
 object_tracker[type=flowunit, flowunit=object_tracker, device=cpu, deviceid=0]
 draw_passenger_bbox[type=flowunit, flowunit=draw_passenger_bbox, device=cpu, deviceid=0]
 video_out[type=flowunit flowunit=video_out device=cpu 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 -> resize:in_image
 resize:out_image -> color_transpose:in_image
 color_transpose:out_image -> normalize:in_data
 normalize:out_data -> head_detection:input
 head_detection:output -> yolov7_post:in_feat
    yolov7_post:out_data -> object_tracker:in_bbox
 object_tracker:out_track -> draw_passenger_bbox:in_track
 video_decoder:out_video_frame -> draw_passenger_bbox:in_image
 draw_passenger_bbox:out_image -> video_out:in_video_frame
}"""

整个应用逻辑比较简单,视频解码后做图像预处理,接着是头肩部检测,模型后处理得到头肩框,送入跟踪算法进行实时跟踪与过线判断,最后将跟踪信息画到图像输出到视频中。

4)核心逻辑

本应用的核心逻辑是跟踪与过线判断,体现在 object_tracker 功能单元中,它是一个Stream功能单元,Stream功能单元的概念和案例可以参考 ModelBox AI应用开发——Stream功能单元 。

object_tracker 功能单元的实现代码在object_tracker.py和easy_tracker.py文件中,目标跟踪算法 EasyTracker 根据IoU使用贪心法进行匹配,过线判断逻辑在object_tracker.py的 get_tracking_objects 函数中:

  def get_tracking_objects(self, line_y):
 '''从跟踪器中获取跟踪目标,保存到结构化数据中'''
        def _is_pass_line(bbox, line_y):
 '''根据检测框的中心点与线段的水平位置关系判断是否过线'''
 center_y = (bbox[1] + bbox[3]) / 2
 return center_y > line_y
 tracking_objects = []  # 所有跟踪目标
 for track in self.tracker.tracks:
            # 只记录CONFIRMED状态的跟踪目标
 if track.state != EasyTracker.TrackingState.CONFIRMED:
 continue
 tracking_obj = {}  # 使用字典保存跟踪目标
 tracking_obj["id"] = track.track_id  # 跟踪id
 tracking_obj["bbox"] = track.det  # 跟踪框
 if not track.passline and _is_pass_line(track.det, line_y):  # 刚好过线
 track.passline = True
 self.flow_count += 1
 tracking_obj["passline"] = track.passline  # 记录过线信息
 tracking_objects.append(tracking_obj)
 return tracking_objects

可以看到,应用做了简化处理,假设过线统计的线段为水平线段,使用检测框的中心点y坐标与线段的y坐标比较判断是否过线。此处开发者可以进行修改扩展,使得应用可以支持非水平线段的过线判断。

5)三方依赖库

本应用中的画图功能单元以来 pillow 工具包以实现中文输出,ModelBox应用不需要手动安装三方依赖库,只需要配置在 dependence\modelbox_requirements.txt ,应用在编译时会自动安装。另外,中文输出还需要对应的字体库,存放在 data 目录下,画图功能单元初始化时将从此目录加载资源。

6)查看输入输出配置

查看任务配置文件bin/mock_task.toml,可以看到其中的任务输入和任务输出配置为如下内容::

[input]
type = "url"
url = "${HILENS_APP_ROOT}/data/passenger_flow.mp4"  # 表示输入源为本地视频文件
[output]
type = "local"
url = "${HILENS_APP_ROOT}/hilens_data_dir/passenger_flow_result.mp4"  # 表示输出为本地视频文件

即,使用本地视频文件data/passenger_flow.mp4作为输入,统计过线客流后,画图输出到本地视频文件data/passenger_flow_result.mp4中。

7)用启动脚本执行应用

启动应用前执行.\build_project.sh进行工程构建,该脚本将编译自定义的C++功能单元(本应用不涉及)、将应用运行时会用到的配置文件转码为Unix格式(防止执行过程中的格式错误)、安装第三方依赖库:

PS ███> .\build_project.sh
...
PS ███>

然后执行.\bin\main.bat运行应用:

PS ███> .\bin\main.bat
...

运行结束后在hilens_data_dir目录下生成了passenger_flow_result.mp4文件,可以打开查看:

可以看到,黄色线段即为过线统计的水平线段,未过线的人使用灰色框标记其头肩部,已过线的使用蓝色框,画面左上角实时显示总的过线客流数量。

3.小结

通过本教程,我们学习了另一类客流统计应用——过线客流统计,通常用于室内出入口,摄像头会架设在高处俯拍,使用头肩部检测可以减少人与人之间的遮挡。

 

点击关注,第一时间了解华为云新鲜技术~

与基于头肩部检测的过线客流统计相似的内容:

基于头肩部检测的过线客流统计

摘要:通过本教程,我们学习了另一类客流统计应用——过线客流统计,通常用于室内出入口,摄像头会架设在高处俯拍,使用头肩部检测可以减少人与人之间的遮挡。 本文分享自华为云社区《客流分析之基于头肩部检测的过线客流统计》,作者:HiLens_feige 。 1.基于头肩部检测的过线客流统计 除了划区域客流统

AI开发实践丨客流分析之未佩戴口罩识别

摘要:通过本教程,我们可以学习客流统计应用的扩展——过线客流统计+口罩佩戴识别,可用于商超、写字楼入口安检。 本文分享自华为云社区《客流分析之未佩戴口罩识别》,作者: HiLens_feige 。 疫情虽然过去了,口罩佩戴防护依然十分重要,本文在 基于头肩部检测的过线客流统计 博文基础上增加口罩佩戴

基于webapi的websocket聊天室(番外二)

我比较好奇的是webapi服务器怎么处理http请求和websocket请求。有了上一篇番外的研究,这里就可以试着自己写个非常简易的webapi服务器来接收这两种请求。 效果 http请求 消息打印 响应解析 websocket请求 消息打印 使用聊天室测试 其实两种请求差不多,就只是一些头部字段有

实训day2

HTML基本介绍 编辑网页的语言,超文本标记语言,是迄今为止网络上应用最为广泛的语言,也是抱成网页文档的主要语言。HTML文本是由HTML命令组成的描述性文本,HTML命令可以说明文字、图形、动画、声音、表格、链接等。HTML的结构包括头部(Head)、主体(Body)两大部分,其中头部猫述浏览器所

HTTP请求:requests的进阶使用方法浅析

上篇文章讲解了requests模块的基础使用,其中有get、put、post等多种请求方式,使用data、json等格式做为请求参数,在请求体中添加请求头部信息的常见信息,如:headers、cookies,以及对请求响应的处理方法。接下来讲解一下requests的高级用法。

驱动开发:摘除InlineHook内核钩子

在笔者上一篇文章`《驱动开发:内核层InlineHook挂钩函数》`中介绍了通过替换`函数`头部代码的方式实现`Hook`挂钩,对于ARK工具来说实现扫描与摘除`InlineHook`钩子也是最基本的功能,此类功能的实现一般可在应用层进行,而驱动层只需要保留一个`读写字节`的函数即可,将复杂的流程放在应用层实现是一个非常明智的选择,与`《驱动开发:内核实现进程反汇编》`中所使用的读写驱动基本一致,

IDP中的黄金路径究竟是什么?

在云原生时代,开发人员面临着越来越多的工具、技术、思维方式的选择,给他们带来了极大的认知负担和工作量。为了提高开发人员的开发效率与开发体验,一些头部科技公司开始建立自己的内部开发者平台(IDP)。在之前的文章我们有简单了解过 IDP 相关的基础概念。IDP 是一套由平台工程团队维护的工具和技术,让开

入门篇-其之四-字符串String的简单使用

什么是字符串? 在Java编程语言中,字符串用于表示文本数据。 字符串(String)属于引用数据类型,根据String的源码,其头部使用class进行修饰,属于类,即引用数据类型。 字符串的表示 字符串使用双引号""表示,在双引号中你可以写任意字符。 和前面定义并初始化基本数据类型的变量一样,定义

7.5 C/C++ 实现链表队列

链表队列是一种基于链表实现的队列,相比于顺序队列而言,链表队列不需要预先申请固定大小的内存空间,可以根据需要动态申请和释放内存。在链表队列中,每个节点包含一个数据元素和一个指向下一个节点的指针,头节点表示队头,尾节点表示队尾,入队操作在队尾插入元素,出队操作在队头删除元素,队列的长度由节点数量决定。由于链表队列没有容量限制,因此可以处理任意数量的元素,但是相比于顺序队列,链表队列的访问速度较慢,因

DHorse v1.5.1 发布,基于 k8s 的发布平台

版本说明 新增特性 支持k8s的v1.30.x版本; 优化特性 优化回滚功能; 修复注册来源的回滚问题; 新增和修改应用时校验应用名; 升级kubernetes-client至v6.13.0; 调整部署明细表头展示; 升级指南 升级指南 DHorse介绍 DHorse是一个轻量级、简单易用的云应用管