一些自己的工作经验总结,用于补救模型、提升速度的常用工程方法。
同样的任务,可以训练两套网络,通过控制网络的 receptive field,分别处理大目标、小目标。 为了检测多尺度目标,模型都会采用类FPN的结构,直接结果就是减少模型的并发性。划分大小网络后,可以减少FPN结构的分支,同时也可以减少训练难度,而且两个网络也可以使用不同的复杂度。
比如高速的视觉感知上,越在中间位置越需要更远的识别距离,越在周边位置目标越近。 就可以用一个低分辨率的图片检测近距离目标,用中心区域的高分辨率图片检测远距离目标。
后续可以更加智能,使用一个额外的网络,预测哪些区域需要高分辨率检测,哪些区域低分就可以。用来处理弯道、 特殊场景等情况。
同样的思路也可以应用在不同焦距多摄像头的系统上。
这个方法我也用了多年,屡试不爽。由于CNN的特性,运算量集中在高分辨率上,第一层conv往往占用了很可观的运算量。 所以,如果对色彩没有特别要求的话,可以直接用黑白的单通道图片。这样就直接减少第一层 conv 2/3 的运算量。整体上甚至可能会有10%的速度提升。
如果应用的场景有很大的变化,可以考虑先用分类网络来确定场景,然后选择适合场景的模型。 分类模型可以很轻量,这样用不同的重量网络来处理不同的场景,相当于一个N倍容量的单一重量模型。 比如,先分类确认白天、黑夜、隧道,然后再载入对应场景的检测模型。
这个方法根据我的经验和观察应该是被普遍采用的。毕竟,很多应用实际使用中并不需要完全实时(30+FPS)。 根据自己的经验,15FPS的检测频率,即使把检测框打出来,人眼也是感觉不出来延时的。所以,之前工作中我都会有一个性能指标叫做准实时:检测速度在 15~20FPS 这个范围内,在嵌入式设备上会进一步降低到 10~13FPS。
自己对 Tracking 并不支持,更愿意用其他的方法来实现。
比如,可以将所有已检目标和其附近区域作为一个 batch,塞给一个轻量级的检测网络。或者用 ReID 的思路进一步来保持 ID。
由于检测模型的训练会对目标类型的特征更加敏感,相对 Tracking 使用的通用 feature ,或者 online 生成的 feature 可能会更加有效,也能减少不少工程复杂度。
多种任务合并后可能需要一个容量很大的网络才能获得比较好的结果。可以考虑先将一个任务完成,后续增加一个分任务的网络。这样整体上可能会获得一个更好的性能提升。或者,先用一个网络完成到60分,后面可以针对性的用网络把60分提升到80分,Two-stage的Faster RCNN就是这个方法的一个典型。
比如,检测目标后需要很多更加细致的属性分类。可以先将所有目标检测出来,然后再交给一个后续网络完成细致属性的判断。
很多人可能会直接利用现在各个网络库提供的预训练模型来解决自己的问题,这些模型的网络复杂度一般都是和 Res50 一致的(这一复杂度其实是在常用算力、训练吞吐量、准确率、实用性之间trade-off的一个最优复杂度了)。
不过,实际任务未必需要这个复杂度,之前的经验,即使在Res18的复杂度下,也可以应付10+类的检测。减少网络复杂度可能 mAP 一类的指标会掉一点,但是速度大幅度提升,这个平衡就看实际情况了。
用于应对偶尔的误检,这也算是普遍使用的基础方法。每次检出并不直接认为是目标,而是等待多次检测后才认为检出目标。具体可以用滤波方法、置信度模型、或者单纯的连续5帧中检出3次这样的判断。
这也是基本方法,可以用于避免目标偶尔漏检、平滑检测框,不废话了。
有些目标和场景未必需要保持图像比例:行人太细可以考虑拉宽点分辨率训练;一些车道检测也会通过视角变化来获得更好效果,或者方便使用传统方法快速检测。
接触过摄像头或者摄影的都会知道,CMOS对于大光比是很无力的。如果对摄像头的曝光有控制力的话,调整曝光是个很有效的方法。比如: 在行驶路面场景下,相机自动曝光因为天空太亮的原因,会趋向于让路面变得更加黑暗,这样地面目标检测会容易误检或者漏检。其实天空区域过曝关系并不大(除了有红绿灯的情况),路面场景更加关心的是路面的各类目标,所以可以使用更加智能的曝光,让不重要的区域过曝或者欠曝。
或者能够有一个足够快速的HDR算法,多个曝光选项的合并,但是这个难度和复杂度要比放弃部分区域的曝光更大,控制曝光更加简单粗暴。
ROI检测框合并会用NMS,或者其他的变种。不过,如果有时候偷懒的话,可以直接用 OpenCV 里面的 groupRectangle。也可以完成检测框的合并,考虑到这是个不用自己实现的接口,可以临时省下一点工作量。实际上,用这个接口来合并检测结果,被我自己用了很多年。