三维点云处理06-2D/3DIoU计算
- IoU定义:预测边框与真是边框的交集与并集之比
- 首先说明IoU的计算并不需要像下图所示对各种情况进行分类后,再进行计算
- IoU的计算本质上是集合交集的计算,首先从一维IoU的计算开始,然后扩展到二维等等
一维IoU计算
-
首先看上图右侧一维IoU的计算,IoU的计算本质就是集合上下边界的计算
1.计算交集的下界:max(x1,y1) 2.计算交集的下界:min(x2,y2) 3.判断交集是否真是存在:上界-下界: min(x2,y2) - max(x1,y1) 如果上界-下界 > 0 交集存在 如果上界 - 下界 <=0 交集不存在 4.计算并集:集合A + 集合B - 集合A和B的交集 (x2 - x1) + (y2 - y1) - (min(x2,y2) - max(x1,y1)) 5.计算IoU
def iou(set_a, set_b):
'''
一维IoU的计算
'''
# 获得集合A和B的边界
x1, x2 = set_a
y1, y2 = set_b
# 计算交集的上下界
low = max(x1,y1)
high - min(x2, y2)
# 计算交集
if high - low < 0:
inter = 0
else:
inter = high - low
# 计算并集
union = (x2 -x1) + (y2 - y1) - inter
# 计算IoU
iou = inter / union
return iou
二维IoU计算
-
从一维IoU的计算拓展到二维IoU的计算,就是计算X和Y两个方向上交集的上界和下界
-
二维bbox的输入一般有两种形式:
一种是中心+宽高的形式:(x,y,w,h); 一种是左上和右下两个角的形式:(x1,y1,x2,y2)
def iou(box1,box2):
'''
二维IoU的计算:
注意图像坐标系的原点一般在左上角,x方向朝右,y方向朝下
box的表示:[top, left, bottom, right]
box的表示分别对应:[y1,x1,y2,x2]
'''
in_h = min(box1[2],box2[2]) - max(box1[0],box2[0])
in_w = min(box1[3],box2[3]) - max(box1[1],box2[1])
inter = 0 if in_h < 0 or in_w < 0 else in_h * in_w
union = (box1[2] - box1[0]) * (box1[3] - box1[1]) + (box2[2] - box2[0]) * (box2[3] - box2[1]) - inter
iou = inter / union
return iou
def iou(box1,box2):
'''
二维Iou计算
box表示形式:[x,y,w,h]
'''
x_max = box1[0] + box1[2] /2
y_max = box1[1] + box1[3] /2
x_min = box1[0] - box1[2] /2
y_min = box1[1] - box1[3] / 2
l_x_max = box2[0] + box2[2] /2
l_y_max = box2[1] + box2[3] /2
l_x_min = box2[0] - box2[2] /2
l_y_min = box2[1] - box2[3] / 2
inter_x_max = min(x_max,l_x_max)
inter_x_min = max(x_min,l_x_min)
inter_y_max = min(y_max, l_y_max)
inter_y_min = max(y_min,l_y_min)
inter_w = inter_x_max - inter_x_min
inter_h = inter_y_max - inter_y_min
inter = 0 if inter_w < 0 or inter_h < 0 else inter_w * inter_h
union = (box1[2] * box1[3]) + (box2[2] * box2[3]) - inter
iou = inter / union
return iou
三维IoU计算
- 3D IoU的计算与2D和1D类似,核心思想仍然是寻找各个维度上的交集
def iou(box1,box2):
'''
3D IoU计算
box表示形式:[x1,y1,z1,x2,y2,z2] 分别是两对角点的坐标
'''
in_w = min(box1[3],box2[3]) - max(box1[0],box2[0])
in_l = min(box1[4],box2[4]) - max(box1[1],box2[1])
in_h = min(box1[5],box2[5]) - max(box1[2],box2[2])
inter = 0 if in_w < 0 or in_l < 0 or in_h < 0 else in_w * in_l * in_h
union = (box1[3] - box1[0]) * (box1[4] - box1[1]) * (box1[5] - box1[2]) + (box2[3] - box2[0]) * (box2[4] - box2[1]) * (box2[5] - box2[2]) - inter
iou = inter / union
return iou
def iou(box1,box2):
'''
3D Iou计算
box表示形式:[x,y,z,w,l,h]
'''
x_max = box1[0] + box1[3] / 2
y_max = box1[1] + box1[4] / 2
z_max = box1[2] + box1[5] / 2
x_min = box1[0] - box1[3] / 2
y_min = box1[1] - box1[4] / 2
z_min = box1[2] - box1[5] / 2
l_x_max = box2[0] + box2[3] / 2
l_y_max = box2[1] + box2[4] / 2
l_z_max = box2[2] + box2[5] / 2
l_x_min = box2[0] - box2[3] / 2
l_y_min = box2[1] - box2[4] / 2
l_z_min = box2[2] - box2[5] / 2
inter_x_max = min(x_max, l_x_max)
inter_x_min = max(x_min, l_x_min)
inter_y_max = min(y_max, l_y_max)
inter_y_min = max(y_min, l_y_min)
inter_z_max = min(z_max,l_z_max)
inter_z_min = max(z_min,l_z_min)
inter_w = inter_x_max - inter_x_min
inter_l = inter_y_max - inter_y_min
inter_h = inter_z_max - inter_z_min
inter = 0 if inter_w < 0 or inter_l < 0 or inter_h < 0 else inter_w * inter_l * inter_h
area1 = (x_max - x_min) * (y_max - y_min) * (z_max - z_min)
area2 = (l_x_max - l_x_min) * (l_y_max - l_y_min) * (l_z_max - l_z_min)
union = area1 + area2 - inter
iou = inter / union
return iou
2维旋转IoU的计算
- 使用opencv库函数实现
def iou_rotate_calculate(boxes1, boxes2):
'''
2D旋转框的表示:[x ,y, w, h, theta],旋转角theta单位是角度,而不是弧度
'''
# 计算boxes1中旋转框的面积
area1 = boxes1[:,2] * boxes1[:,3]
# 计算boxes2中旋转框的面积
area2 = boxes2[:,2] * boxes2[:,3]
# 创建用于存储iou的list
ious = []
for i, box1 in enumerate(boxes1):
temp_ious = []
r1 = ((box1[0],box1[1]),(box1[2],box1[3]),box1[4])
for j, box2 in enumerate(boxes2):
r2 = ((box2[0],box2[1]),(box2[2],box2[3]),box2[4])
int_pts = cv2.rotatedRectangleIntersection(r1,r2)[1]
if in_pts is not None:
order_pts = cv2.convexHull(in_pts, returnPoints = True)
int_area = cv2.contourArea(order_pts)
iou = in_area * 1.0 / (area1[i] + area2[j] - int_area)
temp_ious.append(iou)
else:
temp_ious.append(0.0)
ious.append(temp_ious)
return np.array(ious,dtype=np.float32)