393浏览
查看: 393|回复: 1

[官方资料] NVIDIA Jetson Nano 2GB 系列文章(38):nvdsanalytics视频分析插件

[复制链接]
本帖最后由 jetson小助理 于 2021-11-17 10:48 编辑

nvdsanalytics 视频分析插件是 DeepStream 5.0 添加的功能,对 nvinfer(主检测器)和 nvtracker 附加的元数据执行分析,目前主要针对涉及感兴趣区域(ROI)的过滤、过度拥挤检测、方向检测和跨线统计等四大功能,如下表:


功能说明
ROI 过滤此功能检测 ROI 中是否存在目标类别的对象,结果作为每个对象的元数据附加,以及每帧 ROI 中的对象总数。
拥挤检测在“ROI 过滤”的前提下,检测每帧对象总数是否处于过度拥挤的状态,就是检测 ROI 中的对象数量是否超过预先配置的阈值。
方向检测使用对象位置历史记录和当前帧信息检查对象是否遵循预配置的方向。结果作为每个对象的元数据附加。
跨线统计此功能检查对象是否遵循虚拟线的预配置方向,以及是否已越过虚拟线。当测线交叉时,结果将附加到对象上,同时还会附加帧元,其中累积计数与测线交叉的每帧计数一起附加。

可以看出这是 NVIDIA 经过实际项目的要求所增加的功能插件,主要就是针对视频内的我们所指定的“某个区块(兴趣区,ROI)”或“某条线(跨越线)”范围中的标的物件,进行“物件动向”的分析与统计(如下图)。大部分的使用场景是在道路流量分析的应用,但这也可以应用在營建工地、生产工厂、楼宇、校园、消防设施的危险区(danger zone)监控,实用性非常之高。

qw2.jpg

有经验的开发人员就会很清楚,如果缺少 nvdsanalytics 这个插件的时候,则开发者需要自行从 nvtracker 里面抽取相关数据,然后与兴趣区或跨越线进行持续比对,确认是否属于要列入统计数据的物件,至于“动向分析”功能,更需要大量的“前后帧”位置比对去进行判断,这些开发的工作量是相当艰辛、计算量是非常巨大的,如今在 DeepStream 里面只要轻松调用 nvdsanalytics 插件,就能轻松地完成很复杂的工作。

在 DeepStream 开发套件里的 deepstream-nvdsanalytics-test 是 C/C++版本的范例代码,先前文章里带着大家安装过的 deepstream_python_apps 范例中,也提供 Python 版本的代码,在范例路径下面的 deepstream-nvdsanalytics 里面。

Gst-nvdsanalytics 工作原理

DeepStream 一直令人赞赏的一个特色,就是将插件的接口做得十分简单,因此在开始执行范例代码之前,我们需要先对这个插件有个初步了解,请参考下面链接的原厂说明:https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_plugin_gst-nvdsanalytics.html

下图是 Gst-nvdsanalytics 的基本工作原理图:

qw3.jpg

整个执行流程其实就是很简单的四个步骤:
  • 接受上游(左边)的 nvinfer 与 nvtracker 元件发送的批处理缓冲区(GstBuffer + NvDsBatchMeta),并从中提取元数据;
  • 将元数据传递到低阶 nvds_analytics 接口(上图下方)进行处理;
  • 低阶接口根据为每个流的所制定配置(前面所列的四项功能)的规则去执行分析;
  • 然后返回添加了分析元数据的作为输出,这是每个跟踪对象以及整个帧的分析结果。

这个插件伴随着 NvDsAnalyticsFrameMetaNvDsAnalyticsObjInfo 两组元数据,可以在 DeepStream 开发包的sources/includes/nvds_analytics_meta.h 找到完整的定义,也可以在https://docs.nvidia.com/metropolis/deepstream/sdk-api/Meta/analytics.html 找到使用说明。这里也简单说明一下,对于后面说明代码时会有帮助:

  • NvDsAnalyticsFrameMeta:定义“帧级(frame level)”的数据内容,配合所提供的四项功能,主要结构如下:

    ocStatus(数据类型:bool):在给定的ROI 区域内
    objInROIcnt(数据类型:unit32_t):在ROI 区域内检测到的物件总数
    objLCCurrCnt(数据类型:unit64_t):保存当前帧中跨线物件的数量objLCCumCnt(数据类型:unit64_t):保存已配置线条的累计跨线物件数量
    unique_id(数据类型:guint):保存 nvdsanalytics 实例的唯一标识符objCnt(数据类型:unit64_t):保存每帧里面每个类 ID 的对象总数

  • NvDsAnalyticsObjInfo:定义“对象(object level)”的数据内容,配合所提供的四项功能,主要结构如下:

    roiStatus(数据类型:字符串数组):保存对象所在的 ROI 标签数组
    ocStatus(数据类型:字符串数组):保存对象所在的 ROI 标签数组保存对象所在的过度拥挤标签数组
    lcStatus(数据类型:字符串数组):保存对象已跨越的线交叉标签数组
    dirStatus(数据类型:字符串):保存跟踪对象的方向字符串
    unique_id(数据类型:guint):保存 nvdsanalytics 实例的唯一标识符

前面工作流最右边的输出,是以帧级的 NvDsAnalyticsFrameMeta 结构进行封装,想要调用时就定义一个用户元,将 meta_type 设置为NVDS_USER_FRAME_META_NVDSANALYTICS。然后将用户元添加到 NvDsFrameMeta 的 frame_user_meta_list 成员。

分析(每个检测到的对象)的输出结果封装在 NvDsAnalyticsObjInfo 结构中,同样再定义定义一个用户元,将类型设置为 NVDS_USER_OBJ_META_NVDSANALYTICS,然后将这个用户元添加到 NvDsObjectMeta 的 obj_user_meta_list 成员中。

上述步骤与数据结构,已经将大部分 nvdsanalytics 插件的工作都部署的差不多了,剩下就是启动并监听交互信息的部分。

项目配置文件说明

这个范例的代码与前面几个范例的工作流程是一致的,只是这里接受多个输入源,包括 H264/H265 视频文件与 RTSP 视频流,因此需要建立多个队列(queue)作为缓冲来处理,至于 nvanalytics_src_pad_buffer_probe 部分与 test1 的 osd_sink_pad_buffer_probe 代码结构的逻辑也是相近的,因此请自行根据先前代码内容进行类比,这里就不花力气再重复那些冗余的内容。

不过这个项目里面的配置文件与前面的项目有比较大的不同之处,因此这里就花点时间探索这部分的细节。范例的配置文件为 config_nvdsanalytics.txt,一共有 5 个配置组。

这个插件一共有以下的 5 个配置组:

  • [property]:配置插件的一般行为,这是唯一的强制(必须有的)组
  • [roi-filtering-stream-<n>]:为第<n>个流配置 roi 筛选规则参数,无数量限制
  • [overcrowding-stream<n>]:为第<n>个流配置过度拥挤参数的阈值
  • [direction-detection-stream-<n>]:为第<n>个流配置方向检测参数
  • [line-crossing-stream-<n>]:为第<n>个流配置跨线参数

在[property]组里面的参数是大家比较熟悉的,其他组里面有几个用法比较特殊的参数,在这里挑出来说明:

  • roi-<label>:用在[roi-filtering-stream-<n>]与[overcrowding-stream-<n>]这两个组,可自行配置<label>名称,例如“RF”、“OC”、“DangerZone”等,后面设定一组“多(3 以上)边形”坐标,使用“;”作为间隔,坐标顺序为“x1;y1;x2;y2;x3; y3;...”,例如“roi-DangerZone=295;643;579;634;642;913;56;828”、“roi-OC=295;643;579; 634;642;913;56;828”等,可以为每个视频源指定多个的兴趣区。
  • direction-<label>:用在[direction-detection-stream-<n>]组,可自行配置<label>内容,例如“South”、“East”、“Forward”等等,后面给定一组(x1;y1;x2;y2)坐标来表示方向,当对象沿这个方向移动时,前面设定的标签将作为用户元数据附加到对象里,可以为每个视频源指定多个方向。
  • line-crossing-<label>:用在[line-crossing-stream-<n>]组里面,同样可自行设定<label>内容,例如“Entry”、“Exit”、“Start”等,后面的设定值定义两组线的四个坐标,依序为(x1d;y1d;x2d;y2d;x1c;y1c;x2c;y2c),其中第一组(x1d;y1d;x2d;y2d)代表移动的方向,如下图“向下方的黄色箭头”所表示;第二组(x1c;y1c;x2c;y2c)标示“跨越线”的坐标,如下图与黄色箭头所交叉的“横向线”。

    qw4.jpg
    只有当物件“以符合要求的方向通过跨越线”,才算符合这里的统计要求,才会纳入这个视频分析的计数之中,这个功能定义的十分完善。
    同样的,我们可以为每个视频流提供多组这种跨越线的配置。
  • extended:用在[line-crossing-stream-<n>]组,这个开关设定值是为了将上一个参数做个扩展,当设置为“0(关闭)”的时候,则计算物件通过的参考依据就仅止于“两条线的交叉点”,如果设置为“1(开启)”时,就会以(x1c;y1c;x2c;y2c)整条线作为参考依据。
  • mode:用在[line-crossing-stream-<n>]与[direction-detection-stream-<n>]这两个组,设定“检测方向”与“配置方向”一致性的严格程度,有“loose(宽松)”、“strict(严格)”、“balance(平衡)”三种选项,例如“loose”只检查物体是否已越过线,并且该物体保持同一方向行进即可,公差可能会很高。

以上是比较复杂的参数与用法的简单说明,如果需要所有参数的完整说明,请直接参考https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_plugin_gst-nvdsanalytics.html下方的“Configuration File Parameters”内容。

接下来就开始执行这个很有用处的范例,透过修改参数值来感受用途。

范例执行

由于 deepstream_nvdsanalytics.py 这个代码可以接受多个视频输入,因此需要使用“file:///”格式给定输入文件完整路径,为了简化指令长度,我们在工作目录下使用软链接来提供视频文件路径:
  1. ln -s ../../../../samples/streams/sample_720p.h264  ~/test.h264
  2. python3 deepstream_nvdsanalytics.py file:///home/nvidia/test.h264
复制代码

下面是这个范例的执行画面:

qw5.jpg

接下去看看所显现的数据代表什么意思,下面是我们截取第 649 帧图像的检测结果:
  1. ##################################################
  2. Object 503 moving in direction: North
  3. Object 499 moving in direction: North
  4. Object 526 roi status: ['RF']
  5. Objs in ROI: {'RF': 1}
  6. Linecrossing Cumulative: {'Exit': 20}
  7. Linecrossing Current Frame: {'Exit': 0}
  8. Frame Number= 649 stream id= 0 Number of Objects= 7 Vehicle_count= 5 Person_count= 2
复制代码

  • 最上面两行表示物件编号 503 与 499 行进方向为“North”
  • 第 3 行在 RF 兴趣区检测到编号 526 物件(图左方站立的人)
  • 第 4 行显示兴趣区 RF 目前检测到“1”个物件
  • 第 5 行统计出“累积通过”右方黄色线的物件数量为“20”
  • 第 6 行显示“正在通过”右方黄色线的物件数量为“0”
  • 第 7 行显示这是“第 649 帧”,检测到“7”个物件,其中有“5”辆车与“2”个人

如何?这个插件的功能很棒吧,可以让你自由地设定要监控的区域,并且非常有效率地按照你所设定的要求,反馈对应的统计数据。

安卓机器人  中级技神

发表于 2021-11-19 15:14:43

这些先收藏了,4G版还在吃灰中,希望早见太阳
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2022 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail