今天在改模型的时候刚好用到了IOU,因此将IOU说说,记录一下代码,方便以后复用。
IoU 的全称为交并比(Intersection over Union),它的计算也比较简单,就是两个目标proposal框重叠的区域比总体的区域。如下图所表示的,着就是所谓的IOU。
在做目标检测的过程中有一个指标来评价这个模型的好坏,也就mAP。这个指标我下次再说,用检测出来的框和ground-truth之间计算IOU,如果IOU大于0.5或者其它的一个阈值,那么就认为该目标框被检测出来了。计算mAP的其中一步就需要用到IOU的计算值。比如在Faster rcnn这个模型中也需要用Iou去挑选proposal(128前景+128背景)
从上图中可以看出来,两个区域的交集是黄色区域,因此我们只需要计算出来黄色区域的面积areaC,A,B区域的面积分别是areaA,areaB。因此Iou=C/A+B-C。公式十分明了,我们只需要计算来各个部分的面积就可以了。
首先将IOU计算的输入,分别是A,B区域的坐标,以A举例说明,A=(x1,y1,x2,y2)。首先搞清楚A中坐标的含义,分别是左上角和右下角的坐标,在图像中的直接坐标是这样的:
因此确定了左上角的坐标和右下角的坐标,我们就可以计算出来areaA和areaB的面积,计算重叠区域稍微有一点麻烦。
计算出来重叠区域的左上角和重叠区域的右下角,那么就可以把重叠区域的宽和长分别计算出来,
上面已经提到A的坐标了,B=(X1,Y1,X2,Y2)
左上角的横坐标 new_x1 = max(x1,X1)
右下角的横坐标 new_x2 = min(x2,X2)
左上角的纵坐标 new_y1 = max(y1,Y1)
右下角的纵坐标 new_y2 = min(y2,Y2)
既然左上角和右下角的坐标都有了计算面积就完事了。
def bbox_overlaps(anchors, gt_boxes):
"""
anchors: (N, 4) ndarray of float
gt_boxes: (K, 4) ndarray of float
overlaps: (N, K) ndarray of overlap between boxes and query_boxes
"""
#输入进来的是list,将list转换成tensor格式进行计算
anchors = torch.Tensor(anchors[:4]).unsqueeze(0)
gt_boxes = torch.Tensor(gt_boxes[:4]).unsqueeze(0)
N = anchors.size(0)
K = gt_boxes.size(0)
gt_boxes_area = ((gt_boxes[:,2] - gt_boxes[:,0] + 1) *
(gt_boxes[:,3] - gt_boxes[:,1] + 1)).view(1, K)
anchors_area = ((anchors[:,2] - anchors[:,0] + 1) *
(anchors[:,3] - anchors[:,1] + 1)).view(N, 1)
boxes = anchors.view(N, 1, 4).expand(N, K, 4)
query_boxes = gt_boxes.view(1, K, 4).expand(N, K, 4)
iw = (torch.min(boxes[:,:,2], query_boxes[:,:,2]) -
torch.max(boxes[:,:,0], query_boxes[:,:,0]) + 1)
iw[iw < 0] = 0
ih = (torch.min(boxes[:,:,3], query_boxes[:,:,3]) -
torch.max(boxes[:,:,1], query_boxes[:,:,1]) + 1)
ih[ih < 0] = 0
ua = anchors_area + gt_boxes_area - (iw * ih)
overlaps = iw * ih / ua
return overlaps
这个函数接受的参数是tensor格式的,我输入进来的是列表形式,将列表形式转换成tensor格式就可以了。至于每次计算出来的宽为啥加1,我也不是很清楚,我猜想应该是计算出来有误差,所以统一都加上1了。