笔者使用numpy实现了GIOU,废话不多说,直接贴上代码:
import numpy as np
def GIOU (boxes1 , boxes2 ):
"calculate GIOU "
'''
boxes1 shape : shape (n, 4)
boxes2 shape : shape (k, 4)
gious: shape (n, k)
'''
IOU = []
GIOU = []
num = (boxes1[:,0]).size
x1 = boxes1[:,0]
y1 = boxes1[:,1]
x2 = boxes1[:,2]
y2 = boxes1[:,3]
xx1=boxes2[:,0]
yy1=boxes2[:,1]
xx2=boxes2[:,2]
yy2=boxes2[:,3]
area1 = (x2 -x1) * (y2 -y1) #求取框的面积
area2 = (xx2-xx1) * (yy2- yy1)
for i in range (num):
inter_max_x = np.minimum(x2[i], xx2[:]) #求取重合的坐标及面积
inter_max_y = np.minimum(y2[i], yy2[:])
inter_min_x = np.maximum(x1[i], xx1[:])
inter_min_y = np.maximum(y1[i], yy1[:])
inter_w = np.maximum(0 ,inter_max_x-inter_min_x)
inter_h = np.maximum(0 ,inter_max_y-inter_min_y)
inter_areas = inter_w * inter_h
out_max_x = np.maximum(x2[i], xx2[:]) #求取包裹两个框的集合C的坐标及面积
out_max_y = np.maximum(y2[i], yy2[:])
out_min_x = np.minimum(x1[i], xx1[:])
out_min_y = np.minimum(y1[i], yy1[:])
out_w = np.maximum(0, out_max_x - out_min_x)
out_h = np.maximum(0, out_max_y - out_min_y)
outer_areas = out_w * out_h
union = area1[i] + area2[:] - inter_areas #两框的总面积 利用广播机制
ious = inter_areas / union
gious = ious - (outer_areas - union)/outer_areas # IOU - ((C\union)/C)
print("ious :",ious)
print("gious" ,gious)
IOU.append(ious)
GIOU.append(gious)
return IOU , GIOU
#测试
box1 = np.array([[0,0,1,1]
,[1,1,2,2]
,[2,2,3,3],
])
box2 = np.array([[0,0,2,2],
[2,0,3,1]])
print("+"*30)
print(GIOU(box1,box2))
计算GIOU时由于可能预测box和实际gtbox数量不一致,所以笔者采用了每次取一个gtbox与其他的所有box都计算,然后遍历所有的gtbox均执行此操作即可,实际使用的时候可以将gtbox和预测box按照class_id来进行分别计算,即传入GIOU函数的box按照class_id分别传入,这样可以计算每一类的GIOU,然后求算术平均值即可得到avg_GIOU。
上述的测试结果如下:
++++++++++++++++++++++++++++++
ious : [0.25 0. ]
gious [ 0.25 -0.33333333]
ious : [0.25 0. ]
gious [ 0.25 -0.5 ]
ious : [0. 0.]
gious [-0.44444444 -0.33333333]
([array([0.25, 0. ]), array([0.25, 0. ]), array([0., 0.])], [array([ 0.25 , -0.33333333]), array([ 0.25, -0.5 ]), array([-0.44444444, -0.33333333])])
若此博客对您有所帮助,不胜荣幸。