Python 示例应用和绑定源码详情#
示例应用程序源码详情#
下表显示了 Python 示例应用程序在 NVIDIA-AI-IOT/deepstream_python_apps 下的位置。
Python 示例应用程序源码详情# 参考测试应用程序
GitHub 仓库内的路径
描述
简单测试应用程序 1
apps/deepstream-test1
如何为单个 H.264 流使用 DeepStream 元素的简单示例:filesrc → decode → nvstreammux → nvinfer (主要检测器) → nvdsosd → renderer。
简单测试应用程序 2
apps/deepstream-test2
如何为单个 H.264 流使用 DeepStream 元素的简单示例:filesrc → decode → nvstreammux → nvinfer (主要检测器) → nvtracker → nvinfer (二级分类器) → nvdsosd → renderer。
简单测试应用程序 3
apps/deepstream-test3
基于 deepstream-test1(简单测试应用程序 1)构建,演示如何
在 pipeline 中使用多个源
使用 uridecodebin 接受任何类型的输入 (例如 RTSP/File)、任何 GStreamer 支持的容器格式以及任何编解码器
配置 Gst-nvstreammux 以生成一批帧并在其上进行推理,以获得更好的资源利用率
提取流元数据,其中包含有关批处理缓冲区中帧的有用信息
简单测试应用程序 4
apps/deepstream-test4
基于 deepstream-test1 构建,用于单个 H.264 流:filesrc、decode、nvstreammux、nvinfer、nvdsosd、renderer,以演示如何
在 pipeline 中使用 Gst-nvmsgconv 和 Gst-nvmsgbroker 插件
创建 NVDS_META_EVENT_MSG 类型元数据并将其附加到缓冲区
将 NVDS_META_EVENT_MSG 用于不同类型的对象,例如车辆和人
如果通过 extMsg 字段扩展元数据,则实现“copy”和“free”函数以供使用
USB 摄像头源应用程序
apps/deepstream-test1-usbcam
修改后的简单测试应用程序 1,用于处理来自 USB 摄像头的单个流。
RTSP 输出应用程序
apps/deepstream-test1-rtsp-out
修改后的简单测试应用程序 1,用于通过 RTSP 输出可视化流。
图像数据访问应用程序
apps/deepstream-imagedata-multistream
基于简单测试应用程序 3 构建,演示如何
在 pipeline 中将解码帧作为 NumPy 数组访问
检查检测到的对象的检测置信度(需要 DBSCAN 或 NMS 聚类)
修改帧并查看 pipeline 中下游反映的更改
使用 OpenCV 注释帧并将它们保存到文件
SSD 检测器输出解析器应用程序
apps/deepstream-ssd-parser
演示如何为来自 Triton Inference Server 的推理输出执行自定义后处理
在 Triton Inference Server 上使用 SSD 模型进行对象检测
通过配置文件设置启用 Triton Inference Server 的自定义后处理和原始张量导出
在 pipeline 中访问推理输出张量,以便在 Python 中进行后处理
将检测到的对象添加到元数据
将 OSD 可视化输出到 MP4 文件
光流应用程序
apps/deepstream-opticalflow
演示如何获取光流元数据,并演示如何
将光流向量作为 numpy 数组访问
使用获取的流向量和 OpenCV 可视化光流
分割应用程序
apps/deepstream-segmentation
演示如何获取分割元数据,并演示如何
访问分割掩码作为 numpy 数组
使用获取的掩码和 OpenCV 可视化分割
分析应用程序
apps/deepstream-nvdsanalytics
演示如何使用 nvdsanalytics 插件并获取分析元数据
运行时源添加/删除应用程序
apps/runtime_source_add_delete
演示如何在运行时添加和删除输入源
面部编辑应用程序
apps/deepstream-imagedata-multistream-redaction
演示如何访问图像数据并执行面部编辑
RTSP 输入/输出应用程序
apps/deepstream-rtsp-in-rtsp-out
具有 RTSP 输入和输出的多流 pipeline
预处理应用程序
apps/deepstream-preprocess-test
演示如何使用 nvdspreprocess 插件并在提供的 ROI 上执行自定义预处理
解复用器应用程序
apps/deepstream-demux-multi-in-multi-out
基于 deepstream-test3 构建,演示如何使用 nvstreamdemux 插件来拆分批次并输出单独的缓冲区/流。
CuPy 应用程序
apps/deepstream-imagedata-multistream-cupy
演示如何在多流源中将 GPU 缓冲区作为 CuPy 数组访问,并在适当位置修改图像。
Segmask 应用程序
apps/deepstream-segmask
演示如何从流元数据中提取 NvOSD_MaskParams,以及如何调整大小和二值化掩码数组以获得可解释的分割掩码。
自定义绑定应用程序
apps/deepstream-custom-binding-test
演示如何使用 NvDsUserMeta 将 Python 绑定中编写的自定义数据结构附加到缓冲区/从缓冲区中提取。
Python 绑定和应用程序开发#
本节提供有关在 Python 中进行 DeepStream 应用程序开发的详细信息。Python 绑定在此处可用: NVIDIA-AI-IOT/deepstream_python_apps 。在此处阅读有关 Pyds API 的更多信息 here。
先决条件#
Ubuntu 22.04
DeepStream SDK 7.0 或更高版本
Python 3.10
Gst Python v1.20.3
如果 Jetson 上缺少 Gst python 安装,请按照 bindings readme 中的说明进行操作。
运行示例应用程序#
克隆
deepstream_python_apps
仓库到<DeepStream ROOT>/sources
下git clone https://github.com/NVIDIA-AI-IOT/deepstream_python_apps
这将创建以下目录
<DeepStream ROOT>/sources/deepstream_python_apps
Python 应用程序位于
apps
目录下。进入每个应用程序目录并按照 README 中的说明进行操作。注意
应用程序配置文件包含模型的相对路径。
Pipeline 构建#
DeepStream pipeline 可以使用 Gst Python(GStreamer 框架的 Python 绑定)构建。请参阅示例应用程序主函数以获取 pipeline 构建示例。
元数据访问#
DeepStream 元数据包含推理结果和分析中使用的其他信息。元数据附加到每个 pipeline 组件接收的 Gst Buffer
。SDK 元数据文档和 API 指南中详细描述了元数据格式。SDK 元数据库是在 C/C++ 中开发的。Python 绑定提供从 Python 应用程序访问元数据的功能。请在 NVIDIA-AI-IOT/deepstream_python_apps 中查找 Python 绑定源码和软件包。
内存管理#
元数据的内存由 Python 和 C/C++ 代码路径共享。例如,元数据项可以由 Python 中编写的 probe 函数添加,并且需要由 C/C++ 中编写的下游插件访问。deepstream-test4 应用程序包含此类用法。Python 垃圾回收器无法查看 C/C++ 中的内存引用,因此无法安全地管理此类共享内存的生命周期。由于这种复杂性,Python 对元数据内存的访问通常通过引用来实现,而不声明所有权。
分配#
当在 Python 中分配元数据对象时,绑定提供分配函数以确保对象的正确内存所有权。如果使用构造函数,则当其 Python 引用终止时,该对象将被垃圾回收器回收。但是,下游的 C/C++ 代码仍然需要访问该对象,因此该对象必须在这些 Python 引用之外持续存在。示例:要分配 NvDsEventMsgMeta
实例,请使用此
msg_meta = pyds.alloc_nvds_event_msg_meta() *# get reference to allocated instance without claiming memory ownership*
而不是此
msg_meta = NvDsEventMsgMeta() *# memory will be freed by the garbage collector when msg_meta goes out of scope in Python*
分配器可用于以下结构
NvDsVehicleObject: alloc_nvds_vehicle_object()
NvDsPersonObject: alloc_nvds_person_object()
NvDsFaceObject: alloc_nvds_face_object()
NvDsEventMsgMeta: alloc_nvds_event_msg_meta()
NvDsEvent: alloc_nvds_event()
NvDsPayload: alloc_nvds_payload()
通用 buffer: alloc_buffer(size)
字符串访问#
某些元数据结构包含字符串字段。以下部分提供有关访问它们的详细信息。
设置字符串字段#
设置字符串字段会导致在底层 C++ 代码中分配字符串缓冲区。
obj.type = "Type"
这将导致分配内存缓冲区,并将字符串“TYPE”复制到其中。此内存归 C 代码所有,稍后将被释放。要在 Python 代码中释放缓冲区,请使用
pyds.free_buffer(obj.type)
注意
NvOSD_TextParams.display_text
字符串现在在分配新字符串时自动释放。
读取字符串字段#
直接读取字符串字段会以 int 形式返回字段的 C 地址,例如
obj = pyds.NvDsVehicleObject.cast(data);
print(obj.type)
这将打印一个 int,表示 C 中 obj.type
的地址(它是 char*)。要检索此字段的字符串值,请使用 pyds.get_string()
,例如
print(pyds.get_string(obj.type))
类型转换#
某些元数据实例以 GList 形式存储。要访问 GList 节点中的数据,需要将数据字段强制转换为适当的结构。此强制转换通过目标类型的 cast() 成员函数完成
NvDsBatchMeta.cast
NvDsFrameMeta.cast
NvDsObjectMeta.cast
NvDsUserMeta.cast
NvDsClassifierMeta.cast
NvDsDisplayMeta.cast
NvDsLabelInfo.cast
NvDsEventMsgMeta.cast
NvDsVehicleObject.cast
NvDsPersonObject.cast
在 v0.5 版本中,提供了独立的 cast 函数。这些函数现在已弃用,并被上面的 cast() 函数取代
glist_get_nvds_batch_meta
glist_get_nvds_frame_meta
glist_get_nvds_object_meta
glist_get_nvds_user_meta
glist_get_nvds_classifier_meta
glist_get_nvds_display_meta
glist_get_nvds_label_info
glist_get_nvds_event_msg_meta
glist_get_nvds_vehicle_object
glist_get_nvds_person_object
示例
l_frame = batch_meta.frame_meta_list
frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
回调函数注册#
添加到 NvDsUserMeta 的自定义元数据需要自定义复制和释放函数。元数据库依赖于这些自定义函数来执行自定义结构的深层复制,并释放已分配的资源。这些函数在 NvDsUserMeta 结构中注册为回调函数指针。回调函数使用以下函数注册
pyds.set_user_copyfunc(NvDsUserMeta_instance, copy_function)
pyds.set_user_releasefunc(NvDsUserMeta_instance, free_func)
注意
在应用程序退出之前,需要使用 bindings 库取消注册回调。bindings 库当前保留对已注册函数的全局引用,并且这些引用不能在 bindings 库卸载之后持续存在,而 bindings 库卸载发生在应用程序退出时。使用以下函数取消注册所有回调
pyds.unset_callback_funcs()
有关回调注册和注销的示例,请参阅 deepstream-test4 示例应用程序。
限制:bindings 库目前仅支持每个应用程序的一组回调函数。将使用最后注册的函数。
优化和实用程序#
Python 解释通常比运行编译后的 C/C++ 代码慢。为了提供更好的性能,某些操作在 C 中实现,并通过 bindings 接口公开。这目前是实验性的,并且会随着时间的推移而扩展。以下优化函数可用
pyds.NvOSD_ColorParams.set(double red, double green, double blue, double alpha)
这是一个简单的函数,其执行的操作与以下操作相同
txt_params.text_bg_clr.red = red txt_params.text_bg_clr.green = green txt_params.text_bg_clr.blue = blue txt_params.text_bg_clr.alpha = alpha
这些操作在 deepstream_test_4.py 中的每个对象上执行,导致聚合处理时间减慢 pipeline 的速度。将此函数推送到 C 层有助于提高性能。
generate_ts_rfc3339 (buffer, buffer_size)
此函数使用根据 RFC3339 生成的时间戳填充输入缓冲区:
%Y-%m-%dT%H:%M:%S.nnnZ\0
图像数据访问#
解码后的图像可以通过 get_nvds_buf_surface
函数作为 NumPy
数组访问。此函数在 API 指南中记录。有关图像数据用法的示例,请参阅 deepstream-imagedata-multistream
示例应用程序。