交并比(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)
非极大值抑制(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