2D_IOU
计算两个矩形的交并比,预测检测值和真值的差距
判断两条线段相交
# 两条线段存在交及
line_1 = [1, 5]
line_2 = [3, 5]
# 两条线段最左端
l1_x1 = line_1[0]
l1_x2 = line_1[1]
# 两条线段最右端
l2_x1 = line_2[0]
l2_x2 = line_2[1]
# 计算最左端重叠
inner_x1 = max(l1_x1, l2_x1)
# 计算最右端重叠
inner_x2 = min(l1_x2, l2_x2)
# 计算重叠面积
inner_l = max((inner_x2 - inner_x1), 0)
计算矩形IOU
box1 = [1, 1, 3, 3]
box2 = [2, 2, 3, 3]
def iou(box1, box2):
# 计算y轴重叠
in_h = min(box1[3], box2[3]) - max(box1[1], box2[1])
# 计算x轴重叠
in_w = min(box1[2], box2[2]) - max(box1[0], box2[0])
# 计算xy重叠面积
inner = 0 if in_w < 0 or in_h < 0 else in_w * in_h
# 计算两个矩形并及
union = (box1[2] - box1[0]) * (box1[3] - box1[1]) + (box2[2] - box2[0]) * (box2[3] - box2[1]) - inner
# 计算iou
iou = inner / union
return iou
NMS
将那些不是最大值的给抑制下去
我们程序接受的是这个图片里面的所有框,但是我们并不知道每个框代表是谁,所以这里就用到iou了,我们将iou的值比较大的就归于同一个物体,这样我们只需要计算iou即可
nms算法的流程如下:
1.我们先将所有候选框的置信度排序,因为我们最终是要最大的
2.将置信度最大的加入到最终的返回值中
3.将其他的候选框和当前的最大的那个计算iou
4.如果iou大于一个阈值,则可删除(说明和置信度大的那个是重叠的)
5.将剩下的框重复以上过程
boxes = np.array([[100, 100, 210, 210, 0.72],
[250, 250, 420, 420, 0.8],
[220, 220, 320, 330, 0.92],
[100, 100, 210, 210, 0.72],
[230, 240, 325, 330, 0.81],
[220, 230, 315, 340, 0.9]])
def nms(bboxs, thr):
x1 = bboxs[:, 0]
y1 = bboxs[:, 1]
x2 = bboxs[:, 2]
y2 = bboxs[:, 3]
score = bboxs[:, 4]
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
order = np.argsort(score)
print(order)
keep = []
while order.size > 0:
index = order[-1]
keep.append(index)
inner_x1 = np.maximum(x1[index], x1[order[:-1]])
inner_x2 = np.minimum(x2[index], x2[order[:-1]])
inner_y1 = np.maximum(y1[index], y1[order[:-1]])
inner_y2 = np.minimum(y2[index], y2[order[:-1]])
in_w = np.maximum(0.0, inner_x2 - inner_x1 + 1)
in_h = np.maximum(0.0, inner_y2 - inner_y1 + 1)
inner = in_w * in_h
# 利用相交的面积和两个框自身的面积计算框的交并比, 将交并比大于阈值的框删除 对应第4步
ratio = inner / (areas[index] + areas[order[:-1]] - inner)
left = np.where(ratio < thr) # left里面对应的就是<thr的索引
order = order[left] # 将所有<thr的索引取出来
return keep
BEV_IOU(3D鸟瞰图)
计算A框与B框的IOU值
def calculate_iou_3d(box_a, box_b):
"""
计算两个3D框的IoU
:param box_a: 框A,格式为[x, y, z, w, l, h, yaw]
:param box_b: 框B,格式为[x, y, z, w, l, h, yaw]
:return: 两个框的IoU
"""
# 计算框A和框B在水平方向上的重叠部分的长度
x_min_a, x_max_a = box_a[0] - box_a[3] / 2, box_a[0] + box_a[3] / 2
x_min_b, x_max_b = box_b[0] - box_b[3] / 2, box_b[0] + box_b[3] / 2
w = min(x_max_a, x_max_b) - max(x_min_a, x_min_b)
# 计算框A和框B在垂直方向上的重叠部分的长度
y_min_a, y_max_a = box_a[1] - box_a[4] / 2, box_a[1] + box_a[4] / 2
y_min_b, y_max_b = box_b[1] - box_b[4] / 2, box_b[1] + box_b[4] / 2
l = min(y_max_a, y_max_b) - max(y_min_a, y_min_b)
# 计算框A和框B在高度方向上的重叠部分的长度
z_min_a, z_max_a = box_a[2] - box_a[5] / 2, box_a[2] + box_a[5] / 2
z_min_b, z_max_b = box_b[2] - box_b[5] / 2, box_b[2] + box_b[5] / 2
d = min(z_max_a, z_max_b) - max(z_min_a, z_min_b)
# 如果水平方向或垂直方向上没有重叠部分,或者高度方向上的重叠部分长度小于等于0,则两个框的IoU为0
if w <= 0 or l <= 0 or d <= 0:
return 0.0
# 计算两个框的交集的体积和并集的体积
intersection_volume = w * l * d
box_a_volume = box_a[3] * box_a[4] * box_a[5]
box_b_volume = box_b[3] * box_b[4] * box_b[5]
union_volume = box_a_volume + box_b_volume - intersection_volume
# 计算两个框的IoU
iou = intersection_volume / union_volume
return iou