一、目标检测的任务是什么?
- 定位——目标在哪里;
- 分类——目标是什么;
图1 目标检测结果图
二、目标检测的基础知识
1.参数IoU(Intersection over Union)
把A看作真实的bounding box,把B看作预测的bounding box,那么IoU反映的是真实bounding box和预测bounding box的重叠率,IoU越接近1,重叠率越高,预测定位越准确。
2. anchor
(1)anchor:是不同尺度(scale)和不同宽高比(ratio)的参考框。
(2)anchor是人们根据数据集人为预设的参考框。
(3)Anchor 的使用与作用[1]
Anchor Box的生成是以CNN网络最后一层的Feature Map上的点为中心的(映射回原图的坐标),以Faster R-CNN为例,使用VGG网络对输入的图像下采样了16倍,也就是Feature Map上的一个点对应于输入图像上的一个16×16的正方形区域(感受野)。根据预定义的Anchor,Feature Map上的一点为中心 就可以在原图上生成9种不同形状不同大小的边框,如图3:
从上图也可以看出为什么需要Anchor。根据CNN的感受野,一个Feature Map上的点对应于原图的16×16的正方形区域,仅仅利用该区域的边框进行目标定位,其精度无疑会很差,甚至根本“框”不到目标。 而加入了Anchor后,一个Feature Map上的点可以生成9中不同形状不同大小的框,这样“框”住目标的概率就会很大,就大大的提高了检查的召回率;再通过后续的网络对这些边框进行调整,其精度也能大大的提高。
(4)anchor的另一个作用[2]
在anchor出现之前,无论是基于滑动窗口的DPM还是生成两个bounding box的YOLOv1,一个网格只能检测一个目标,如图4中,把原图划分成3x3网格,那么第三第二列网格负责检测人和汽车两个目标,不用anchor就只能检测出其中一个目标或者把两个目标当做一个整体检测出,总之一个网格最多只能检测出一个目标,图中y是没有anchor时一个网格的输出向量。
Anchor可以解决上述问题,用两个box去检测这两个目标,如图5所示。用anchor box1检测人,用anchor box2检测汽车,y是一个网格的输出向量。在实际应用中,会用多个anchor box。比如YOLOv3中预设9个anchor,网络预测时,从9个anchor中用K均值筛选出3个anchor。
图中用了两个Anchor Box,y向量中参数的含义:
pc:网格中是否含有目标对象
bx:目标对象中心点的x坐标
by:目标对象中心点的y坐标
bh:目标对象的高度
bw:目标对象的宽度
c1,c2,c3:目标对象的类别
(5)anchor的缺点
①anchor的引入会出现正负样本不均衡。大多数目标检测算法需要一组非常多的anchor,如在DSSD中超过4万,在RetinaNet中超过10万,但一张图中目标数量很少,这就导致正样本数量会远远少于负样本。因此有了对负样本做欠采样以及focal loss等算法来解决这个问题。
②anchor的引入增加了很多的超参数,比如anchor的数量,anchor的大小,anchor比例等,这使得更加复杂,特别是与金字塔输入结合时,每个尺度特征要和它自己的一组anchor boxes对应。
3.NMS
(1)NMS: non maximum suppression,非极大值抑制
(2)NMS的作用:在检测任务中去除多余的检测框。
(3)NMS的深度理解[3]
如图6所示,在目标检测任务中,每一个目标会检测出多个bounding boxes,每一个bounding box 有一个对应的score,一般认为score越大,越接近真实的bounding box,NMS操作步骤如下(NMS是针对每一类目标去做):
①将所有检测到的bounding boxes按score排序,并选出得分最高的bounding box 为M。
②遍历其他的bounding boxes,如果M和当前的bounding box的IoU大于设定的阈值,则删除当前bounding box
③从未处理的bounding boxes中继续选一个得分最高的,重复上述过程。
(4)NMS实现[4]
①. 找出分数最高的M;
②. 将M对应的box从B中删除;
③. 将删除的box添加到集合D中;
④. 从B中删除与M对应的box重叠区域大于阈值Nt的其他框;
⑤. 重复上述步骤1-4。
其中si可表述为:
Mask RCNN中的python实现:
def non_max_suppression(boxes, scores, threshold):
"""执行non-maximum suppression并返回保留的boxes的索引.
boxes: [N, (y1, x1, y2, x2)].注意(y2, x2)可以会超过box的边界.
scores: box的分数的一维数组.
threshold: Float型. 用于过滤IoU的阈值.
"""
assert boxes.shape[0] > 0
if boxes.dtype.kind != "f":
boxes = boxes.astype(np.float32)
# 计算box面积
y1 = boxes[:, 0]
x1 = boxes[:, 1]
y2 = boxes[:, 2]
x2 = boxes[:, 3]
area = (y2 - y1) * (x2 - x1)
# 获取根据分数排序的boxes的索引(最高的排在对前面)
ixs = scores.argsort()[::-1]
pick = []
while len(ixs) > 0:
# 选择排在最前的box,并将其索引加到列表中
i = ixs[0]
pick.append(i)
# 计算选择的box与剩下的box的IoU
iou = compute_iou(boxes[i], boxes[ixs[1:]], area[i], area[ixs[1:]])
# 确定IoU大于阈值的boxes. 这里返回的是ix[1:]之后的索引,
# 所以为了与ixs保持一致,将结果加1
remove_ixs = np.where(iou > threshold)[0] + 1
# 将选择的box和重叠的boxes的索引删除.
ixs = np.delete(ixs, remove_ixs)
ixs = np.delete(ixs, 0)
return np.array(pick, dtype=np.int32)
三、目标检测位置预测方法:
1.滑动窗口:用一个窗口滑动遍历每一个像素来定位目标。如:DPM.
2.anchor:如:faster-rcnn,YOLOv2,YOLOv3
3.关键点检测:cornernet用检测目标的左上角和右下角两个关键点来定位目标。
4.其他:(1)YOLOv1用生成两个box来预测定位。
(2)RCNN用选择性搜索的方法来预测边界框。
相关笔记
RCNN学习笔记
Fast RCNN 学习笔记
YOLOv1学习笔记
YOLOv2学习笔记
CornerNet学习笔记
参考
[1]目标检测 1 : 目标检测中的Anchor详解
[2]目标检测中的Anchor Box算法:
[3] NMS——非极大值抑制:
[4]【目标检测】NMS(Non-maximum suppression,非极大值抑制)算法