目标检测——IOU和NMS计算

IOU

交并比(Intersection-over-Union,IoU),在目标检测领域,通常指在图片中两个方框面积之间的交并比。给定两个方框C,G。则有:
I O U ( C , G ) = a r e a ( C ) ⋂ a r e a ( G ) a r e a ( C ) ⋃ a r e a ( G ) 其 中 a r e a ( C ) 代 表 方 框 C 的 面 积 , 其 它 同 理 。 IOU(C,G) = \frac{area(C)\bigcap area(G)}{area(C)\bigcup area(G)} \\其中area(C)代表方框C的面积,其它同理。 IOU(C,G)=area(C)area(G)area(C)area(G)area(C)C
在这里插入图片描述
作用:在目标检测算法中,以Faster_Rcnn为例,对于一张图片,模型会预测生成多个Anchor(预测方框),这些预测的方框和图片中实际的真实方框肯定是不完全匹配的, 如何确定每个Anchor是大概属于哪个真实方框,通过计算两者之间IOU值即可,通常还规定一个iou阈值(iou_threshold),若预测框和真实框之间的iou值大于iou_threshold,就表明此预测框具有和真实框的相同属性(如类别、是否前景)。

python实现
bbox_a通常代表对于一张图片模型预测的Anchor、bbox_b代表对应此图片中的真实方框。当然,在具体函数传值时两者交换也无妨,只需注意最后函数返回矩阵中的行列对应关系即可。

def bbox_iou(bbox_a, bbox_b):
    """
	计算两组方框之间的IOU值。
	
	bbox_a:一个numpy.ndarray型二维数组,shape为(N,4),N代表bbox_a包含的方框个数
	bbox_b: 一个numpy.ndarray型二维数组,shape为(k,4),K代表bbox_b包含的方框个数
	4表示每个方框的坐标,按顺序依次表示y_min,x_min,y_max,x_max
	min代表左上角,max代表右下角,在图片中,左上角代表坐标原点,正方向为下、右。
	
	此函数需要计算的就是bbox_a中的每个方框与bbox_b中的每个方框的IOU值,所以最后返回的数组shape为(N,K)
	
Calculate the Intersection of Unions (IoUs) between bounding boxes.

    IoU is calculated as a ratio of area of the intersection
    and area of the union.

    This function accepts both :obj:`numpy.ndarray` and :obj:`cupy.ndarray` as
    inputs. Please note that both :obj:`bbox_a` and :obj:`bbox_b` need to be
    same type.
    The output is same type as the type of the inputs.

    Args:
        bbox_a (array): An array whose shape is :math:`(N, 4)`.
            :math:`N` is the number of bounding boxes.
            The dtype should be :obj:`numpy.float32`.
        bbox_b (array): An array similar to :obj:`bbox_a`,
            whose shape is :math:`(K, 4)`.
            The dtype should be :obj:`numpy.float32`.

    Returns:
        array:
        An array whose shape is :math:`(N, K)`. \
        An element at index :math:`(n, k)` contains IoUs between \
        :math:`n` th bounding box in :obj:`bbox_a` and :math:`k` th bounding \
        box in :obj:`bbox_b`.

    """
    if bbox_a.shape[1] != 4 or bbox_b.shape[1] != 4:
        raise IndexError

    # top left
    tl = np.maximum(bbox_a[:, None, :2], bbox_b[:, :2])
    # bottom right
    br = np.minimum(bbox_a[:, None, 2:], bbox_b[:, 2:])

    area_i = np.prod(br - tl, axis=2) * (tl < br).all(axis=2)
    area_a = np.prod(bbox_a[:, 2:] - bbox_a[:, :2], axis=1)
    area_b = np.prod(bbox_b[:, 2:] - bbox_b[:, :2], axis=1)
    return area_i / (area_a[:, None] + area_b - area_i)

NMS

非极大值抑制(non maximum suppression,NMS),在目标检测领域中,以Faster_Rcnn算法为例,对于一张图片,模型最后会预测出许多方框,以及该方框的预测得分,如下图所示:
在这里插入图片描述
明显上图不会作为最终预测结果,因为有太多重叠方框(即方框之间的IOU值太大),此时只需采用NMS算法优化即可,优化结果如下图所示:
在这里插入图片描述
总的来说,NMS的算法思想就是:若两个方框之间的IOU值大于设定的阈值,即可认同两个方框属于同一种类方框(识别的目标一样),显然需要去除得分较低的哪个方框。整个算法需要做的就是重复上述过程,直到没有可以去除的。

至于详细过程可参见FasterRcnn作者给出的python版本的nms代码。除此之外,还可以直接调用pytorch(>=1.2.0)、torchvision(>= 0.3)中封装好了的nms函数。

from torchvision.ops import nms
keep = nms(boxes,scores,iou_threshold)  

#返回的keep表示为经过nms后保留下来的boxes的索引值,并且keep的中索引值是按照scores得分降序排列的
#len(keep) <= len(boxes)

#通过下列操作即可获取具体nms后的boxes
boxes = boxes[keep]

参数:

boxes (Tensor[N, 4])) – bounding boxes坐标. 格式:(x1, y1, x2, y2)

scores (Tensor[N]) – bounding boxes得分

iou_threshold (float) – IoU过滤阈值

参考文献:
Faster-RCNN详解和torchvision源码解读(五):NMS(非极大值抑制)
Unexpected behavior of torchvision.ops.nms

猜你喜欢

转载自blog.csdn.net/qq_35268841/article/details/107526707