gpt4 book ai didi

基于人形检测的划区域客流统计

转载 作者:我是一只小鸟 更新时间:2023-03-07 22:31:27 26 4
gpt4 key购买 nike

摘要: 通过本教程,我们学习了一类客流统计应用——区域内客流统计,通常用于室外安防,或室内客流热力图,经过简单改造还可以实现区域入侵检测、人员在离岗检测等应用。

本文分享自华为云社区《 客流分析之基于人形检测的划区域客流统计 》,作者:HiLens_feige .

在智慧园区、智慧门店等商业场景中,划区域的客流统计是一类常见的AI应用,本文介绍基于人形检测的划区域客流统计:采用人形框检测行人并进行跟踪,若人形框中心点位于事先划定的区域中,增加客流计数;区域内外的人形将使用不同颜色的框表示,画面中也会实时显示客流数量.

准备工作

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

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

  。

技能开发

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

1)下载模板

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

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

结果中的 passenger_flow_person_det_yolo7 即为基于人形检测的划区域客流统计应用模板,可使用如下命令下载模板:

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

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

2)创建工程

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

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

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

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

                            
                              passenger_flow_count

                            
                            |--
                            
                              bin
│  
                            
                            |--
                            
                              main.bat:应用执行入口
│  
                            
                            |--
                            
                              mock_task.toml:应用在本地执行时的输入输出配置,此应用默认使用本地视频文件为输入源,最终结果输出到另一本地视频文件,可根据需要修改

                            
                            |--
                            
                              CMake:存放一些自定义CMake函数

                            
                            |--
                            
                              data:存放应用运行所需要的图片、视频、文本、配置等数据
│  
                            
                            |--
                            
                              passenger_flow.mp4:客流统计测试用视频文件
│  
                            
                            |--
                            
                              simsun.ttc:中文字体库

                            
                            |--
                            
                              dependence
│  
                            
                            |--
                            
                              modelbox_requirements.txt:应用运行依赖的外部库在此文件定义,本应用依赖pillow、lap、scipy等工具包

                            
                            |--
                            
                              etc
│  
                            
                            |--
                            
                              flowunit:应用所需的功能单元存放在此目录
│  │  
                            
                            |--cpp:存放C++功能单元编译后的动态链接库,此应用没有C++
                            
                              功能单元
│  │  
                            
                            |--
                            
                              draw_passenger_bbox:客流画图功能单元
│  │  
                            
                            |--
                            
                              object_tracker:目标跟踪功能单元
│  │  
                            
                            |--
                            
                              yolov7_post:人形检测使用的是YOLO7模型,此处即为后处理功能单元

                            
                            |--flowunit_cpp:存放C++功能单元的源代码,此应用没有C++
                            
                              功能单元

                            
                            |--
                            
                              graph:存放流程图
│  
                            
                            |--
                            
                              passenger_flow_count.toml:默认流程图,使用本地视频文件作为输入源
│  
                            
                            |--
                            
                              modelbox.conf:modelbox相关配置

                            
                            |--
                            
                              hilens_data_dir:存放应用输出的结果文件、日志、性能统计信息

                            
                            |--
                            
                              model:推理功能单元目录
│  
                            
                            |--
                            
                              person_det:人形检测推理功能单元
│  │  
                            
                            |--
                            
                              person_det.toml:人形检测推理功能单元的配置文件
│  │  
                            
                            |--
                            
                              person_det.onnx:人形检测onnx模型

                            
                            |--
                            
                              build_project.sh:应用构建脚本

                            
                            |--
                            
                              CMakeLists.txt

                            
                            |--
                            
                              rpm:打包rpm时生成的目录,将存放rpm包所需数据

                            
                            |--rpm_copyothers.sh:rpm打包时的辅助脚本
                          

3)查看流程图

passenger_flow_count工程graph目录下存放流程图,默认的流程图passenger_flow_count.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 person detection with yolov7 for local video or rtsp video stream
                            
                            
                              "
                            
                            
                               # 应用的简单描述
[graph]
format 
                            
                            = 
                            
                              "
                            
                            
                              graphviz
                            
                            
                              "
                            
                            
                               # 流程图的格式,当前仅支持graphviz
graphconf 
                            
                            = 
                            
                              """
                            
                            
                              digraph passenger_flow_count {
                            
                            
    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=
                            
                              416
                            
                            , image_height=
                            
                              320
                            
                            
                              ]
 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.003921568, 0.003921568, 0.003921568
                            
                            
                              "
                            
                            
                              ]
 person_det[type
                            
                            =flowunit flowunit=person_det 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 
                            
                            ->
                            
                               person_det:input
 person_det: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  功能单元中,使用的是 JDE(Towards Real-Time Multi-Object Tracking)算法,算法介绍可参考论文,本应用使用的是简化版本,未使用人形reid特征值做匹配.

区域判断在  draw_passenger_bbox  功能单元draw_passenger_bbox.py的  draw_tracking_object  函数中:

                            
                                  def draw_tracking_object(self, img_data, tracking_objects):
 
                            
                            
                              '''
                            
                            
                              在图中画出跟踪对象的检测框和过线的行人数据
                            
                            
                              '''
                            
                            
                              
        thickness 
                            
                            = 
                            
                              2
                            
                            
                              
 GRAY 
                            
                            = (
                            
                              117
                            
                            , 
                            
                              117
                            
                            , 
                            
                              117
                            
                            
                              )
 GREEN 
                            
                            = (
                            
                              0
                            
                            , 
                            
                              255
                            
                            , 
                            
                              0
                            
                            
                              )
 YELLO 
                            
                            = (
                            
                              255
                            
                            , 
                            
                              255
                            
                            , 
                            
                              0
                            
                            
                              )
        # 画出区域边界线
        cv2.polylines(img_data, [self.area], True, YELLO, 
                            
                            
                              3
                            
                            
                              )
 flow_count 
                            
                            = 
                            
                              0
                            
                            
                              for
                            
                             track 
                            
                              in
                            
                            
                               tracking_objects:
            # 人形框的中心点
 c_x 
                            
                            = 
                            
                              int
                            
                            ((track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              0
                            
                            ] + track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              2
                            
                            ]) / 
                            
                              2
                            
                            
                              )
 c_y 
                            
                            = 
                            
                              int
                            
                            ((track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              1
                            
                            ] + track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              3
                            
                            ]) / 
                            
                              2
                            
                            
                              )
            # 判断人形框的中心点是否在区域内
            flag 
                            
                            =
                            
                               cv2.pointPolygonTest(self.area, (c_x, c_y), False)
 
                            
                            
                              if
                            
                             flag > 
                            
                              0
                            
                            
                              :
                # 区域内人形框用绿色,同时客流计数增加
 flow_count 
                            
                            += 
                            
                              1
                            
                            
                              
                cv2.rectangle(img_data, (track[
                            
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              0
                            
                            ], track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              1
                            
                            
                              ]),
 (track[
                            
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              2
                            
                            ], track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              3
                            
                            ]), GREEN, 
                            
                              2
                            
                            
                              )
 
                            
                            
                              else
                            
                            
                              :
                # 区域内人形框用灰色
                cv2.rectangle(img_data, (track[
                            
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              0
                            
                            ], track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              1
                            
                            
                              ]),
 (track[
                            
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              2
                            
                            ], track[
                            
                              "
                            
                            
                              bbox
                            
                            
                              "
                            
                            ][
                            
                              3
                            
                            
                              ]), GRAY, thickness)
        # 左上角显示实时的客流数量
 img_data 
                            
                            =
                            
                               self.put_chi_text(
 img_data, 
                            
                            
                              '
                            
                            
                              客流计数:%d
                            
                            
                              '
                            
                             % flow_count, (
                            
                              50
                            
                            , 
                            
                              20
                            
                            ), YELLO, 
                            
                              50
                            
                            
                              )
 
                            
                            
                              return
                            
                             img_data
                          

可以看到,我们使用了OpenCV的  pointPolygonTest  函数判断点与区域的位置关系。其中区域参数配置在draw_passenger_bbox.toml文件中,配置的是划定区域的4个顶点坐标,围成一个封闭的四边形:

                            
                              ...
# 自定义的配置项
[config]
area 
                            
                            = [
                            
                              "
                            
                            
                              0
                            
                            
                              "
                            
                            , 
                            
                              "
                            
                            
                              325
                            
                            
                              "
                            
                            , 
                            
                              "
                            
                            
                              1280
                            
                            
                              "
                            
                            , 
                            
                              "
                            
                            
                              25
                            
                            
                              "
                            
                            , 
                            
                              "
                            
                            
                              1280
                            
                            
                              "
                            
                            , 
                            
                              "
                            
                            
                              360
                            
                            
                              "
                            
                            , 
                            
                              "
                            
                            
                              0
                            
                            
                              "
                            
                            , 
                            
                              "
                            
                            
                              720
                            
                            
                              "
                            
                            
                              ]  # 客流统计的划定区域
...
                            
                          

5)模型训练

本应用中包含模型推理部分,ModelBox内置了主流的推理引擎,如TensorFlow,TensorRT,LibTorch,Ascend ACL,MindSpore,以及Windows版本中所用的ONNXRuntime。在开发推理功能单元时,只需要准备模型文件,并配置对应的toml文件,即可完成推理功能单元的开发,无需掌握推理引擎的开发接口.

passenger_flow_person_det_yolo7 模板中内置了人形检测模型,这个模型基于yolov7与yolov5-lite,训练数据集用的是开源的CUHK-SYSU,在ModelArts的Notebook环境中训练后,再转换成对应平台的模型格式:onnx格式可以用在Windows设备上,RK系列设备上需要转换为 rknn格式.

模型的训练与转换教程已经开放在AI Gallery中,其中包含训练数据、训练代码、模型转换脚本,以及详细的指导文档。开发者如果希望尝试自己训练模型,或者对模板中提供的模型效果不满意,可以进入  【ModelBox】行人检测模型训练 页面,点击右上角的 Run in ModelArts 按钮,跟随教程一步步操作,也可以修改其中的代码、更换新的数据集训练出自己的模型.

6)三方依赖库

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

7)查看输入输出配置

查看任务配置文件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中.

8)用启动脚本执行应用

启动应用前执行.\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. 小结

通过本教程,我们学习了一类客流统计应用——区域内客流统计,通常用于室外安防,或室内客流热力图,经过简单改造还可以实现区域入侵检测、人员在离岗检测等应用.

  。

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

最后此篇关于基于人形检测的划区域客流统计的文章就讲到这里了,如果你想了解更多关于基于人形检测的划区域客流统计的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com