介绍
本文总结了目标检测领域的一些常见问题并给出了详细的解答。
目标检测两阶段和一阶段的核心区别
目标检测技术分为两个阶段,一级和二级。第二阶段的核心思想是首先提出一个proposal框,利用第一阶段的网络来回归目标框作为前景的大概位置、大小和概率。第二阶段是使用另一个网络来回归目标框架的位置、大小和类别。一阶段网络的核心是对于输入图像,通过网络直接返回目标大小、位置和类别。
目标检测两阶段比一阶段的算法精度高的原因
1.正负样本的不均衡性
当某一类别的样本数量特别多时,训练好的网络对该类别的检测精度往往会比较高。当某类目标的训练样本数量较少时,模型对该类目标的检测精度会下降。这就是所谓的样本不平衡导致的检测精度差异。
对于第一阶段的目标检测,既需要定位又需要分类。最后几层11卷积层的损失全部混合在一起。没有明确的分工,哪一部分专门做分类,哪一部分专门做分类。对预测框做回归,这样对于每一个参数,学习难度都会增加。
对于两阶段目标检测(Faster RCNN),在RPN网络结构中对前景和背景进行分类和检测。这个过程比第一阶段目标检测简单得多,第一阶段目标检测直接涉及分类和检测。通过区分前景和背景,可以选择性地选择样本,使正负样本更加平衡,然后重点进行一些参数的分类训练。训练的分类难度会比直接做混合分类和预测框回归进行一阶段目标检测简单很多。
2.样本的不一致性
如何理解样本不一致?首先我们都知道,当RPN获取多个anchor时,会用到NMS。在进行回归操作时,预测框和gt的IoU与回归后的预测框和gt的IOU相比,一般会发生明显的变化。然而,当使用NMS时,使用的是回归之前的置信度,因此会导致一些回归后IoU较高的预测框被删除。这意味着回归前的置信度不能完全表征回归后的IoU大小。这也会导致算法精度的下降。这种情况第一次使用NMS时会比较明显,第二次使用时会好很多。因此,第一阶段只使用一次NMS会对精度产生影响,而在第二阶段目标检测中,会在RPN之后。进行更精细的回归,其中也会使用NMS,检测精度会好很多。
如何解决目标检测中密集遮挡问题
遮挡本身也可以分为两种,一种是非目标引起的遮挡,另一种是同样需要检测的目标引起的遮挡。这两种类型的遮挡分别称为遮挡和拥挤。
对于前一种遮挡,很难有针对性地解决。最好的方法是使用更多的数据和更强的功能。您可以从训练数据开始。添加掩模和扰动以提高算法响应遮挡的能力。
对于第二种类型的遮挡,提出了两种损失来解决这个问题。
通过设置损失函数,即Repulsion Loss,使预测框和所负责的真实目标框的距离缩小,而使得其与周围非负责目标框(包含真实目标框和预测框)的距离加大 。如下式,如果与周围目标的距离越大,损失值会越小。
除了常用的smooth L1让回归目标接近GT之外,这两个loss的目标之一就是让proposal sum尽可能远离与之重叠的第二大GT,另一个目标就是让提案被分配到不同的GT。尝试在提案之间彼此保持尽可能远的距离。通过这两个损失,不仅可以将proposal移近正确的目标,还可以使其远离错误的目标,从而减少NMS期间的错误检测。
“狭长形状”目标检测有什么合适方法
使用可旋转粘合盒进行贴标
手工设计的锚
如何解决动态目标检测
1.光流法
光流是空间运动物体被观测表面上的像素运动产生的瞬时速度场,包含了物体表面结构和动态行为的重要信息。光流计算方法大致可以分为三类:
(1)基于匹配的光流计算方法包括基于特征和基于区域的光流计算方法。基于特征的方法连续定位和跟踪目标的主要特征,对大目标的运动和亮度变化具有鲁棒性。问题是光流通常是稀疏的,特征提取和精确匹配也非常困难;基于区域的方法首先定位相似区域,然后通过相似区域的位移来计算光流。该方法已广泛应用于视频编码中,但其计算的光流仍然不稠密。
(2)基于频域的方法使用速度可调的滤波器组来输出频率或相位信息。虽然可以获得非常高精度的初始光流估计,但往往涉及复杂的计算,可靠性评估也非常困难。
(3)基于梯度的方法利用图像序列的时空微分来计算二维速度场(光流)。基于梯度的方法由于计算简单和更好的实验结果而被广泛使用。
2.相邻帧差法
相邻帧差分法是运动目标检测中最常用的算法。原理就是将图像前后两帧对应的像素值相减。当环境亮度变化不大时,如果对应的像素值相差很小,则可以认为这里的场景是静止的,否则,就是运动的物体。
相邻帧差分法对动态环境的适应性强,鲁棒性好,可以适应各种动态环境。然而,它通常无法完全提取所有相关的特征像素,这很容易在移动实体内部造成空洞。现象。
3.背景差法
背景差分法是常用的运动目标检测方法之一。其基本思想是通过确定灰度等特征的变化或使用直方图等系统来将输入图像与背景模型进行比较。
范数所占的样本比例,对样本进行动态的加权,使得具有小梯度的容易分类的样本降权,具有中梯度的hard expamle升权,具有大梯度的outlier降权。
手撕代码IOU
import numpy as npdef ComputeIOU(boxA, boxB): ## 计算相交框的坐标 ## bboxA[0][1] 左上角坐标 bboxA[2][3] 右下角坐标 x1 = np.max([boxA[0], boxB[0]]) y1 = np.max([boxA[1], boxB[1]]) x2 = np.min([boxA[2], boxB[2]]) y2 = np.min([boxA[3], boxB[3]]) ## 计算交区域,并区域,及IOU S_A = (boxA[2]-boxA[0]+1)*(boxA[3]-boxA[1]+1) S_B = (boxB[2]-boxB[0]+1)*(boxB[3]-boxB[1]+1) interArea = np.max([x2-x1+1, 0])*np.max([y2-y1+1,0])##一定要和0比较大小,如果是负数就说明压根不相交 unionArea = S_A + S_B - interArea iou = interArea/unionArea return iouboxA = [1,1,3,3]boxB = [2,2,4,4]IOU = ComputeIOU(boxA, boxB)手撕代码NMS
对整个bboxes排序的写法import numpy as npdef nms(dets, iou_thred, cfd_thred): if len(dets)==0: return [] bboxes = np.array(dets) ## 对整个bboxes排序 bboxes = bboxes[np.argsort(bboxes[:,4])] pick_bboxes = []# print(bboxes) while bboxes.shape[0] and bboxes[-1,-1] >= cfd_thred: bbox = bboxes[-1] x1 = np.maximum(bbox[0], bboxes[:-1,0]) y1 = np.maximum(bbox[1], bboxes[:-1,1]) x2 = np.minimum(bbox[2], bboxes[:-1,2]) y2 = np.minimum(bbox[3], bboxes[:-1,3]) inters = np.maximum(x2-x1+1, 0) * np.maximum(y2-y1+1, 0) unions = (bbox[2]-bbox[0]+1)*(bbox[3]-bbox[1]+1) + (bboxes[:-1,2]-bboxes[:-1,0]+1)*(bboxes[:-1,3]-bboxes[:-1,1]+1) - inters ious = inters/unions keep_indices = np.where(ious不改变bboxes,维护orders的写法始终维护orders,代表到原bboxes的映射(map) 优化1:仅维护orders,不改变原bboxes 优化2:提前计算好bboxes的面积,以免在循环中多次重复计算
import numpy as npdef nms(dets, iou_thred, cfd_thred): if len(dets)==0: return [] bboxes = np.array(dets) ## 维护orders orders = np.argsort(bboxes[:,4]) pick_bboxes = [] x1 = bboxes[:,0] y1 = bboxes[:,1] x2 = bboxes[:,2] y2 = bboxes[:,3] areas = (x2-x1+1)*(y2-y1+1) ## 提前计算好bboxes面积,防止在循环中重复计算 while orders.shape[0] and bboxes[orders[-1],-1] >= cfd_thred: bbox = bboxes[orders[-1]] xx1 = np.maximum(bbox[0], x1[orders[:-1]]) yy1 = np.maximum(bbox[1], y1[orders[:-1]]) xx2 = np.minimum(bbox[2], x2[orders[:-1]]) yy2 = np.minimum(bbox[3], y2[orders[:-1]]) inters = np.maximum(xx2-xx1+1, 0) * np.maximum(yy2-yy1+1, 0) unions = areas[orders[-1]] + areas[orders[:-1]] - inters ious = inters/unions keep_indices = np.where(iousNMS的改进思路
根据手动设置阈值的缺陷,通过自适应的方法在目标系数时使用小阈值,目标稠密时使用大阈值。例如Adaptive NMS将低于阈值的直接置为0的做法太hard,通过将其根据IoU大小来进行惩罚衰减,则变得更加soft。例如Soft NMS,Softer NMS。只能在CPU上运行,速度太慢的改进思路有三个,一个是设计在GPU上的NMS,如CUDA NMS,一个是设计更快的NMS,如Fast NMS,最后一个是掀桌子,设计一个神经网络来实现NMS,如 ConvNMS。IoU的做法存在一定缺陷,改进思路是将目标尺度、距离引进IoU的考虑中。如DIoUIOU相关优化(giou,diou,ciou)
GIOU
普通IOU是对两个框的距离不敏感的,下面两张图中,左图预测框的坐标要比右图预测框的坐标更接近真实框。但两者的IOU皆为0,如果直接把IOU当作loss函数进行优化,则loss=0,没有梯度回传,所以无法进行训练。
但是,GIOU也存在它的缺点:当两个预测框高宽相同,且处于同一水平面时,GIOU就退化为IOU。此外,GIOU和IOU还有两个缺点:收敛较慢、回归不够准确。
DIOU
在介绍DIOU之前,先来介绍采用DIOU的效果:如图,黑色代表anchor box, 蓝色红色代表default box,绿色代表真实目标存在的框GT box的位置,期望红蓝框与绿框尽可能重合。第一行是使用GIOU训练网络,让预测边界框尽可能回归到真实目标边界框中,迭代到400次后才勉强重合。第二行使用DIOU训练网络,到达120步时,发现与目标边界框已经完全重合。可以看出,相对于GIOU,DIOU的不仅收敛速度更快,准确率也更高。
我们再看一组图,图中给出了3组目标边界框与目标边界框的重合关系,显然他们的重合位置不相同的,我们期望第三种重合(两个box中心位置尽可能重合。这三组计算的IOU loss和GIoU loss是一模一样的,因此这两种损失不能很好表达边界框重合关系)。但是DIOU计算出的三种情况的损失是不一样的,显然DIOU更加合理。
从公式和示意图中,我们可以看到,DIoU有几个优点:
DIoU的惩罚项是基于中心点的距离和对角线距离的比值,避免了像GIoU在两框距离较远时,产生较大的外包框,Loss值较大难以优化(因为它的惩罚项是 A ∪ B 比上最小外包框的面积)。所以DIoU Loss收敛速度会比GIoU Loss快。
即使在一个框包含另一个框的情况下,c值不变,但d值也可以进行有效度量。
CIOU LOSS:
论文中,作者表示一个优秀的回归定位损失应该考虑三种几何参数:重叠面积、中心点距离、长宽比。CIoU就是在DIoU的基础上增加了检测框尺度的loss,增加了长和宽的loss,这样预测框就会更加的符合真实框。
审核编辑 :李倩