目标检测算法基础概念:边框回归和NMS

2020-06-10 16:43:23 浏览数 (1)

【导读】前面我们详细介绍了目标检测领域常用的一些评价指标。本文我们来讨论一下在目标检测算法中必须掌握的两个基本概念:边框回归和NMS(非极大值抑制)。

边框回归的背景

如下图所示:

对于上图,绿色的框表示Ground Truth, 红色的框为Selective Search提取的Region Proposal。那么即便红色的框被分类器识别为飞机,但是由于红色的框定位不准(IoU<0.5), 那么这张图相当于没有正确的检测出飞机。如果我们能对红色的框进行微调, 使得经过微调后的窗口跟Ground Truth 更接近, 这样岂不是定位会更准确。确实,Bounding-box regression 就是用来微调这个窗口的。

边框回归的含义

对于窗口一般使用四维向量(x,y,w,h)来表示, 分别表示窗口的中心点坐标和宽高。边框回归的目的就是:在给定一组候选目标框 ,寻找到一个

映射 ,使得 。边界框回归过程图像表示如下图所示。在图2中红色框代表候选目标框,绿色框代表真实目标框,蓝色框代表边界框回归算法预测目标框,红色圆圈代表选候选目标框的中心点,绿色圆圈代表选真实目标框的中心点,蓝色圆圈代表选边界框回归算法预测目标框的中心点。

边界框回归中的变换

RCNN论文里指出,边界框回归是利用平移变换和尺度变换来实现映射 。平移变换的计算公式如下:

尺度变换的计算公式如下:

宽高尺度设计

由于CNN具有尺度不变性,以下图为例:

我们想要得到一个放缩的尺度,也就是说这里限制尺度必须大于0。我们学习的tw,th怎么保证满足大于0呢?直观的想法就是EXP函数,如公式(2)所示,那么反过来推导就是Log函数的来源了。

为什么IoU较大时边界框回归可视为线性变换?

在这里我们需要回顾下在高等数学中有关等价无穷小的结论:

NMS的定义

NMS(Non-maximum suppression),即非极大值抑制,在目标检测中的出镜率也很高呀。在目标检测中,不论是最初的region proposal,还是后来的anchor box,不可避免的一个问题就是对于同一个物体,会预测出多个bounding box,如下左图所示。而NMS所做的就是去除掉多余的bounding box,只保留和ground truth重叠度最高的bounding box,如下右图所示。

在目标检测中,分类器会给每个bounding box(bbox)计算出一个class score,就是这个bbox属于每一类的概率,NMS就是根据这些值来进行的,主要流程:

  • 对于每一类,首先把所有score<threshold的bbox的score设为0
  • 之后,将所有的bbox按照得分排序,选中最高分及其对应的bbox
  • 遍历其余的bbox,如果和当前最高分bb的重叠面积(IoU)大于一定的阀值,便将该bbox删除
  • 从未处理的bbox中继续选择一个最高分的bb,重复上述过程
  • 重复上述过程,直到找到全部保留的bbox
  • 然后根据所有保留bbox的class score和class color画出最后的预测结果

NMS的实现(Pytorch代码)

代码语言:javascript复制
from __future__ import absolute_import

import numpy as np
import torch

def nms(dets, thresh):
    dets = dets.numpy()
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]
    scores = dets[:, 4]

    areas = (x2 - x1   1) * (y2 - y1   1)
    order = scores.argsort()[::-1]

    keep = []
    while order.size > 0:
        i = order.item(0)
        keep.append(i)
        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])

        w = np.maximum(0.0, xx2 - xx1   1)
        h = np.maximum(0.0, yy2 - yy1   1)
        inter = w * h
        ovr = inter / (areas[i]   areas[order[1:]] - inter)

        inds = np.where(ovr <= thresh)[0]
        order = order[inds   1]

    return torch.IntTensor(keep)

参考链接:

1. https://blog.csdn.net/zijin0802034/article/details/77685438

2. https://zhuanlan.zhihu.com/p/76603583

0 人点赞