本篇文章转自:https://zhuanlan.zhihu.com/p/49995236,若侵权,立即删。
首先需要对网络的输入进行理解。Yolov3需要的训练数据的label是根据原图尺寸归一化了的,这样做是因为怕大的边框的影响比小的边框影响大,因此做了归一化的操作,这样大的和小的边框都会被同等看待了,而且训练也容易收敛。既然label是根据原图的尺寸归一化了的,自己制作数据集时也需要归一化才行,如何转为yolov3需要的label网上有一大堆教程,也可参考我的文章:将实例分割数据集转为目标检测数据集,这里不再赘述。
这里需要注意的是,虽然输入尺寸是416416,但原图是按照纵横比例缩放至416416的,取 min(w/img_w, h/img_h)这个比例来缩放,保证长的边缩放为需要的输入尺寸416,而短边按比例缩放不会扭曲,img_w,img_h是原图尺寸768,576, 缩放后的尺寸为new_w, new_h=416,312,需要的输入尺寸是w,h=416*416.如图1所示:
剩下的灰色区域用(128,128,128)填充即可构造为416*416。不管训练还是测试时都需要这样操作原图。pytorch代码比较好理解这一点。下面这个函数实现了对原图的变换。
论文中边框预测公式如图2:
其中,Cx,Cy是feature map中grid cell的左上角坐标,在yolov3中每个grid cell在feature map中的宽和高均为1。如图3的情形时,这个bbox边界框的中心属于第二行第二列的grid cell,它的左上角坐标为(1,1),故Cx=1,Cy=1。Pw、Ph是预设的anchor box映射到feature map中的宽和高,在yolov3.cfg文件中的anchor box原本设定是相对于416*416坐标系下的坐标,代码中是把cfg中读取的坐标除以stride如32映射到feature map坐标系中。
最终得到的边框坐标值是bx,by,bw,bh即边界框bbox相对于feature map的位置和大小,是我们需要的预测输出坐标。但网络实际上的学习目标是tx,ty,tw,th这4个偏移量(offsets),其中tx,ty是预测的坐标偏移值,tw,th是尺度缩放,有了这4个offsets,自然可以根据图2的公式去求得真正需要的bx,by,bw,bh4个坐标。
问题1:为何不直接学习bx,by,bw,bh呢?
解答:因为YOLO 的输出是一个卷积特征图,包含沿特征图深度的边界框属性,
边界框属性由彼此堆叠的单元格预测得出。
因此,如果需要在 (5,6) 处访问该单元格的第二个边框bbox,需要通过 map[5,6, (5+C): 2*(5+C)] 将其编入索引。
这种格式对于输出处理过程(例如通过目标置信度进行阈值处理、添加对中心的网格偏移、应用锚点等)很不方便,因此我们求偏移量即可。
另外,通过学习偏移量,就可以通过网络原始给定的anchor box坐标经过线性回归(平移加尺度缩放)去逐渐靠近groundtruth.
问题2:anchor box作用的详细描述。
解答:YOLO3为每种FPN预测特征图(13*13,26*26,52*52)设定3种anchor box,总共聚类出9种尺寸的anchor box。
在COCO数据集这9个anchor box是:(10x13),(16x30),(33x23),(30x61),(62x45),(59x119),(116x90),(156x198),(373x326)。分配上,在最小的13*13特征图上由于其感受野最大故应用最大的anchor box (116x90),(156x198),(373x326),(这几个坐标是针对416*416下的,当然要除以32把尺度缩放到13*13下),适合检测较大的目标。中等的26*26特征图上由于其具有中等感受野故应用中等的anchor box (30x61),(62x45),(59x119),适合检测中等大小的目标。
较大的52*52特征图上由于其具有较小的感受野故应用最小的anchor box(10x13),(16x30),(33x23),适合检测较小的目标。
同Faster-Rcnn一样,特征图的每个像素(即每个grid)都会有对应的三个anchor box,如13*13特征图的每个grid都有三个anchor box (116x90),(156x198),(373x326)(这几个坐标需除以32缩放尺寸)。
4个坐标tx,ty,tw,th是怎么求出来的呢?对于训练样本,在大多数文章里需要用到ground truth的真实框来求这4个坐标:
图4公式是faster-rcnn系列文章用到的公式,Px,Py在faster-rcnn系列文章是预设的anchor box在feature map上的中心点坐标。 Pw、Ph是预设的anchor box的在feature map上的宽和高。Gx、Gy、Gw、Gh是ground truth在这个feature map的4个坐标。其实Gx、Gy、Gw、Gh坐标在第1节已经描述了这个过程,要根据原图坐标系先根据原图纵横比不变映射为416416坐标下的一个子区域如416312,取 min(w/img_w, h/img_h)这个比例来缩放成416312,再填充为416416,坐标变换上只需要让ground truth在416312下的y1,y2(即左上角和右下角纵坐标)加上图1灰色部分的一半,y1=y1+(416-416/768576)/2=y1+(416-312)/2,y2同样的操作,把x1,x2,y1,y2的坐标系的换算从针对实际红框的坐标系(416312)变为416416下了,这样保证bbox不会扭曲,然后除以stride得到相对于feature map的坐标。
问题3:用x,y坐标减去anchor box的x,y坐标得到偏移量好理解,为何要除以feature map上anchor box的宽和高呢?
解答:可能是为了把绝对尺度变为相对尺度。不同尺度的anchor box如果都用Gx-Px来衡量显然不对,有的anchor box大有的却很小,都用Gx-Px会导致不同尺度的anchor box权重相同,而大的anchor box肯定更能容忍大点的偏移量,小的anchor box对小偏移都很敏感,故除以宽和高可以权衡不同尺度下的预测坐标偏移量。
但是在yolov3中与faster-rcnn系列文章用到的公式在前两行是不同的,yolov3里Px和Py就换为了feature map上的grid cell左上角坐标Cx,Cy了,即在yolov3里是Gx,Gy减去grid cell左上角坐标Cx,Cy。x,y坐标并没有针对anchon box求偏移量,所以并不需要除以Pw,Ph。
也就是说是tx = Gx - Cx
ty = Gy - Cy
这样就可以直接求bbox中心距离grid cell左上角的坐标的偏移量。
tw和th的公式yolov3和faster-rcnn系列是一样的,是物体所在边框的长宽和anchor box长宽之间的比率,不管Faster-RCNN还是YOLO,都不是直接回归bounding box的长宽而是尺度缩放到对数空间。
问题4,为何不是直接回归bounding box的长宽而是尺度缩放到对数空间?
解答:是怕训练会带来不稳定的梯度。因为如果不做变换,直接预测相对形变tw和th,那么要求tw,th>0,因为你的框的宽高不可能是负数。这样,是在做一个有不等式条件约束的优化问题,没法直接用SGD来做。所以先取一个对数变换,将其不等式约束去掉,就可以了。
这里就有个重要的疑问了,一个尺度的feature map有三个anchors,那么对于某个ground truth框,究竟是哪个anchor负责匹配它呢?和YOLOv1一样,对于训练图片中的ground truth,若其中心点落在某个cell内,那么该cell内的3个anchor box负责预测它,具体是哪个anchor box预测它,需要在训练中确定,即由那个与ground truth的IOU最大的anchor box预测它,而剩余的2个anchor box不与该ground truth匹配。
YOLOv3需要假定每个cell至多含有一个grounth truth,而在实际上基本不会出现多于1个的情况。与ground truth匹配的anchor box计算坐标误差、置信度误差(此时target为1)以及分类误差,而其它的anchor box只计算置信度误差(此时target为0)。在训练过程中划分正负样本是非常重要的,因为anchor很多,只有对一大堆anchor box划分了正负样本,才能有效地用正样本参与损失函数训练。但问题是三个检测层,那么多anchor box,如果只把gt匹配一个anchor,那么正样本数量会极其稀少,训练会极为不利。
问题5,那么究竟是如何划分正负样本呢?
解答:假设iou阈值为0.7,所有瞄点框与真实标签进行匹配,需要构造 IOU 矩阵,每一行代表一个瞄点框,行数代表anchor box数量,每一列代表一个真值框,列数代表gt的个数。然后执行 3 个标准:1.对于任何一个瞄点框,与所有标签的最大 IOU 小于 0.3,则视为负样本;2.对于任何一个真值,与其有最大 IOU 的瞄点框视为正样本;3.对于任何一个瞄点框,与所有真值框的最大 IOU 大于 0.7 则视为正样本。这样的三个标准顺序不能变动,保证了多个瞄点框对应一个真值,而一个真值框不能对应多个瞄点框。
有了平移(tx,ty)和尺度缩放(tw,th)才能让anchor box经过微调与grand truth重合。如图5,红色框为anchor box,绿色框为Ground Truth,平移+尺度缩放可实线红色框先平移到虚线红色框,然后再缩放到绿色框。边框回归最简单的想法就是通过平移加尺度缩放进行微调嘛。