将自定义模型与 DeepStream 结合使用#

NVIDIA® DeepStream SDK 在 NVIDIA® Tesla® 或 NVIDIA® Jetson 平台上可以进行自定义,以支持用于对象检测和分类的自定义神经网络。您可以创建自己的模型。您必须在 nvinfer 配置文件(例如,config_infer_primary.txt)的 [property] 组中指定适用的配置参数。您必须指定的配置参数包括

  • model-file (Caffe 模型)

  • proto-file (Caffe 模型)

  • onnx-file (ONNX 模型)

  • model-engine-file,如果已生成

  • INT8 模式的 int8-calib-file

  • mean-file,如果需要

  • offsets,如果需要

  • maintain-aspect-ratio,如果需要

  • parse-bbox-func-name(仅限检测器)

  • parse-classifier-func-name(仅限分类器)

  • custom-lib-path

  • network-type

  • model-color-format

  • process-mode

  • engine-create-func-name

  • infer-dims (UFF 模型)

自定义模型实现接口#

nvinfer 支持以下用途的接口

  • 用于自定义神经网络检测器和分类器的自定义边界框解析

  • 对于 NVIDIA® TensorRT™ 本身不支持的层的 IPlugin 实现

  • 在网络具有多个输入层的情况下初始化非图像输入层

  • 使用 TensorRT Layer API 而不是模型解析 API 创建 CUDA 引擎。在此处阅读有关 TensorRT 文档的更多信息: https://docs.nvda.net.cn/deeplearning/tensorrt/developer-guide/index.html

  • IModelParser 接口,用于解析模型并在 INetworkDefinition 中填充层

模型的所有接口实现都必须放入单个独立的共享库中。 nvinfer 使用 dlopen() 动态加载库,使用 dlsym() 查找已实现的接口,并根据需要调用接口。有关接口的更多信息,请参阅头文件 nvdsinfer_custom_impl.h

自定义输出解析#

对于检测器,您必须编写一个库,该库可以从输出层解析边界框坐标和对象类别。对于分类器,库必须从输出层解析对象属性。例如,在分割模型中,库必须从输出层解析边界框、对象类别和掩码。您可以在源代码目录 sources/libs/nvdsinfer_customparser 中找到示例代码和 makefile。生成的库路径和函数名称必须使用配置参数指定,如自定义模型部分所述。sources/libs/nvdsinfer_customparser 中的 README 文件包含如何使用此自定义解析器的示例。当前版本支持以下输出解析器

  • MaskRCNN

  • SSD

  • YoloV3 / YoloV3Tiny / YoloV2 / YoloV2Tiny

  • DetectNet

IPlugin 实现#

DeepStream 支持包含 TensorRT 不支持但通过 IPlugin 接口的实现支持的网络的层。objectDetector_SSDobjectDetector_FasterRCNNobjectDetector_YoloV3 示例应用程序显示了 IPlugin 实现的示例。DeepStream 支持用于自定义层的 NVIDIA® TensorRT™ 插件。 Gst-nvinfer 插件现在支持 TensorRT 5.0 中引入的 IPluginV2 和 IPluginCreator 接口。对于 caffemodel 以及为了向后兼容现有插件,它还支持以下接口

  • nvinfer1::IPluginFactory

  • nvuffparser::IPluginFactory

  • nvuffparser::IPluginFactoryExt

  • nvcaffeparser1::IPluginFactory

  • nvcaffeparser1::IPluginFactoryExt

  • nvcaffeparser1::IPluginFactoryV2

有关新的和已弃用的插件接口的详细信息,请参阅 TensorRT 文档。

如何使用 IPluginCreator#

要使用新的 IPluginCreator 接口,您必须在独立的自定义库中实现该接口。必须通过使用 custom-lib-path 键指定库的路径名,将此库传递给 Gst-nvinfer 插件。 Gst-nvinfer 使用 dlopen() 打开库,这会导致插件在 TensorRT 中注册。自定义库和 Gst-nvinfer 之间没有进一步的直接交互。 TensorRT 根据需要调用自定义插件函数。 SDK 随附的 SSD 示例提供了使用 IPluginV2 和 IPluginCreator 接口的示例。此示例已从 TensorRT 调整。

如何使用 IPluginFactory#

要使用 IPluginFactory 接口,您必须在独立的自定义库中实现该接口。通过在插件的配置文件中使用 custom-lib-path 键指定库的路径名,将此库传递给 Gst-nvinfer 插件。自定义库必须实现适用的函数

  • NvDsInferPluginFactoryCaffeGet

  • NvDsInferPluginFactoryCaffeDestroy

  • NvDsInferPluginFactoryUffGet

  • NvDsInferPluginFactoryUffDestroy

  • NvDsInferPluginFactoryRuntimeGet

  • NvDsInferPluginFactoryRuntimeDestroy

这些结构在 nvdsinfer_custom_impl.h 中定义。函数定义必须与头文件中的名称相同。 Gst-nvinfer 使用 dlopen() 打开自定义库并查找名称。

对于 Caffe 文件#

在解析和构建 Caffe 网络期间,Gst-nvinfer 查找 NvDsInferPluginFactoryCaffeGet。如果找到,它会调用该函数以获取 IPluginFactory 实例。根据返回的 IPluginFactory 的类型,Gst-nvinfer 使用 ICaffeParser 接口的方法 setPluginFactory()setPluginFactoryExt()setPluginFactoryV2() 之一设置工厂。在构建和序列化网络后,Gst-nvinfer 查找 NvDsInferPluginFactoryCaffeDestroy 并调用它以销毁 IPluginFactory 实例。

对于 Uff 文件#

在解析和构建 Caffe 网络期间,Gst-nvinfer 查找 NvDsInferPluginFactoryUffGet。如果找到,它会调用该函数以获取 IPluginFactory 实例。根据返回的 IPluginFactory 的类型,Gst-nvinfer 使用 IUffParser 接口的方法 setPluginFactory()setPluginFactoryExt() 之一设置工厂。在构建和序列化网络后,Gst-nvinfer 查找 NvDsInferPluginFactoryUffDestroy 并调用它以销毁 IPluginFactory 实例。

在反序列化期间#

如果反序列化模型需要 NvInfer1::IPluginFactory 的实例,则自定义库还必须实现 NvDsInferPluginFactoryRuntimeGet() 和可选的 NvDsInferPluginFactoryRuntimeDestroy()。在反序列化期间,Gst-nvinfer 调用库的 NvDsInferPluginFactoryRuntimeGet() 函数以获取 IPluginFactory 实例,然后在 Gst-nvinfer 反初始化期间找到该函数时,调用 NvDsInferPluginFactoryRuntimeDestroy 以销毁该实例。 SDK 随附的 FasterRCNN 示例提供了将 IPluginV2+nvcaffeparser1::IPluginFactoryV2 接口与 DeepStream 结合使用的示例。此示例已从 TensorRT 调整。它还提供了使用旧版 IPlugin + nvcaffeparser1::IPluginFactory + Gst-nvinfer 1::IPluginFactory 接口以实现向后兼容性的示例。

输入层初始化#

DeepStream 支持为具有多个输入层的网络初始化非图像输入层。这些层仅在首次推理调用之前初始化一次。 objectDetector_FasterRCNN 示例应用程序显示了实现的示例。

自定义模型的 CUDA 引擎创建#

DeepStream 支持为非 Caffe、UFF 或 ONNX 格式的模型或必须从 TensorRT Layer API 创建的模型创建 TensorRT CUDA 引擎。 objectDetector_YoloV3 示例应用程序显示了实现的示例。当在管道中使用单个自定义库用于多个 nvinfer 插件实例时,每个实例都可以有自己的 engine-create-func-name 实现,这可以在配置文件中指定。一个示例是具有不同类型的 yolo 模型的背靠背检测器管道。

用于自定义模型解析的 IModelParser 接口#

这是用于解析和填充 TensorRT 网络 (INetworkDefinition) 的“CUDA 引擎创建”接口的替代方案。objectDetector_YoloV3 示例应用程序显示了实现的示例。