YOLO序列版本和Deepstream的数据缩放预处理问题

因为我们的项目使用Deepstream作为视频播放和模型推理的框架,经过前面解决若干模型转换上的问题和Deepstream内在的问题后,在同分布的测试集上,Deepstream里FP16量化模型的推理精度基本上和无量化版模型使用python调用的推理精度差不多了,可以说是基本无损了,但是近来拿到从未参与训练的场景和摄像头角度差异有点大的新的试点部署现场测试,泛化能力表现却比较差,在经过序列调查排除网络模型本身的问题后,发现几点原因:

1. 我们目前使用的yolov5-v6版模型比之前使用的yolov5旧版模型的泛化能力受数据预处理上的缩放填充方式的影响比较大;

2. Deepstream里数据的缩放填充预处理方式是把图片保持宽高比(aspect ratio)缩放到小于或等于640x640以内然后直接拷贝到640x640的buffer的上方,下侧以黑色填充的(我翻看了nvinfer插件的源码,实际上是事先创建640x640的0值缓冲区,将缩小的图片内容填到上方后,下方就相当于用黑色填充了),所以不是标准的Letterbox方式,而且只提供了这种缩放填充方式,里面代码写死了的没得选;

3.yolo序列模型最初的版本是直接做resize后输入模型,后来AlexeyAB版的yolov3以及后来的pytorch版的yolov4和yolov5都是这样搞的: training时是直接resize原始图片到模型输入的尺寸或者在原始图片基础上做mosaic和mixup增强效果直接弄成了模型输入数据的尺寸(例如640x640),也就根本不存在填充问题,而在validation时却是将输入图片先保持宽高比缩放到小于或等于640x640的范围内并将缩小了的图片放在待输入模型的图片数据mat的中央,上下两侧不足的部分用灰色(114,114,114)填充的,也就是标准的Letterbox缩放填充方式,也就是用Letterbox方式缩放填充后的图片作为输入模型的数据去选择最好的参数组合:

YOLO序列版本和Deepstream的数据缩放预处理问题_第1张图片

这样有点的搞法根据yolov5的作者自己的说法是,炼丹实验中发现这样做效果是最好的:

参见 https://github.com/ultralytics/yolov5/issues/6122

YOLO序列版本和Deepstream的数据缩放预处理问题_第2张图片

为何training时不使用letterbox(至少可以作为一种增加这中缩放填充形式的数据呀)而只在validation时使用了,作者没有说,而且只是说(参见the advantages of letterbox? · Issue #7454 · ultralytics/yolov5 · GitHub):

YOLO序列版本和Deepstream的数据缩放预处理问题_第3张图片

 我猜training时不加入Letterbox形式缩放填充了的数据而是只使用mosaic和mixhup处理之后的数据,主要是考虑经过增强处理的图片中的很多目标已经比较小了,再缩小填充就更小了,可能对小目标非常不利而已。

Resizing : keeping aspect ratio, or not · Issue #232 · AlexeyAB/darknet · GitHub这里列出了数据输入模型前常用的几种缩放办法极其示例,非常有助于理解各种办法的各自优缺点:

YOLO序列版本和Deepstream的数据缩放预处理问题_第4张图片

实例:

YOLO序列版本和Deepstream的数据缩放预处理问题_第5张图片

YOLO序列版本和Deepstream的数据缩放预处理问题_第6张图片

YOLO序列版本和Deepstream的数据缩放预处理问题_第7张图片

 YOLO序列版本和Deepstream的数据缩放预处理问题_第8张图片

 AlexeyAB认为直接resize比使用Letterbox保持aspect ratio缩放再填充的方式得到的缩小了的小目标的尺寸要大一些有利于识别,语气是倾向于使用resize的:

此外,作者认为虽然直接resize()导致了缩小了的目标可能被扭曲了,但是training是用这样的resize()后的扭曲目标训练的,那么测试时只要保持同样直接使用resize()缩小原图,那么被扭曲的目标的识别就不会有问题,参见 https://github.com/AlexeyAB/darknet/issues/1907 :

YOLO序列版本和Deepstream的数据缩放预处理问题_第9张图片

 这可以解释原始的darknet里图片预处理用的是letterbox_image()而AlexeyAB的版本里为何改成了resize()。仔细想想是这么回事,保持宽高比缩放后填充的Letterbox只是解决了扭曲问题,但是对于小目标来说被缩得更小了,直接resize()后的目标虽然可能被扭曲了,但是训练时也是这么训练的,推理时也这么缩放扭曲的,那么应该不会有问题,我们以前做其他模型的训练和推理事实上也经常直接做resize(),只是这次是因为需要迁就Deepstream里的缩放方式,不得不以保持宽高比缩放方式对原图进行缩放。至于blobFromImage()这种处理太特殊,只对目标少且集中的场景才有效,一般多目标分散场景里肯定只适合用来做数据增强,或者用于高分辨率图片里围绕目标做切片训练和切片推理。

针对Deepstream里的填充位置以及填充使用的颜色和yolov5-v6里validation的输入数据填充位置和使用的颜色不一样,我做了实验,发现填充位置的不同,对模模识别未参加训练的跨域场景的图片里的同样目标的识别影响挺大的,同样目标的置信度得分严重的可能有0.3以上的下降,这个比较吓人了,填充颜色的不同也有点影响,下降大约在0.05-0.1之间,对于同一数据集内未参与训练的测试集的图片的识别,填充位置和填充颜色的不同则对目标识别的置信度得分看不出明显差异。

针对Deepstream里数据缩放填充位置和填充颜色和yolov5-v6里validation时的数据缩放填充位置和填充颜色不一致而造成的检测目标的置信度得分下降的问题,我们打算这么改进:

1)将yolov5-v6里validation的数据缩放填充位置和填充颜色改成与Deepstream里的方式(因为Deepstream里只支持一种方式而且代码是写死的)保持一致然后再用同样数据训练一版模型和目前的模型对比集成到Deepstream里后的推理效果;

2)在yolov5-v6里做点改动,在training部分,将mosaic和mixup处理的所有结果图片复制一份做Deepstream里那种方式的缩放和填充处理,结果图片数据也加入训练集中参与训练,看是否对模型识别跨域场景中的目标的能力是否有较大提升,一个是因为感觉yolov5里为了避免小目标识别不好不将Letterbox方式缩放填充的数据参与训练,而只用于validation阶段对参数的选择,这有点怪异,我想试试这样做到底会怎么样,另外一个是因为我们的项目需求中需要识别的目标中一般没有特别小的目标,所以做类似Letterbox方式的缩放带来的尺寸上的一点减小应该问题不大。

第一点实验证明,validation选择和Deepstream里的缩放填充方式一致后在跨域识别新数据时能保持得分稳定一点,第二点实验目前没时间,后面有结果再更新。

你可能感兴趣的:(Deepstream,YOLOv3,darknet,深度学习,Deepstream,yolov5,yolo,darknet)