交并比(Intersection Over Union, IoU)是度量两个目标检测框交叠程度的方式,公式如下
I o U = a r e a ( B p ∩ B g t ) a r e a ( B p ∪ B g t ) \mathrm{IoU}=\frac{\mathrm{area(B_p \cap B_{gt})}}{\mathrm{area(B_p \cup B_{gt})}} IoU=area(Bp∪Bgt)area(Bp∩Bgt)
其中 B g t \mathrm{B_{gt}} Bgt代表真值(Ground Truth), B p \mathrm{B_{p}} Bp代表预测值
I o U \mathrm{IoU} IoU是一种常用的评估目标检测算法性能的指标,其计算的意义如下:
综上所述, I o U \mathrm{IoU} IoU是评估和改进目标检测算法的关键工具之一,下面介绍具体如何计算
2D检测框的 I o U \mathrm{IoU} IoU计算比较直接,就是按照公式
I o U = a r e a ( B p ∩ B g t ) a r e a ( B p ∪ B g t ) \mathrm{IoU}=\frac{\mathrm{area(B_p \cap B_{gt})}}{\mathrm{area(B_p \cup B_{gt})}} IoU=area(Bp∪Bgt)area(Bp∩Bgt)
计算面积,具体如下所示
def cal2dBoxOverlap(g_boxes, q_boxes, criterion=-1):
N, K = g_boxes.shape[0], q_boxes.shape[0]
overlaps = np.zeros((N, K), dtype=g_boxes.dtype)
for k in range(K):
qbox_area = ((q_boxes[k, 2] - q_boxes[k, 0]) * (q_boxes[k, 3] - q_boxes[k, 1]))
for n in range(N):
gbox_area = (g_boxes[n, 2] - g_boxes[n, 0]) * (g_boxes[n, 3] - g_boxes[n, 1])
iw = (min(g_boxes[n, 2], q_boxes[k, 2]) - max(g_boxes[n, 0], q_boxes[k, 0]))
if iw > 0:
ih = (min(g_boxes[n, 3], q_boxes[k, 3]) - max(g_boxes[n, 1], q_boxes[k, 1]))
if ih > 0:
ua = (gbox_area + qbox_area - iw * ih)
overlaps[n, k] = iw * ih / ua
return overlaps
与2D目标检测不同,3D目标检测需要使用3D立方体来表示目标物体的位置和姿态。计算IoU时,需要考虑立方体的3D空间位置、大小和朝向的匹配程度
通常的算法步骤是:
本节介绍旋转2D检测框重叠面积的计算
def inter(rbbox1, rbbox2):
corners1 = cuda.local.array((8, ), dtype=numba.float32)
corners2 = cuda.local.array((8, ), dtype=numba.float32)
intersection_corners = cuda.local.array((16, ), dtype=numba.float32)
rbbox2corners(corners1, rbbox1)
rbbox2corners(corners2, rbbox2)
num_intersection = quadrilateralIntersection(corners1, corners2, intersection_corners)
sortVertexInConvex(intersection_corners, num_intersection)
return area(intersection_corners, num_intersection)
其中quadrilateralIntersection()
函数计算了重叠部分的顶点信息,具体而言,通过求直线的交点和判断顶点是否在四边形内部来确定
def quadrilateralIntersection(pts1, pts2, int_pts):
num_of_inter = 0
for i in range(4):
if pointInQuadrilateral(pts1[2 * i], pts1[2 * i + 1], pts2):
int_pts[num_of_inter * 2] = pts1[2 * i]
int_pts[num_of_inter * 2 + 1] = pts1[2 * i + 1]
num_of_inter += 1
if pointInQuadrilateral(pts2[2 * i], pts2[2 * i + 1], pts1):
int_pts[num_of_inter * 2] = pts2[2 * i]
int_pts[num_of_inter * 2 + 1] = pts2[2 * i + 1]
num_of_inter += 1
temp_pts = cuda.local.array((2, ), dtype=numba.float32)
for i in range(4):
for j in range(4):
has_pts = lineSegmentIntersection(pts1, pts2, i, j, temp_pts)
if has_pts:
int_pts[num_of_inter * 2] = temp_pts[0]
int_pts[num_of_inter * 2 + 1] = temp_pts[1]
num_of_inter += 1
return num_of_inter
得到重叠多边形后,通过切割三角形来计算面积
def area(int_pts, num_of_inter):
area_val = 0.0
for i in range(num_of_inter - 2):
area_val += abs(trangleArea(int_pts[:2], int_pts[2 * i + 2:2 * i + 4],
int_pts[2 * i + 4:2 * i + 6]))
return area_val
加上高度维度的重叠信息即可计算3D检测框IoU,这部分与2D检测框IoU计算类似,不再赘述
def cal3dBoxOverlap(g_boxes, q_boxes, r_inc, criterion=-1):
N, K = g_boxes.shape[0], q_boxes.shape[0]
overlaps = np.zeros((N, K), dtype=g_boxes.dtype)
for n in range(N):
for k in range(K):
if r_inc[n, k] > 0:
iw = (min(g_boxes[n, 1], q_boxes[k, 1]) - max(
g_boxes[n, 1] - g_boxes[n, 4], q_boxes[k, 1] - q_boxes[k, 4]))
if iw > 0:
area1 = g_boxes[n, 3] * g_boxes[n, 4] * g_boxes[n, 5]
area2 = q_boxes[k, 3] * q_boxes[k, 4] * q_boxes[k, 5]
inc = iw * r_inc[n, k]
ua = (area1 + area2 - inc)
overlaps[n, k] = inc / ua
return overlaps
本文完整工程代码请通过下方名片联系博主获取
更多精彩专栏: