NVIDIA DeepStream插件之Gst-nvtracker
- 1. 源由
- 2. 基础知识
- 3. Gst-nvtracker插件
- 3.1 插件参数
- 3.2 插件API接口
- 4. 分析问题
- 5. 总结
- 6. 参考资料
1. 源由
这篇的主要目的是稍微吐槽下NVIDIA的设计,当然其实他们做的还是不错的(从系统架构设计角度看,插件采用so动态库方式是不错的,只不过技巧上还可以更加不错)。
本次涉及到使用 BYTETrack
开源代码的 DeepStream
集成,在实际使用的时候遇到非常郁闷、糟心的事情。N多年前的开源代码,已经被证明或者成熟应用的东西,为啥不好用(报错)???
- Gstnvtracker: Optional NvMOT_RetrieveMiscData not implemented
daniel@daniel-nvidia:~/Work/jetson-fpv/utils/dsyolo$ deepstream-app -c source_config_yolov8s.txt
** WARN: <parse_tracker:1604>: Unknown key 'enable-batch-process' for group [tracker]
gstnvtracker: Loading low-level lib at /home/daniel/Work/jetson-fpv/utils/dsyolo/libByteTracker.so
gstnvtracker: Optional NvMOT_RetrieveMiscData not implemented
[BYTETrack Initialized]
gstnvtracker: Only batch processing mode is supported. query.batchMode must be set as NvMOTBatchMode_Batch
gstnvtracker: Failed to initilaize low level lib.
** ERROR: <main:716>: Failed to set pipeline to PAUSED
Quitting
nvstreammux: Successfully handled EOS for source_id=0
App run failed
daniel@daniel-nvidia:~/Work/jetson-fpv/utils/dsyolo$ ls /home/daniel/Work/jetson-fpv/utils/dsyolo/libByteTracker.so
/home/daniel/Work/jetson-fpv/utils/dsyolo/libByteTracker.so
其实本来是非常简单的一件事情,但由于兼容性的问题,折腾!!!为了解决该问题,所以投资了不少时间,有必要讨论、吐槽下。
2. 基础知识
这里牵涉到一些概念,当然CSDN这里就不再详细赘述。以前折腾过一些框架设计相关的知识和要点如下:
【1】静态库和动态库编译方法和开发上的重要性
【2】Linux的so组件设计框架及逻辑
【3】【C语言】函数默认实现和用户自定义实现编程方法 – 【weak, strong alias】
这个插件实际上使用的是【1】、【2】点内容,而缺少了【3】,所以导致了本次报错,给兼容性带来了不必要的麻烦。
3. Gst-nvtracker插件
- Gst-nvtracker 插件允许 DeepStream (DS) 流水线使用低级跟踪器库,通过唯一的 ID 持续跟踪检测到的对象。
支持实现 NvDsTracker API 的库,包括由 NvMultiObjectTracker 库提供的参考实现:
- IOU 跟踪器:交并比(Intersection-Over-Union,IOU)跟踪器使用检测器在两帧之间的边界框的 IOU 值来进行关联,如果没有找到匹配,则分配一个新的目标 ID。该跟踪器包含一个逻辑,用于处理目标检测器中的误检(false positives)和漏检(false negatives);然而,这可以被认为是最基础的目标跟踪器,仅能作为基准使用。
- NvSORT:NvSORT 跟踪器是 NVIDIA® 增强版的简单在线实时跟踪(Simple Online and Realtime Tracking,SORT)算法。与简单的二分图匹配算法不同,NvSORT 使用基于边界框(bbox)接近性的级联数据关联方法,在连续帧之间进行边界框的关联,并使用卡尔曼滤波器更新目标状态。由于不涉及任何像素数据处理,它的计算效率非常高。
- NvDeepSORT:NvDeepSORT 跟踪器是 NVIDIA® 增强版的基于深度关联度量的在线实时跟踪(DeepSORT)算法。它通过使用带有重新识别(Re-ID)神经网络的深度余弦度量学习,在多帧之间进行多个对象的数据关联。此实现允许用户使用任何支持 NVIDIA TensorRT™ 框架的 Re-ID 网络。NvDeepSORT 同样采用级联数据关联方法,而非简单的二分图匹配算法,并针对 GPU 进行了高效处理的优化。
- NvDCF:NvDCF 跟踪器是一种在线多目标跟踪器,采用判别性相关滤波器进行视觉目标跟踪,即使检测结果不可用时也能独立跟踪目标。它结合了相关滤波器的响应和边界框的接近性来进行数据关联。
注:NvDeepSORT 和 NvDCF 跟踪器使用 NV12 或 RGBA 格式,而 IOU 和 NvSORT 不需要任何视频帧缓冲区。
- Gst-nvtracker 插件还支持通过 NvMOT_RetrieveMiscData API 从低级跟踪器库中检索用户定义的杂项数据
这些数据包括当前帧目标的默认数据以外的有用对象跟踪信息。例如,历史帧的对象数据、阴影跟踪模式中的目标、已终止目标的完整轨迹以及重新识别特征。有关杂项数据类型及其意义的更多详细信息,可以参考“杂项数据输出”部分。用户还可以在 NvMOTTrackerMiscData 中定义其他类型的杂项数据。
3.1 插件参数
Property | Meaning | Type and Range | Example Notes |
---|---|---|---|
tracker-width | Frame width at which the tracker is to operate, in pixels. (To be a multiple of 32 when visualTrackerType: 1 or reidType is non-zero with useVPICropScaler: 0 ) | Integer, 0 to 4,294,967,295 | tracker-width=640 |
tracker-height | Frame height at which the tracker is to operate, in pixels. (To be a multiple of 32 when visualTrackerType: 1 or reidType is non-zero with useVPICropScaler: 0 ) | Integer, 0 to 4,294,967,295 | tracker-height=384 |
ll-lib-file | Pathname of the low-level tracker library to be loaded by Gst-nvtracker. | String | ll-lib-file=/opt/nvidia/deepstream/deepstream/lib/libnvds_nvmultiobjecttracker.so |
ll-config-file | Configuration file for the low-level library if needed. Supports multiple files with semicolon delimiter. | Path to configuration file OR a semicolon-delimited list of paths | ll-config-file=config_tracker_NvDCF_perf.yml ll-config-file=config_tracker_NvDCF_perf1.yml;config_tracker_NvDCF_perf2.yml |
gpu-id | ID of the GPU on which memory is allocated, and buffer copy/scaling is done. (dGPU only.) | Integer, 0 to 4,294,967,295 | gpu-id=0 |
tracking-surface-type | Set surface stream type for tracking. (Default is 0.) | Integer, ≥0 | tracking-surface-type=0 |
display-tracking-id | Enables tracking ID display on OSD. | Boolean | display-tracking-id=1 |
compute-hw | Compute engine to use for scaling: 0 - Default 1 - GPU 2 - VIC (Jetson only) | Integer, 0 to 2 | compute-hw=1 |
tracking-id-reset-mode | Allows force-reset of tracking ID based on pipeline events: 0 - No reset 1 - Reset on GST_NVEVENT_STREAM_RESET 2 - Reset on GST_NVEVENT_STREAM_EOS 3 - Both | Integer, 0 to 3 | tracking-id-reset-mode=0 |
input-tensor-meta | Use tensor-meta from Gst-nvdspreprocess if available for tensor-meta-gie-id . | Boolean | input-tensor-meta=1 |
tensor-meta-gie-id | Tensor Meta GIE ID to use (valid only if input-tensor-meta is TRUE). | Unsigned Integer, ≥0 | tensor-meta-gie-id=5 |
sub-batches | Configure batch splitting in sub-batches: Option 1: Semicolon-separated array of source IDs. Option 2: Colon-separated array of sub-batch sizes. | See description | Option 1: sub-batches=0,1;2,3 Option 2: sub-batches=2:1 |
sub-batch-err-recovery-trial-cnt | Number of recovery attempts for errors in low-level tracker. -1 for infinite retries. | Integer, ≥-1 | sub-batch-err-recovery-trial-cnt=3 |
user-meta-pool-size | Size of tracker miscellaneous data buffer pool. | Unsigned Integer, >0 | user-meta-pool-size=32 |
3.2 插件API接口
- NvMOT_Query
NvMOTStatus NvMOT_Query (uint16_t customConfigFilePathSize,char* pCustomConfigFilePath,NvMOTQuery *pQuery
);
- NvMOT_Init
NvMOTStatus NvMOT_Init (NvMOTConfig *pConfigIn,NvMOTContextHandle *pContextHandle,NvMOTConfigResponse *pConfigResponse
);
- NvMOT_Process
NvMOTStatus NvMOT_Process (NvMOTContextHandle contextHandle,NvMOTProcessParams *pParams,NvMOTTrackedObjBatch *pTrackedObjectsBatch
);
- NvMOT_RetrieveMiscData
NvMOTStatus NvMOT_RetrieveMiscData (NvMOTContextHandle contextHandle,NvMOTProcessParams *pParams,NvMOTTrackerMiscData *pTrackerMiscData
);
- NvMOT_RemoveStreams
void NvMOT_RemoveStreams (NvMOTContextHandle contextHandle,NvMOTStreamId streamIdMask
);
- NvMOT_DeInit
void NvMOT_DeInit (NvMOTContextHandle contextHandle);
4. 分析问题
现象:鉴于前面执行LOG显示: gstnvtracker: Optional NvMOT_RetrieveMiscData not implemented
分析:NvMOT_RetrieveMiscData
正好是上面第四个API,因此逻辑上考虑可能是加载这个so符号的时候遇到了问题。
原因:最终,发现在 BTYETrack
确实没有这部分代码。
解决:由于之前这部分代码是可以使用,随着Jetpack版本升级,增加了这部分API,但是BYTETrack
没有这部分。为此:fix multi-object track and Deepstream 6.3 API link issue
5. 总结
若在架构设计的时候,考虑兼容性方面的问题,引入weak symbol概念(当用户没有实现,weak链接到stub函数,就能很好的兼容旧接口开发的代码)。
总的来说,NVIDIA在Deepstream这块其实采用了so插件的框架结构,很好,但若能更好的技巧上运用一些方法,可以让代码兼容性,尤其是第三方插件开发更好的应用于NVIDIA的生态。
6. 参考资料
【1】DeepStream documentation - Gst-nvtracker
【2】ByteTrack is a simple, fast and strong multi-object tracker