首先,请允许我说明一下,笔者也是一名目标检测的小白(研一的小萌新)。前些日子,我敬爱的导师让我根据自己理解总结一下目前自己对于遥感领域目标检测相关的知识,于是便有了以下内容。如果你恰好读到这篇文章,发现文章有问题或者你有自己的见解,欢迎留言!
-------------------------------------------------------------------------------------------------------------------------------
在我看来,遥感领域目标检测的工作需要按照以下几个方面:遥感旋转数据集、数据预处理、主干网络、颈部网络、检测头、损失计算、一些阈值的选择、评价指标。关于当前旋转目标检测的最新进展,可以参考以下网址:
https://github.com/SJTU-Thinklab-Det/DOTA-DOAI
遥感旋转数据集(以下为我用过的数据集):
如果是针对某一个数据集进行训练提点的话,可以先做好调研。比如每一类目标的数量、目标的大小分布等。对症下药。
1、HRSC2016数据集
一共有1061张图片(大小3G左右,每张图片大小处于300 X 300到1500 X 900范围),训练集、验证集和测试集中分别包含436、181和444张图片。其主要包括3大类27小类,共2,976个目标。
标注格式:xml格式,主要参数为xywh以及一个角度。另外,还提供了一组head_x、head_y数据,其表示为船只的头部坐标。
但是对于大多数算法,通常会把所有的类只当成一类来处理,即ship。只区分船只与背景,不对具体细节进行区分。该数据集的map已经被刷到了90%左右。(R3Det89.26%)该数据集的目标呈现长条状,纵横比较大。采用anchor-based的方法可根据此设定anchor。但是也有一个缺点,这其实也是针对所有旋转数据集:IOU对角度额外的敏感,倾斜一个很小的角度会导致IOU骤减,导致角度回归不精确。
2、DOTA数据集
DOTAv1.0和v1.5都包含了2806张图片,大小为800 X 800到4000 X 4000不等。V1.0有15个类别,v1.5为16类。DOTAv2数据集包含11268张图像,18个类别,图像宽高范围为[800, 20000]。目前DOTAv1.0数据集的OBB检测map为80.93(KFIoU算法,backbone为Swin-ting)。DOTAv1.5map为78.34(APE算法,backbone为ResNext。)TASK1用来进行OBB检测,TASK2用来进行HBB检测。
标注格式:txt格式,dota排序方式。分布为x1 y1 x2 y2 x3 y3 x4 y4 classname difficult。因为DOTA数据集的图片比较大,若是直接把它喂到模型进行训练,基本上都会报显存问题。而官方提供了DOTA_devkit工具,其主要实现:
DOTA.py :加载图片并绘制目标边框
ImgSplit.py :分割数据集
ResultMerge.py: 将被分割数据集的检测结果合并,便于后续评估模型性能
dota_×_evaluation_task×.py: 评估模型性能
3、UCAS_AOD数据集
包含两类目标,汽车和飞机,还有一部分是背景样本,总计约2400张影像(大小3G,每张图片大约是1000 X 800)目前该数据集map最高为97.02(PolarDet算法)。
标注格式:txt格式。为x1 y1 x2 y2 x3 y3 x4 y4 角度 x y w h
该数据集目前map最高为97.02(PolarDet)。
数据预处理
拿到数据集后,首先需要做的工作是把数据集的格式转换成为模型所要求的格式。将数据集裁剪为合适大小后,随后进行数据增强。通常来说,数据增强分为有监督数据增强和无监督数据增强,而我们经常用的都是有监督数据增强的方法,如mosaic、仿射变换、mixup等。这些要使用通常只需要修改相应的超参数即可,如yolov5当中的mosaic、Translation、Shear、degrees等。数据增强我认为不能盲目去使用,需要结合数据集的目标与背景分布情况,在遥感图像中,背景本来就比较复杂,小目标在这种复杂背景下难以训练,若是再加上mixup,对于小目标的训练无疑是雪上加霜。
主干网络
用来做特征提取,现在大部分用的还是分类的主干网络,以ResNet101居多。我觉得这也是当前检测领域所面临的一个问题,没有专门用来检测的backbone。
颈部网络
大多数还是以FPN为主,当然现在用的也是五花八门,各种改造后的FPN。Yolov5用的是SPPF+Panet。
检测头
在训练时,将Anchor铺设在不同尺度的featuremap上,通过与GT_box的匹配度筛选,完成不同尺度anchor的正样本采样工作,之后进入损失函数训练。
损失计算
包括类别损失、置信度损失、角度损失、bbox回归损失。
类别损失、置信度损失一般就是二值交叉熵的方式,即BCEWithLogitsLoss。(置信度损失这一块还弄得不太明白,这里需要花时间好好学习一下)
角度损失的话,因为角度边界问题,当处于边界角度时,会出现损失值暴增。于是有人会把角度回归转化成为分类,我的理解是把角度0-180离散化成0、1、2………180。然后也以二值交叉熵的方式计算。
Bbox回归损失,一般会有IOU、GIOU、CIOU、DIOU的方法,这当然只是传统的HBB检测。OBB检测在DOTA_devkit工具里面会提供一个旋转IOU的计算方法,不过这一块也没弄太明白,需要好好学习。
阈值选择
置信度阈值a:在NMS之前会设置一个置信度阈值a,对于一张图片中的每一个预测框来说,模型为其每一个类别都预测了一个置信度分数,取置信度最高的那一个类别作为预测框中对象所属的类别,然后将置信度分数低于置信度阈值a的所有预测框去掉 。我们通常会设置置信度阈值a为0.3。
置信度阈值b:在进行map计算时,首先会遍历groundturth的object,随后读取检测器的预测框,过滤掉置信度低于置信度阈值b的预测框。
IOU阈值c:NMS时,过滤掉同一检测对象置信度最高的预测框与其他预测框IOU大于该阈值c的预测框。这一操作可以剔除与置信度最高的预测框高度重合的预测框。
IOU阈值d:在正负样本划分的过程中,过滤掉置信度分数低于置信度阈值b的框,将剩下的检测框按置信度分数从高到低排序,判断检测框与gt bbox的IoU是否大于IoU阈值d,若IoU大于设定的IoU阈值即判断为TP, IoU小于阈值的,为FP。
在测试阶段才会进行NMS,NMS之后再进行map计算。
评价指标
精度指标map,map是整个数据集所有类的AP的平均值。
AP07:选取recall大于0、0.1、0.2…1总共11个点的precision最大值,然后取平均。而map07便是所有类的平均。
AP12:相对于AP07就是recall不再是11个点,而是所有recall值。
coco数据集评价指标:map0.5和map0.5-0.95(以0.05为步长)
要计算每一类的AP,需要先计算precision和recall,计算如下:
Precision: TP / (TP + FP)
Recall: TP / (TP + FN)
速度指标FPS
速度评价指标要在同一硬件上进行,因为同一硬件,它的FLOPS是相同的。