目标检测|边框检测框转换,交并比计算 代码实现

文章目录

  • 1. 相互转换的函数
  • 2.交并比实现

在目标检测任务中,非常重要的一部分就是框出检测框

这就需要检测框的位置大小等一些信息

一般我们有如下两种方式标记一个检测的位置和大小

1 两点法 检测框左上角坐标(x1,y1),检测框右下角坐标(x2,y2)

2 中心法 检测框中心的坐标(x,y)和检测框的宽w,高h

这两种表述方式都可以表达一个检测框的位置

因而他们也可以相互转换

1. 相互转换的函数

我们实际中处理的往往是一批框

这时我们不用for循环依次转换,而是直接用张量的切片操作!

import torch
#两角表示法[x1,y1,x2,y2]
#中心表示法[x,y,w,h]
#模拟传入10个框,每个框有四维度
boxes=torch.rand(10,4)
#两点法转换为中心法
def corner_to_center(boxes):
    x1=boxes[:,0]
    y1=boxes[:,1]
    x2=boxes[:,2]
    y2=boxes[:,3]
    w=x2-x1
    h=y2-y1
    x=(x1+x2)*0.5
    y=(y1+y2)*0.5
    return torch.stack((x,y,w,h),axis=-1)#注意这里不能用cat,stack可以增加一个维度,我们在之前操作之后他们的维度都降低了,所以要用stack

#中心法转换为两点法
def center_to_corner(boxes):
    x=boxes[:,0]
    y=boxes[:,1]
    w=boxes[:,2]
    h=boxes[:,3]
    x1=x-w*0.5
    y1=y-h*0.5
    x2=x+w*0.5
    y2=y+h*0.5
    return torch.stack((x1,y1,x2,y2),axis=-1)

这里我第一次写这个函数的时候,在最后拼接的时候写成了torch.cat,这是有问题的

torch.cattorch.stack 都是PyTorch中用于组合张量(tensors)的函数,但它们在如何组合张量以及输出的形状方面有一些重要的区别。

  1. torch.cat(Concatenate):
    • torch.cat 用于沿着指定的维度(通常是现有维度)连接多个张量。
    • 你需要指定一个维度作为连接维度,这个维度必须在所有输入张量中具有相同的大小,除了连接维度外的其他维度可以不同。
    • 输出张量将在连接维度上沿着所有输入张量连接起来,不会创建新的维度。
    • 例如,如果你有两个形状为 (3, 4)(3, 5) 的张量,并使用 torch.cat 连接它们,你将得到一个形状为 (3, 9) 的输出张量。
  2. torch.stack:
    • torch.stack 用于在一个新维度上堆叠多个张量,它会为新的维度创建一个新的轴。
    • 所有输入张量必须具有相同的形状。
    • 你需要指定一个维度来堆叠这些张量,这将成为新的维度。
    • 输出张量的维度比输入张量的维度高一个。
    • 例如,如果你有两个形状为 (3, 4) 的张量,并使用 torch.stack 堆叠它们,你将得到一个形状为 (2, 3, 4) 的输出张量,其中新的维度是2。

总结:

  • 使用 torch.cat 来连接张量,通常是在现有维度上进行的。
  • 使用 torch.stack 来创建新的维度并堆叠张量。
  • torch.cat 不会增加张量的维度,而 torch.stack 会增加一个新的维度。根据你的需求,你可以选择使用其中之一。

2.交并比实现

交并比是判断两个检测框重叠大小的重要指标

交并比=两个框相交的面积/两个框并的面积

我们先看两个检测框的交并比计算怎么实现

两个框无非两种情况

1 有相交

目标检测|边框检测框转换,交并比计算 代码实现_第1张图片

2 无相交

目标检测|边框检测框转换,交并比计算 代码实现_第2张图片

对于第一种情况

我们需要知道两个框里左上角坐标更大的那个坐标,和右下角坐标更小的坐标,如下图的红点,知道这两个红点以后就可以求交的面积了

用右下角的红点坐标减去左上角的红点坐标即可,就得到宽和高了
目标检测|边框检测框转换,交并比计算 代码实现_第3张图片

对于第二种情况

我们同样求得两个框里左上角坐标更大的那个坐标,和右下角坐标更小的坐标

两个相减得到负数

目标检测|边框检测框转换,交并比计算 代码实现_第4张图片

既然如此,说明如果相减是负数,则不相交,这时候把他置0,这是交并比就会得0

如果是正数,说明得到相交的宽高,那么一乘即可

def box_iou(boxes1,boxes2):
    box_area=lambda boxes:((boxes[:,2]-boxes[:,0])*(boxes[:,3]-boxes[:,1]))#定义一个求面积的函数
    area1=box_area(boxes1)#求第一组边界框面积
    area2=box_area(boxes2)#求第二组边界框面积
    #获得左上角的坐标的较大值,右下角的坐标的较小值
    inter_upperlefts=torch.max(boxes1[:,None,:2],boxes2[:,:2])  #注意这里的boxes1和boxes2的数量不一定相等,因而这里用了None升高维度做匹配
    inter_lowerrights=torch.min(boxes1[:,None,2:],boxes2[:,2:])
    inters=(inter_lowerrights-inter_upperlefts).clamp(min=0)#.clamp函数将所有小于 0 的元素设置为 0,而保留所有大于等于 0 的元素不变,过滤掉不相交的情况
    inter_aress=inters[:,:,0]*inters[:,:,1]
    union_aress=area1[:,None]+area2-inter_aress
    return inter_aress/union_aress

这里可以理解为第一组框的每一个和第二组框依次求交并比

那么假如第一组框有10个,第二组框有5个

那么总共返回10×5=50个结果

你可能感兴趣的:(计算机视觉CV,目标检测,人工智能,计算机视觉)