文章目录
- 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.cat
和 torch.stack
都是PyTorch中用于组合张量(tensors)的函数,但它们在如何组合张量以及输出的形状方面有一些重要的区别。
torch.cat
(Concatenate):torch.cat
用于沿着指定的维度(通常是现有维度)连接多个张量。- 你需要指定一个维度作为连接维度,这个维度必须在所有输入张量中具有相同的大小,除了连接维度外的其他维度可以不同。
- 输出张量将在连接维度上沿着所有输入张量连接起来,不会创建新的维度。
- 例如,如果你有两个形状为
(3, 4)
和(3, 5)
的张量,并使用torch.cat
连接它们,你将得到一个形状为(3, 9)
的输出张量。
torch.stack
:torch.stack
用于在一个新维度上堆叠多个张量,它会为新的维度创建一个新的轴。- 所有输入张量必须具有相同的形状。
- 你需要指定一个维度来堆叠这些张量,这将成为新的维度。
- 输出张量的维度比输入张量的维度高一个。
- 例如,如果你有两个形状为
(3, 4)
的张量,并使用torch.stack
堆叠它们,你将得到一个形状为(2, 3, 4)
的输出张量,其中新的维度是2。
总结:
- 使用
torch.cat
来连接张量,通常是在现有维度上进行的。 - 使用
torch.stack
来创建新的维度并堆叠张量。 torch.cat
不会增加张量的维度,而torch.stack
会增加一个新的维度。根据你的需求,你可以选择使用其中之一。
2.交并比实现
交并比是判断两个检测框重叠大小的重要指标
交并比=两个框相交的面积/两个框并的面积
我们先看两个检测框的交并比计算怎么实现
两个框无非两种情况
1 有相交
2 无相交
对于第一种情况
我们需要知道两个框里左上角坐标更大的那个坐标,和右下角坐标更小的坐标,如下图的红点,知道这两个红点以后就可以求交的面积了
用右下角的红点坐标减去左上角的红点坐标即可,就得到宽和高了
对于第二种情况
我们同样求得两个框里左上角坐标更大的那个坐标,和右下角坐标更小的坐标
两个相减得到负数
既然如此,说明如果相减是负数,则不相交,这时候把他置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个结果