在将模型集成到Deepstream Infer Plugin过程中可能会碰到这样那样的问题,其中一个困扰人的问题就是一个模型集成到Deepstream Infer Plugin后,模型推理时的效果下降,使用onnx格式导出模型使用TensorRT解析生成engine后推理精度下降这个问题我报过case但是一直没有得到解决,这里说的是另一个方式使用模型时遇到的问题,就是模型使用TensorRT的API实现后集成到Deepstream Infer Plugin里比不使用Deepstream而是直接使用python调用原始模型或者使用C++调用TensorRT API实现的模型的效果要差得不少,两种方式使用同样的视频或图片和同样的模型engine文件,模型在Deepstream Infer Plugin里的表现要差,经过很多次的调查和实验,可以确定这个问题和模型本身的基于TensorRT API实现没有关系,和数据预处理也没有关系,最后发现这个问题的根本原因在Deepstream的gstnvinfer_meta_utils.cpp里处理不正确,这个bug即使在最新版的Deepstream5.1中都仍然存在:
void
attach_metadata_detector (GstNvInfer * nvinfer, GstMiniObject * tensor_out_object,
GstNvInferFrame & frame, NvDsInferDetectionOutput & detection_output, float segmentationThreshold)
{
...
obj.left /= frame.scale_ratio_x;
obj.top /= frame.scale_ratio_y;
obj.width /= frame.scale_ratio_x;
obj.height /= frame.scale_ratio_y;
...
if (obj.top + obj.height >
(frame.input_surf_params->height - filter_params.roiBottomOffset))
continue;
当把bbox缩放到原始图片下的坐标后检测到bbox坐标越界时,它不是做安全转换而是静默地把这个bbox丢掉了!这样处理是明显不正确的,按照一般做法应该是对越界的bbox坐标做安全转换,直接丢掉bbox显然会降低召回率,造成bbox触及边界的物体识别非常不稳定!造成的直接效果就是在Nano之类的板子上使用Deepstream Infer Plugin集成模型后进行视频识别的效果比单独使用python或者C++直接调用TensorRT API来使用模型对同一视频进行识别的效果要差不少。
把上述代码改成这样就可以解决问题:
if (obj.top + obj.height >
(frame.input_surf_params->height - filter_params.roiBottomOffset))
obj.height = frame.input_surf_params->height - filter_params.roiBottomOffset - obj.top;
如果不想修改Deepstream的代码造成需要自己维护Deepstream特定版本,也可以在定制bbox解析接口函数里增加这个检查和转换,不过得根据缩放前后的图片的大小把代码写死,因为解析bbox的定制接口函数的入参里没有scale_ratio_x和scale_ratio_y,所以没法做到灵活,当然缩放后的尺寸大小参数是有的(networkInfo.height,networkInfo.width),缩放前的原始帧图片大小就只能使用配置文件方式读入了,即便这样显然还是不灵活,视频的图像尺寸有变化时都得记得修改这里,不然解析bbox的定制接口函数这里的检查和转换没起到对放大后坐标的提前检查把关作用的话,又会出现Deepstream把触及边界的bbox丢掉造成识别效果下降。
这种问题大致可以分成三个方面排查。
一是模型网络的实现本身是否有问题,例如用于推理的cuda stream要保持自始至终使用同一个,并且最好自己创建而不是使用default cuda stream,使用python或C++代码调用TensorRT API测试模型的效果确认模型的输出和官方原始版本的测试结果一样,这部分工作和你使用或实现的模型网络有关,所以也不好说太具体的步骤细节。
排除了模型网络实现本身的问题之后,就是进行第二个方面的调查,就是比较Deepstr

博客详细分析了在Deepstream中集成模型进行视频识别时,推理效果下降的原因,指出问题根源在于Deepstream的gstnvinfer_meta_utils.cpp文件中处理边界bbox的错误。解决方案包括修改Deepstream源码或在定制接口中处理,以及通过对比预处理数据和模型输出来排查问题。此外,还提供了将GPU预处理改为CPU处理的方法。
最低0.47元/天 解锁文章
1134





