FCOS难点记录

在这里插入图片描述
FCOS 中有计算 特征图(Feature map中的每个特征点到gt_box的左、上、右、下的距离)

1、特征点到gt_box框的 左、上、右、下距离计算

		x = coords[:, 0] # h*w,2   即 第一列y = coords[:, 1] l_off = x[None, :, None] - gt_boxes[..., 0][:, None, :]  # [1,h*w,1]-[batch_size,1,m]-->[batch_size,h*w,m]t_off = y[None, :, None] - gt_boxes[..., 1][:, None, :]r_off = gt_boxes[..., 2][:, None, :] - x[None, :, None]b_off = gt_boxes[..., 3][:, None, :] - y[None, :, None]ltrb_off = torch.stack([l_off, t_off, r_off, b_off], dim=-1)  # [batch_size,h*w,m,4]areas = (ltrb_off[..., 0] + ltrb_off[..., 2]) * (ltrb_off[..., 1] + ltrb_off[..., 3])  # [batch_size,h*w,m]off_min = torch.min(ltrb_off, dim=-1)[0]  # [batch_size,h*w,m]off_max = torch.max(ltrb_off, dim=-1)[0]  # [batch_size,h*w,m]

根据上边的画的图可以看出,假设对应的 feature map 大小为 2x2,stride=4,原始图片为8x8。将特征图中的每个特征点映射回去,可以得到相应的 4个(h*w个)坐标。对应图中的 红色a,绿色b,黄色c和蓝色d的点。

print(x,"\n",y,x.shape)
'''
tensor([2., 6., 2., 6.]) 
tensor([2., 2., 6., 6.]) torch.Size([4])
'''print(x[None,:,None]) # [1,4,1]
'''
tensor([[[2.],[6.],[2.],[6.]]]) 
'''print(gt_boxes) # [1,2,4]  batch=1, 两个框,每个框左上角和右下角坐标
'''
tensor([[[5, 4, 7, 6],[1, 1, 4, 6]]])
'''print(gt_boxes[...,0],gt_boxes[...,0][:,None,:])
''' 
tensor([[5, 1]]) tensor([[[5, 1]]])
'''
l_off = [2,2]-[5,1]=[-3,1]  以此类推print(l_off,"\n", l_off.shape)'''
**第一列代表,所有的点abcd横坐标与第一个框的左边偏移量。第二列代表到第二个框的偏移量**
tensor([[[-3.,  1.],[ 1.,  5.],[-3.,  1.],[ 1.,  5.]]]) torch.Size([1, 4, 2])'''print(ltrb_off)
'''
第一列代表,所有的投影点abcd,到两个框的左边偏移量。第一行第二行分别代表两个框。
tensor([[[[-3., -2.,  5.,  4.], # a 点到第一个框的左边、上边、右边、下边的偏移[ 1.,  1.,  2.,  4.]], # a 点到第二框的左边、上边、右边、下边的偏移[[ 1., -2.,  1.,  4.], # b 点到第一个框的左边、上边、右边、下边的偏移[ 5.,  1., -2.,  4.]],[[-3.,  2.,  5.,  0.],[ 1.,  5.,  2.,  0.]],[[ 1.,  2.,  1.,  0.],[ 5.,  5., -2.,  0.]]]]) torch.Size([1, 4, 2, 4]) #[batch_size,h*w,m,4]
'''print(ltrb_off[...,0])
'''tensor([[[-3.,  1.],[ 1.,  5.],[-3.,  1.],[ 1.,  5.]]]) torch.Size([1, 4, 2])
'''print(areas)
'''
areas: tensor([[[ 4., 15.],[ 4., 15.],[ 4., 15.],[ 4., 15.]]])
'''torch.return_types.min(
values=tensor([[[-3.,  1.],[-2., -2.],[-3.,  0.],[ 0., -2.]]]),
indices=tensor([[[0, 0],[1, 2],[0, 3],[3, 2]]])) torch.return_types.max(
values=tensor([[[5., 4.],[4., 5.],[5., 5.],[2., 5.]]]),
indices=tensor([[[2, 3],[3, 0],[2, 1],[1, 0]]]))

2、确定该特征点在哪一个框内,是否在该FPN特征层进行尺寸判断并进行后续预测

off_min = torch.min(ltrb_off, dim=-1)[0]  # [batch_size,h*w,m] # off_min 找出所有 特征点  到 每个框的 四条边 最小的距离
off_max = torch.max(ltrb_off, dim=-1)[0]  # [batch_size,h*w,m]  #off_max 找出所有 特征点  到 每个框的 四条边 最大的距离mask_in_gtboxes = off_min > 0
mask_in_level = (off_max > limit_range[0]) & (off_max <= limit_range[1]) # 锁定在这个limit range上的所有的特征的点	
print("ltrf_off",ltrb_off)
print("off_min",off_min,"\n","off_max",off_max)
print("mask_in_gtboxes-->",mask_in_gtboxes)
print("mask_in_level-->",mask_in_level)'''
ltrf_off tensor([[[[-3., -2.,  5.,  4.], # a 点到第一个框的左边、上边、右边、下边的偏移[ 1.,  1.,  2.,  4.]],  # a 点到第二个框的左边、上边、右边、下边的偏移[[ 1., -2.,  1.,  4.], # b 点到第一个框的左边、上边、右边、下边的偏移[ 5.,  1., -2.,  4.]],[[-3.,  2.,  5.,  0.],[ 1.,  5.,  2.,  0.]],[[ 1.,  2.,  1.,  0.],[ 5.,  5., -2.,  0.]]]])off_min 
tensor([[[-3.,  1.], # a点到第一个框最小距离-3,  a点到第二个框的最小偏移距离 1[-2., -2.], #b点到第一个框最小距离-2,  b点到第二个框的最小偏移距离 -2[-3.,  0.], # c点到第一个框最小距离-3,  a点到第二个框的最小偏移距离 0[ 0., -2.]]]) # d点到第一个框最小距离0,  a点到第二个框的最小偏移距离 -2off_max tensor([[[5., 4.],[4., 5.],[5., 5.],[2., 5.]]])mask_in_gtboxes-->  # 判断了 特征点是否在框内
tensor([[[False,  True],  # a点到第一个框四边最小偏移距离小于0,所以,a点不属于第一个框,为false;以此类推。[False, False],[False, False],[False, False]]]) # [batch,h*w,m]mask_in_level-->  # 锁定在这个limit range上的所有的特征的点	
tensor([[[True, True],  # 锁定了a 在这个level中[True, True],  # 锁定了b[True, True],  # 锁定了c[True, True]]])# 锁定了d  都在这个FPN级别上  [batch,h*w,m]
'''

3、特征点是否在框中心的范围内,用来判断是否为正样本

	radiu = stride * sample_radiu_ratio # 4*1.15 = 4.6gt_center_x = (gt_boxes[..., 0] + gt_boxes[..., 2]) / 2gt_center_y = (gt_boxes[..., 1] + gt_boxes[..., 3]) / 2c_l_off = x[None, :, None] - gt_center_x[:, None, :]  # [1,h*w,1]-[batch_size,1,m]-->[batch_size,h*w,m]c_t_off = y[None, :, None] - gt_center_y[:, None, :]c_r_off = gt_center_x[:, None, :] - x[None, :, None]c_b_off = gt_center_y[:, None, :] - y[None, :, None]c_ltrb_off = torch.stack([c_l_off, c_t_off, c_r_off, c_b_off], dim=-1)  # [batch_size,h*w,m,4]c_off_max = torch.max(c_ltrb_off, dim=-1)[0]mask_center = c_off_max < radiu
print("c_ltrb_off",c_ltrb_off)
print("c_off_max",c_off_max)
print("mask_center",mask_center)'''
c_ltrb_off 
tensor([[[[-4.0000, -3.0000,  4.0000,  3.0000],  # 同上边一样,a到 第一个框 小的中心框四边 的距离[-0.5000, -1.5000,  0.5000,  1.5000]], # a到 第二个框 小的中心框四边 的距离[[ 0.0000, -3.0000,  0.0000,  3.0000], # b到 第一个框 小的中心框四边 的距离[ 3.5000, -1.5000, -3.5000,  1.5000]], # # b到 第二个框 小的中心框四边 的距离[[-4.0000,  1.0000,  4.0000, -1.0000],[-0.5000,  2.5000,  0.5000, -2.5000]],[[ 0.0000,  1.0000,  0.0000, -1.0000],[ 3.5000,  2.5000, -3.5000, -2.5000]]]])c_off_max tensor([[[4.0000, 1.5000], # 找到a特征点到第一个框中心框和第二个框的中心框的 最大距离[3.0000, 3.5000],[4.0000, 2.5000],[1.0000, 3.5000]]]) # [batch,h*w,m] 4个特征点(a,b,c,d) x 框的个数2个(第一个框,第二个框)mask_center tensor([[[True, True], # 判断是否在这个框里中心点里边 正样本[True, True],[True, True],[True, True]]]) ## [batch,h*w,m]
'''

3、制定mask,根据上边的 gt_box、fpn_level、mask_center

‘’’
mask_pos 是三个约束条件的交集,分别是特征点在gt中,特征点在level中,以及特征点距离Gt中的center小于指定的范围
‘’’

mask_pos = mask_in_gtboxes & mask_in_level & mask_center  # [batch_size,h*w,m]areas[~mask_pos] = 99999999
areas_min_ind = torch.min(areas, dim=-1)[1]  # [batch_size,h*w]
mask_pos = mask_in_gtboxes & mask_in_level & mask_center  # [batch_size,h*w,m]
print("pre_areas:",areas)
areas[~mask_pos] = 99999999
areas_min_ind = torch.min(areas, dim=-1)[1]  # [batch_size,h*w] # 返回索引,注意和上边的区别,上边返回值,比大小
# torch.max()  or  torch.min() dim=0 找列,dim=1  找行
print("mask_pos-->",mask_pos)
print("post_ares",areas)
print("areas_min_ind",areas_min_ind)'''
mask_in_gtboxes--> 
tensor([[[False,  True],[False, False],[False, False],[False, False]]])
mask_in_level--> 
tensor([[[True, True],[True, True],[True, True],[True, True]]])
mask_center 
tensor([[[True, True],[True, True],[True, True],[True, True]]])mask_pos--> 
tensor([[[False,  True],  # 只有a点在第二个框在这个fpn这个level, 同时满足这三个条件[False, False],[False, False],[False, False]]])post_ares 
tensor([[[1.0000e+08, 1.5000e+01],[1.0000e+08, 1.0000e+08],[1.0000e+08, 1.0000e+08],[1.0000e+08, 1.0000e+08]]]) # #[batch_size,h*w,m] 将 满足要求的 保持面积不面,其他设置为很大的值areas_min_ind tensor([[1, 0, 0, 0]]) # [batch_size,h*w] min[1]返回的是对应的indices  找到最小的面积,返回索引。'''

4、 回归的目标

给a,b,c,d四个特征点 确定 偏移量。用于后续回归

![在这里插入图片描述](https://img-blog.csdnimg.cn/3e504ea230ff47c097ba9eb6caddca55.png在这里插入图片描述

reg_targets = ltrb_off[torch.zeros_like(areas, dtype=torch.bool)
.scatter_(-1, areas_min_ind.unsqueeze(dim=-1), 1)]  # [batch_size*h*w,4]
reg_targets = torch.reshape(reg_targets, (batch_size, -1, 4))  # [batch_size,h*w,4]
scatter_的用法:参考 https://blog.csdn.net/weixin_43496455/article/details/103870889
scatter(dim, index, src)将src中数据根据index中的索引按照dim的方向进行填充。dim=0
'''
areas: 
tensor([[[ 4., 15.],[ 4., 15.],[ 4., 15.],[ 4., 15.]]]) [1,4,2]
扩展维度之后  [1,4] --> torch.Size([1, 4, 1]) ===> [[[1,0,0,0]]]
torch.zeros_like(areas, dtype=torch.bool) 
tensor([[[False, False],[False, False],[False, False],[False, False]]])after scatter_--> 
tensor([[[False,  True],[ True, False],[ True, False],[ True, False]]]) # [1,4,2]ltrf_off 
tensor([[[[-3., -2.,  5.,  4.], # a 点到第一个框的左边、上边、右边、下边的偏移[ 1.,  1.,  2.,  4.]],  # a 点到第二个框的左边、上边、右边、下边的偏移[[ 1., -2.,  1.,  4.], # b 点到第一个框的左边、上边、右边、下边的偏移[ 5.,  1., -2.,  4.]],[[-3.,  2.,  5.,  0.],[ 1.,  5.,  2.,  0.]],[[ 1.,  2.,  1.,  0.],[ 5.,  5., -2.,  0.]]]])reg_targets1 
tensor([[ 1.,  1.,  2.,  4.], # a 点 第二个框[ 1., -2.,  1.,  4.], # b 点 第一个框[-3.,  2.,  5.,  0.], # c 点 第一个框[ 1.,  2.,  1.,  0.]])# d 点 第一个框# torch.Size([4, 4])reg_targets2 tensor([[[ 1.,  1.,  2.,  4.],[ 1., -2.,  1.,  4.],[-3.,  2.,  5.,  0.],[ 1.,  2.,  1.,  0.]]]) # torch.Size([1, 4, 4])
'''

5、 目标的分类

给a,b,c,d四个点分配类别

# 设置classes = torch.tensor([[100,200]])
classes = torch.broadcast_tensors(classes[:, None, :], areas.long())[0]  # [batch_size,h*w,m]
cls_targets = classes[torch.zeros_like(areas, dtype=torch.bool).scatter_(-1, areas_min_ind.unsqueeze(dim=-1), 1) ]
cls_targets = torch.reshape(cls_targets, (batch_size, -1, 1))  # [batch_size,h*w,1]``````pythonclasses = torch.broadcast_tensors(classes[:, None, :], areas.long())[0]  # [batch_size,h*w,m]print("class",classes,classes.shape)cls_targets = classes[torch.zeros_like(areas, dtype=torch.bool).scatter_(-1, areas_min_ind.unsqueeze(dim=-1), 1)]print(torch.zeros_like(areas, dtype=torch.bool).scatter_(-1, areas_min_ind.unsqueeze(dim=-1), 1))print("cls_targets1",cls_targets,cls_targets.shape)cls_targets = torch.reshape(cls_targets, (1, -1, 1))  # [batch_size,h*w,1]print("cls_targets",cls_targets,cls_targets.shape)
'''
class 
tensor([[[100, 200],[100, 200],[100, 200],[100, 200]]]) torch.Size([1, 4, 2])cls_targets1 
tensor([200, 100, 100, 100]) torch.Size([4])cls_targets 
tensor([[[200], # a点属于第二个框,的类别200[100], # b点属于第一个框,的类别100[100], # c点。。。。。。[100]]]) torch.Size([1, 4, 1]) [batch_size,h*w,1]'''

6、 center-ness

在这里插入图片描述
越靠边,cneterness越小。

	left_right_min = torch.min(reg_targets[..., 0], reg_targets[..., 2])  # [batch_size,h*w]print("reg_trargets[...,0]",reg_targets[..., 0],reg_targets[..., 2])left_right_max = torch.max(reg_targets[..., 0], reg_targets[..., 2])top_bottom_min = torch.min(reg_targets[..., 1], reg_targets[..., 3])top_bottom_max = torch.max(reg_targets[..., 1], reg_targets[..., 3]) cnt_targets = (((left_right_min * top_bottom_min) / (left_right_max * top_bottom_max + 1e-10)).sqrt().unsqueeze(dim=-1))  # [batch_size,h*w,1]
reg_targets  a,b,c,d四个点与对应框的 偏移量。
tensor([[[ 1.,  1.,  2.,  4.],[ 1., -2.,  1.,  4.],[-3.,  2.,  5.,  0.],[ 1.,  2.,  1.,  0.]]]) # torch.Size([1, 4, 4])tensor([[ 1.,  1., -3.,  1.]]) tensor([[2., 1., 5., 1.]])
left_right_min tensor([[ 1.,  1., -3.,  1.]])
left_right_max tensor([[2., 1., 5., 1.]])
top_bottom_min tensor([[ 1., -2.,  0.,  0.]])
top_bottom_max tensor([[4., 4., 2., 2.]])cnt_targets:
tensor([[[0.3536],[   nan],[-0.0000],[0.0000]]]) torch.Size([1, 4, 1])

7、 确定最后的结果

		assert reg_targets.shape == (batch_size, h_mul_w, 4)assert cls_targets.shape == (batch_size, h_mul_w, 1)assert cnt_targets.shape == (batch_size, h_mul_w, 1)# process neg coordsmask_pos_2 = mask_pos.long().sum(dim=-1)  # [batch_size,h*w]# num_pos=mask_pos_2.sum(dim=-1)# assert num_pos.shape==(batch_size,)mask_pos_2 = mask_pos_2 >= 1assert mask_pos_2.shape == (batch_size, h_mul_w)cls_targets[~mask_pos_2] = 0  # [batch_size,h*w,1]cnt_targets[~mask_pos_2] = -1reg_targets[~mask_pos_2] = -1return cls_targets, cnt_targets, reg_targets
mask_pos--> 
tensor([[[False,  True],  # 只有a点在第二个框在这个fpn这个level, 同时满足这三个条件[False, False],[False, False],[False, False]]])mask_pos2--> 
# mask_pos_2 = mask_pos.long().sum(dim=-1)  # [batch_size,h*w]
tensor([[1, 0, 0, 0]]) torch.Size([1, 4]) # 按照列相加,第一列+第二列
# mask_pos_2 = mask_pos_2 >= 1
mask_pos_2-->  # 看特征点是否同时存在于多个满足条件
tensor([[ True, False, False, False]]) # 【1,4】print(cls_targets)
print(cnt_targets)
print(reg_targets)#将非 positive location的地方设置成 cls设置成0 ,reg_targets 设置成对应的-1cls_targets[~mask_pos_2] = 0  # [batch_size,h*w,1]
cnt_targets[~mask_pos_2] = -1
reg_targets[~mask_pos_2] = -1cls_targets 
tensor([[[200], # a点属于第二个框,的类别200[100], # b点属于第一个框,的类别100[100], # c点。。。。。。[100]]]) torch.Size([1, 4, 1]) [batch_size,h*w,1]
tensor([[[200],[  0],[  0],[  0]]])cnt_targets:
tensor([[[0.3536],[   nan],[-0.0000],[0.0000]]]) torch.Size([1, 4, 1])         
tensor([[[ 0.3536],[-1.0000],[-1.0000],[-1.0000]]])reg_targets2 
tensor([[[ 1.,  1.,  2.,  4.],[ 1., -2.,  1.,  4.],[-3.,  2.,  5.,  0.],[ 1.,  2.,  1.,  0.]]]) # torch.Size([1, 4, 4])
tensor([[[ 1.,  1.,  2.,  4.],[-1., -1., -1., -1.],[-1., -1., -1., -1.],[-1., -1., -1., -1.]]])

至此呢,经过层层限制,能够找到符合三个条件的 特征点,例如,本案例为 a点,符合第二个框。并给出a点对应的 类别-200;cnt值-0。3536;偏移量【1,1,2,4】

值的注意的是,满足三个条件为正样本,cnt是计算所有正样本的 centerness值,后续为了抑制低质量的正样本,根据cnterness的值计算了一个loss。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/174830.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用U盘安装ubuntu22操作教程

U盘启动 将烧录好的U盘&#xff0c;插上待安装系统的电脑 服务器在开机之后长按【ESC键】进入BIOS选项中&#xff0c;选择对应的U盘启动 如下图&#xff0c;在界面中“USB”选项就是我的U盘&#xff0c;第一启动项选择U盘启动&#xff0c;其他启动项不动&#xff0c;选择后按F…

【推荐】一款AI写作大师、问答、绘画工具-「智元兔 AI」

在当今技术飞速发展的时代&#xff0c;越来越多的领域开始应用人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;。其中&#xff0c;AI写作工具备受瞩目&#xff0c;备受推崇。在众多的选择中&#xff0c;智元兔AI是一款在笔者使用过程中非常有帮助的…

使用gitflow时如何合并hotfix

前言 在使用 git flow 流程时, 对于项目型的部署项目经常会遇到一个问题, 就是现场项目在使用历史版本时发现的一些问题需要修复, 但升级可能会有很大的风险或客户不愿意升级, 这时就要求基于历史版本进行 hotfix 修复. 基于历史发布版本的缺陷修复方式不同于最新发布版本的补…

SQL使用

--天空会的像哭过&#xff0c;离开你以后 并没有更自由 SQL进行数据的删除 一、删除delete 语法 delete [from] 表名称 where 条件数据删除&#xff0c;不能删除某一列&#xff0c;因为删除是对记录而言 2.1 删除是一条一条删除&#xff0c;每次删除都会将操作写入日志文件 删…

JPA Buddy快速创建update、find、count、delete、exists方法

JPA Buddy快速创建update、find、count、delete、exists方法&#xff0c;JPA默认提供的CrudRepository\JpaRepository提供的方法比较少&#xff0c;一般我们会手写一些方法&#xff0c;这里我们选择通过JPA Buddy快速生成&#xff0c;之前文章中讲到了JPA Buddy原本是IDEA收费插…

Word软件手动安装Zotero插件

文章目录 Word软件手动安装Zotero插件方法一方法二 参考资料 Word软件手动安装Zotero插件 方法一 关闭word在zotero中依次点击编辑—首选项—引用—文字编辑软件—重新安装加载项Microsoft word 方法二 寻找Zotero.dotm存储位置&#xff0c; 例如D:\Program Files\Zotero\ext…

kernelbase.dll故障怎么处理?Kernelbase.dll故障的解决方法

在使用Windows操作系统过程中&#xff0c;有可能出现kernelbase.dll故障的情况。本文将详细介绍几种修复kernelbase.dll文件的方法&#xff0c;并对这个重要的dll文件进行简要的介绍。 一.kernelbase.dll文件概述 Kernelbase.dll是Windows系统中的一个关键动态链接库&#xff…

阿里云优惠券介绍、作用、领取入口及使用教程

阿里云是阿里巴巴集团倾力打造的云计算品牌&#xff0c;提供丰富多样的云计算产品及服务&#xff0c;为了吸引用户&#xff0c;阿里云经常推出各种优惠活动&#xff0c;其中就包括阿里云优惠券的发放。本文将为大家详细介绍阿里云优惠券的作用、领取入口以及使用教程。 一、阿里…

leetcode:21. 合并两个有序链表

一、题目 函数原型&#xff1a; struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 二、思路 合并两个有序链表为一个新的升序链表&#xff0c;只需要遍历两个有序链表并比较结点值大小&#xff0c;依次将较小的结点尾插到新链表即可。 三、代码…

arcgis基础篇--实验

一、绘制带空洞的面要素 方法一&#xff1a;先绘制出一个面区域&#xff0c;然后在面上再绘制一个面区域代表面洞&#xff0c;两者位于同一个图层内&#xff0c;选中代表面洞的区域&#xff0c;选择【编辑器】-【裁剪】工具&#xff0c;将面裁剪出一个洞&#xff0c;随后删除代…

零代码秒集成打通小鹅通订单支付信息与 CRM合同接口

随着科技的不断进步&#xff0c;数字化已经成为了商业世界的核心。企业和组织必须紧跟数字化趋势&#xff0c;以适应快速变化的市场需求和消费者行为。企业需要做到快速反应市场的需求变化&#xff0c;从产品设计到产品生产&#xff0c;每一步都离不开技术人员对系统的操作&…

现货黄金职业交易员怎么使用技术分析?

职业的交易员每天要处理很多不同的信息&#xff0c;其中只一部分是涉及技术指标。在这一部分处理技术分析的时间里&#xff0c;只能再分出少之又少的时间给技术指标。那职业交易员会利用做技术指标做什么呢&#xff1f;下面我们就来讨论一下。 识别行情。技术指标的主要作用就是…