计算机视觉/视频分析

使用 NVIDIA DeepStream 对特定帧区域应用推理

 

在高分辨率输入中检测物体是计算机视觉中的一个众所周知的问题。当感兴趣的是框架的某个区域时,不需要对整个框架进行推理。解决这个问题有两种方法:

  • 使用具有高输入分辨率的大型模型。
  • 将大图像分为块,并将较小的模型应用于每个块。

在许多方面,第一种方法是困难的。训练输入量大的模型通常需要更大的主干,使整个模型更笨重。训练或部署这样的模型也需要更多的计算资源。较大的模型被认为不适合在较小的设备上部署边缘。

第二种方法,将整个图像划分为块,并对每个块应用较小的模型,具有明显的优势。使用较小的模型,因此在训练和推理中需要较小的计算能力。将模型应用于高分辨率输入不需要再培训。较小的模型也被认为有利于边缘部署。

在这篇文章中,我们将讨论如何 NVIDIA DeepStream 可以帮助将较小的模型应用于高分辨率输入,以检测特定的帧区域。

视频监控系统概述

视频监控系统用于解决各种问题,例如识别行人、车辆和汽车。如今, 4K 和 8K 摄像机用于捕捉场景细节。军方将航空摄影用于各种目的,这也涵盖了大片区域。

随着分辨率的增加,像素数呈指数增长。处理如此大量的像素需要大量的计算能力,尤其是使用深度神经网络。

基于在建模过程中选择的输入维数,深度神经网络对固定形状的输入进行操作。这种固定大小的输入也称为感受野模型的。通常,在检测和分割网络中,感受野从 256 × 256 到 1280 × 1280 不等。

您可能会发现感兴趣的区域是一个小区域,而不是整个帧。在这种情况下,如果检测应用于整个帧,则不必要地使用计算资源。 DeepStream NvDsPreprocess 插件使您能够在框架的特定区域上进行计算。

DeepStream NvDsPreprocessing 插件

然而,当平铺应用于图像或帧时,尤其是在视频馈送上,您需要在推理管道中增加一个元素。这样的元素预计将执行可按流配置的分块机制、分块推理以及将多个分块的推理组合到单个帧上。

有趣的是, DeepStream 中提供了所有这些功能 Gst-NvDsPreprocess 可自定义插件。它提供了一个用于预处理输入流的自定义库接口。每个流都有自己的预处理要求。

默认插件实现提供以下功能:

  • 具有预定义感兴趣区域( ROI )或分片的流根据推理的网络要求进行缩放和格式转换。每流 ROI 在配置文件中指定。
  • 它从缩放和转换的 ROI 中准备一个原始张量,并通过用户元数据传递给下游插件。下游插件可以访问该张量进行推理。

DeepStream NvDsPreprocessing 插件

下一步是修改现有代码以支持平铺。

使用 NvdsPreprocessing 插件

定义管道内的预处理元素:

preprocess = Gst.ElementFactory.make("nvdspreprocess", "preprocess-plugin")

NvDsPreprocess需要一个配置文件作为输入:

preprocess.set_property("config-file", "config_preprocess.txt")

将预处理元素添加到管道:

pipeline.add(preprocess)

将元素链接到管道:

streammux.link(preprocess)
preprocess.link(pgie)

让 NvdsPreprocess 插件进行预处理

推断是通过NvDsInfer插件完成的,该插件具有帧预处理功能。

当您在NvDsInfer之前使用NvdsPreprocess插件时,您希望预处理(缩放或格式转换)由 NvdsPreprocess而不是NvDsInfer完成。为此,请将NvDsInferinput-tensor-meta属性设置为 true 。这使得NvdsPreprocess可以进行预处理,并使用附加为元数据的预处理输入张量,而不是NvDsInfer本身内部的预处理。

Gst-nvdspreprocess功能合并到现有管道中需要以下步骤。

定义nvdspreprocess插件并将其添加到管道:

preprocess = Gst.ElementFactory.make("nvdspreprocess", "preprocess-plugin")
pipeline.add(preprocess)

NvDsInferinput-tensor-meta属性设置为 true :

pgie.set_property("input-tensor-meta", True)

定义nvdspreprocess插件的配置文件属性:

preprocess.set_property("config-file", "config_preprocess.txt")

将预处理插件链接到主推理机(pgie)之前:

streammux.link(preprocess)
preprocess.link(pgie)

创建配置文件

Gst-nvdspreprocess配置文件使用密钥文件格式。有关更多信息,请参阅 Python 和 C 源代码中的config_preprocess.txt

  • [property]组配置插件的一般行为。
    • [group-<id>]组使用自定义库中的src-id值和custom-input-transformation-function为一组流配置 ROI 、 TILE 和 ull 帧。
    • [user-configs]组配置自定义库所需的参数,自定义库通过<string, string>的映射作为键值对传递给自定义库。然后,自定义库必须相应地解析这些值。

所需的最小值config_preprocess.txt类似于以下代码示例:

[property]
enable=1
target-unique-ids=1 # 0=NCHW, 1=NHWC, 2=CUSTOM
network-input-order=0 network-input-order=0
processing-width=960
processing-height=544
scaling-buf-pool-size=6
tensor-buf-pool-size=6 # tensor shape based on network-input-order
network-input-shape=12;3;544;960 # 0=RGB, 1=BGR, 2=GRAY network-color-format=0 # 0=FP32, 1=UINT8, 2=INT8, 3=UINT32, 4=INT32, 5=FP16
tensor-data-type=0
tensor-name=input_1 # 0=NVBUF_MEM_DEFAULT 1=NVBUF_MEM_CUDA_PINNED 2=NVBUF_MEM_CUDA_DEVICE 3=NVBUF_MEM_CUDA_UNIFIED
scaling-pool-memory-type=0 # 0=NvBufSurfTransformCompute_Default 1=NvBufSurfTransformCompute_GPU 2=NvBufSurfTransformCompute_VIC
scaling-pool-compute-hw=0 # Scaling Interpolation method # 0=NvBufSurfTransformInter_Nearest 1=NvBufSurfTransformInter_Bilinear 2=NvBufSurfTransformInter_Algo1 # 3=NvBufSurfTransformInter_Algo2 4=NvBufSurfTransformInter_Algo3 5=NvBufSurfTransformInter_Algo4 # 6=NvBufSurfTransformInter_Default
scaling-filter=0
custom-lib-path=/opt/nvidia/deepstream/deepstream/lib/gst-plugins/libcustom2d_preprocess.so
custom-tensor-preparation-function=CustomTensorPreparation [user-configs]
pixel-normalization-factor=0.003921568
#mean-file=
#offsets= [group-0]
src-ids=0;1;2;3
custom-input-transformation-function=CustomAsyncTransformation
process-on-roi=1
roi-params-src-0=0;540;900;500;960;0;900;500;0;0;540;900;
roi-params-src-1=0;540;900;500;960;0;900;500;0;0;540;900;
roi-params-src-2=0;540;900;500;960;0;900;500;0;0;540;900;
roi-params-src-3=0;540;900;500;960;0;900;500;0;0;540;900;

Processing-widthprocessing-height是指切片在整个帧上的宽度和高度。

对于network-input-shape,当前配置文件配置为最多运行 12 个 ROI 。要增加 ROI 计数,请将第一维度增加到所需数量,例如network-input-shape=12;3;544;960

在当前配置文件config-preprocess.txt中,每个源有三个 ROI ,所有四个源总共有 12 个 ROI 。所有源的总 ROI 不得超过network-input-shape参数中指定的第一个维度。

Roi-params-src-<id>表示source-<id>的 III 坐标。如果启用了process-on-roi,则为每个 ROI 指定定义 ROI 的left;top;width;heightGst-nvdspreprocess没有将重叠块中的对象检测和计数结合起来。

密码

C 代码可从/ opt / NVIDIA / deepstream / deepstream-6.0 / source / app / sample _ app / deepstream-preprocess-test 下载。

Python 代码可从 NVIDIA-AI-IOT/deepstream_python_apps github 回购。

后果

图 1 显示了您可以指定一个或多个平铺。检测到平铺内的对象,检测不应用于帧的其余区域。

Image showing the application of NVIDIA DeepStream Gst-nvdspreprocess plugin.
图 1 显示了使用 Gst nvdspreprocess 插件在瓷砖上应用的检测。绿色框显示平铺边界,红色框显示平铺内检测到的对象。

Gst-nvdspreprocess允许对视频的特定部分(磁贴或感兴趣区域)应用推理。使用Gst-nvdspreprocess,可以在单个帧上指定一个或多个平铺。

以下是在整个帧上应用yolov4与在磁贴上应用yolov4时的性能指标。通过将流的数量增加到解码器或计算饱和点来收集性能指标,并且进一步增加流不会显示性能增益。

1080p 的视频分辨率用于 NVIDIA V100 GPU 的性能基准。考虑性能和磁贴数量之间的权衡,因为放置太多的磁贴会增加计算需求。

使用NvDsPreprocess平铺有助于对视频中需要的部分进行选择性推断。例如,在图 1 中,推理只能在人行道上使用,而不能在整个框架上使用。

GST-NVDSAnalyticsnvinfer(主检测器)和nvtracker附加的元数据执行分析。Gst-nvdsanalytics可应用于瓷砖,用于 ROI 过滤、过度拥挤检测、方向检测和线交叉。

 

Tags