1 两个box之间计算iou比较简单
def iou(box1, box2):
xi1 = max(box1[0], box2[0])
yi1 = max(box1[1], box2[1])
xi2 = min(box1[2], box2[2])
yi2 = min(box1[3], box2[3])
inter_area = (yi2-yi1) * (xi2-xi1)
box1_area = (box1[2] - box1[0]) * (box1[3]-box1[1])
box2_area = (box2[2] - box2[0]) * (box2[3]-box2[1])
union_area = box1_area + box2_area - inter_area
return inter_area/union_area
2 多个bbox计算,bbox_a [256, 4], bbox_b [3, 4] 得到的函数返回值为 [256, 3] 得到每个iou
以bbox1 = np.array([[50, 50, 100, 100],[80, 80, 125, 125], [90, 90, 125, 125]]).reshape(3, 4)
bbox2 = np.array([[60, 60, 120, 120], [40, 40, 60, 60]]).reshape(2, 4)为例
1) 方法1 ,用for循环,优点是代码清晰,可理解性强,缺点效率低
def cacl_iou(valid_anchors, bbox):
ious = np.empty((len(valid_anchors), bbox.shape[0]), dtype=np.float32)
ious.fill(0)
# print(bbox)
for num1, i in enumerate(valid_anchors):
ya1, xa1, ya2, xa2 = i
anchor_area = (ya2 - ya1) * (xa2 - xa1)
for num2, j in enumerate(bbox):
yb1, xb1, yb2, xb2 = j
box_area = (yb2- yb1) * (xb2 - xb1)
inter_x1 = max([xb1, xa1])
inter_y1 = max([yb1, ya1])
inter_x2 = min([xb2, xa2])
inter_y2 = min([yb2, ya2])
if (inter_x1 < inter_x2) and (inter_y1 < inter_y2):
iter_area = (inter_y2 - inter_y1) * \
(inter_x2 - inter_x1)
iou = iter_area / \
(anchor_area+ box_area - iter_area)
else:
iou = 0.
ious[num1, num2] = iou
# print(ious.shape)
return ious
2) 方法2, 利用numpy广播特性,效率高
def bbox_iou(bbox_a, bbox_b):
"""
以bbox1 = np.array([[50, 50, 100, 100],[80, 80, 125, 125], [90, 90, 125,
125]]).reshape(3, 4)
bbox2 = np.array([[60, 60, 120, 120], [40, 40, 60, 60]]).reshape(2, 4)为例
"""
if bbox_a.shape[1] != 4 or bbox_b.shape[1] != 4:
raise IndexError
tl = np.maximum(bbox_a[:, None, :2], bbox_b[:, :2]) #这里是[3, 1, 2]和[2,2]运算
#自动扩充到[3, 2, 2]和[3, 2, 2]运算 下面也一样
br = np.minimum(bbox_a[:, None, 2:], bbox_b[:, 2:])
area_i = np.prod(br - tl, axis=2) * (tl < br).all(axis=2)#[3, 2]
area_a = np.prod(bbox_a[:, 2:] - bbox_a[:, :2], axis=1) #[3, ]
area_b = np.prod(bbox_b[:, 2:] - bbox_b[:, :2], axis=1) #[2, ]
return area_i / (area_a[:, None] + area_b - area_i)
# [3, 2] / ([3, 1] + [2, ] - [3, 2])
注意[ 3, 1 ] + [ 2, ] 的shape为[3, 2]