NMS算法原理及代码验证

NMS算法常常在图像目标检测的各种算法中使用。原始图像中,单个检测目标往往被识别出多个位置、大小都不相同的目标检测框,这些检测框可以是类似于这样的名字,bbox(bounding box), region proposal, anchors等等。可以在诸如faster rcnn或YOLO算法中看到。

举例来讲,原始图中包含两个检测物体,每个检测物体会存在许多检测框。因为是同一个物体,因此这些框的IOU值都很高(相比较不同物体的检测框来说)。针对同一个检测目标,有必要只留下置信度(score)最高的那个检测框作为该物体的检测框,其它的都应该过滤掉。

该算法具体的步骤如下:

1、假定有6个带置信率的region proposals,并预设一个IOU的阈值如0.7。

2、按置信率大小对6个框排序: 0.95, 0.9, 0.9, 0.8, 0.7, 0.7。

3、设定置信率为0.95的region proposals为一个物体框;

4、在剩下5个region proposals中,去掉与0.95物体框IOU大于0.7的。

5、重复2~4的步骤,直到没有region proposals为止。

6、每次获取到的最大置信率的region proposals就是我们筛选出来的目标。

这个操作的直观结果,就是图片上每个待检查物体,仅仅保留一个置信率最大region proposals。

凡是与这个置信率最大的框相交面积大于某个阈值的其它框,统统去掉。

因此,调整这个IOU的阈值,往往是图像目标检测算法的一个调整点。

 

以下是一段用来实现了NMS算法的代码:

 

'''
# This file isn't part of faster CNN, just for testing something.
'''

# 验证MNS算法
import numpy as np
dets = np.array([
                [204, 102, 358, 250, 0.5],
                [257, 118, 380, 250, 0.7],
                [280, 135, 400, 250, 0.6],
                [255, 118, 360, 235, 0.7]])
thresh = 0.7


def py_cpu_nms(dets,  thresh):
    """Pure Python NMS baseline."""
    x1 = dets[:, 0]  #xmin
    y1 = dets[:, 1]  #ymin
    x2 = dets[:, 2]  #xmax
    y2 = dets[:, 3]  #ymax
    scores = dets[:, 4]  #confidence

    areas = (x2 - x1 + 1) * (y2 - y1 + 1)  #the size of bbox
    order = scores.argsort()[::-1]  #sort bounding boxes by decreasing order, returning array([3, 1, 2, 0])

    keep = []        # store the final bounding boxes
    while order.size > 0:
        i = order[0]      # 永远取置信率最高的框作为物体的最佳框
        keep.append(i)    # 保存起来

        # 获取两个框相交矩形的坐标
        # 左上角坐标取二者最大;右下角取二者最小
        xx1 = np.maximum(x1[i], x1[order[1:]]) #array([ 257.,  280.,  255.])
        yy1 = np.maximum(y1[i], y1[order[1:]]) #array([ 118.,  135.,  118.])
        xx2 = np.minimum(x2[i], x2[order[1:]]) #array([ 360.,  360.,  358.])
        yy2 = np.minimum(y2[i], y2[order[1:]]) #array([ 235.,  235.,  235.])

        w = np.maximum(0.0, xx2 - xx1 + 1)   #array([ 104.,   81.,  104.])
        h = np.maximum(0.0, yy2 - yy1 + 1)   #array([ 118.,  101.,  118.])
        # 计算相交矩形面积
        inter = w * h   #array([ 12272.,   8181.,  12272.])

        # 计算IOU
        # Cross Area / (bbox + particular area - Cross Area)
        ovr = inter / (areas[i] + areas[order[1:]] - inter)
        #reserve all the boundingbox whose ovr less than thresh
        # 找出与当前置信率最高框相交小于阈值的框的索引
        inds = np.where(ovr <= thresh)[0]
        # 只保留比例小于阙值的框,然后继续处理
        order = order[inds + 1]

    return keep

index = py_cpu_nms(dets, thresh)
print(index)
print(dets[index])

 

你可能感兴趣的:(机器学习,NMS,我的深度学习之路)