1.Faster rcnn

1.1.概述

  • anchor本身的设置是基于各层输出分辨率上的各点,由各点回归出anchor的偏移量,预测anchor的类别;故anchor的布局需要和各层输出分辨率对应。
  • 输出分辨率各点anchor的数量和尺寸是可以调整的,其设置的合理与否,决定了网络的训练难易程度和模型的精度。
  • anchor大小的设置是对应到输入分辨率【即训练分辨率】大小,和原图大小和输出分辨率无关。

1.2.anchor生成步骤

a) 在rpn网络初始化的同时,完成基础anchor的构建

class RPNHead(AnchorHead):def __init__(self, in_channels,......seperable=False,**kwargs):......super(RPNHead, self).__init__(2, in_channels, **kwargs)class AnchorHead(nn.Module):def __init__(self,num_classes,.......anchor_scales=[8, 16, 32],anchor_ratios=[0.5, 1.0, 2.0],anchor_strides=[4, 8, 16, 32, 64],anchor_base_sizes=None,......super(AnchorHead, self).__init__()self.num_classes = num_classesself.anchor_scales = anchor_scalesself.anchor_ratios = anchor_ratiosself.anchor_strides = anchor_stridesself.anchor_base_sizes = list(anchor_strides) if anchor_base_sizes is None else anchor_base_sizesself.anchor_generators = []for anchor_base in self.anchor_base_sizes:self.anchor_generators.append(AnchorGenerator(anchor_base, anchor_scales, anchor_ratios))self.num_anchors = len(self.anchor_ratios) * len(self.anchor_scales)#对于fpn的网络结构,如果各层设置多个self.anchor_scales,参考方案如下:# self.anchor_generators = []# if len(self.anchor_scales)>1:#     assert len(self.anchor_base_sizes) == len(self.anchor_scales)#     for i, anchor_base in enumerate(self.anchor_base_sizes):#         self.anchor_generators.append(#             AnchorGenerator(anchor_base,self.anchor_scales[i],anchor_ratios)#         )#     self.num_anchors = len(self.anchor_ratios) * len(self.anchor_scales[0])# else:#     for anchor_base in self.anchor_base_sizes:#         self.anchor_generators.append(#             AnchorGenerator(anchor_base, anchor_scales, anchor_ratios))#     self.num_anchors = len(self.anchor_ratios) * len(self.anchor_scales)

相关参数解释:

#anchor基础尺寸的缩放比例,是控制anchor大小最重要的参数
self.anchor_scales = anchor_scales
#anchor的长宽比例设置
self.anchor_ratios = anchor_ratios
#anchor步长设置【和下采样倍数对应,如果不对应将导致图片部分区域没有anchor或anchor的设置超过图片边缘】
self.anchor_strides = anchor_strides
#anchor基础尺寸,可以设置多个,一般等于各层下采样倍数【anchor_stride】即可,anchor的尺寸可以通过self.anchor_scales进行设置
self.anchor_base_sizes = list(anchor_strides) if anchor_base_sizes is None else anchor_base_sizes
#根据上述参数生成所有的基础anchor【此时没考虑特征图的坐标】
self.anchor_generators = []
for anchor_base in self.anchor_base_sizes:self.anchor_generators.append(AnchorGenerator(anchor_base, anchor_scales, anchor_ratios))
#每个像素点的anchor的数量,网络输出的维度根据该参数计算得到
self.num_anchors = len(self.anchor_ratios) * len(self.anchor_scales)def _init_layers(self):self.conv_cls = nn.Conv2d(self.in_channels,self.num_anchors * self.cls_out_channels, 1)self.conv_reg = nn.Conv2d(self.in_channels, self.num_anchors * 4, 1)

参数设置举例

anchor_scales=[1, 2, 4, 8, 16, 32, 64],
anchor_ratios=[0.33, 0.5, 1.0, 2.0, 3.0],
anchor_strides=[16, ],

anchor_strides严格等于下采样倍数即可
anchor大小的设置通过anchor_scales进行设置
一些极端大小的目标检测效果不佳不一定是anchor设置的原因,可能是没有输出对应特征图的原因

AnchorGenerator

  • 根据尺寸、比例生成基础的anchor
class AnchorGenerator(object):
#生成基础的anchor,与特征图无关def __init__(self, base_size, scales, ratios, scale_major=True, ctr=None):self.base_size = base_size #anchor 基础尺寸self.scales = torch.Tensor(scales)  #anchor的尺寸self.ratios = torch.Tensor(ratios)  #anchor的宽高比self.scale_major = scale_majorself.ctr = ctr #anchor中心点坐标self.base_anchors = self.gen_base_anchors() #生成的基础anchor【total_num,4】@propertydef num_base_anchors(self):return self.base_anchors.size(0)def gen_base_anchors(self):w = self.base_size  #anchor 基础宽【16】h = self.base_size  #anchor 基础高【16】if self.ctr is None:x_ctr = 0.5 * (w - 1) #anchor 中心点横坐标y_ctr = 0.5 * (h - 1)  #anchor 中心点纵坐标else:x_ctr, y_ctr = self.ctrh_ratios = torch.sqrt(self.ratios)#求平方根w_ratios = 1 / h_ratios #保证 h_ratios/w_ratios = self.ratiosif self.scale_major:ws = (w * w_ratios[:, None] * self.scales[None, :]).view(-1)hs = (h * h_ratios[:, None] * self.scales[None, :]).view(-1)else:ws = (w * self.scales[:, None] * w_ratios[None, :]).view(-1)hs = (h * self.scales[:, None] * h_ratios[None, :]).view(-1)
# ws: tensor([  27.8524,   55.7048,  111.4097,  222.8194,  445.6388,  891.2776,
#              1782.5552,   22.6274,   45.2548,   90.5097,  181.0193,  362.0387,
#              724.0773, 1448.1547,   16.0000,   32.0000,   64.0000,  128.0000,
#              256.0000,  512.0000, 1024.0000,   11.3137,   22.6274,   45.2548,
#              90.5097,  181.0193,  362.0387,  724.0773,    9.2376,   18.4752,
#              36.9504,   73.9008,  147.8017,  295.6033,  591.2067])base_anchors = torch.stack(  #以(7.5,7.5)为中心点生成的anchor[x_ctr - 0.5 * (ws - 1), y_ctr - 0.5 * (hs - 1),x_ctr + 0.5 * (ws - 1), y_ctr + 0.5 * (hs - 1)],dim=-1).round()# temp = torch.tensor([[-200.0,-600.0,200.0,600.0][-750.0,-600.0,750.0,600.0]]) #可以考虑单独加其它的anchor# base_anchors = torch.cat((base_anchors,temp),0)# yapf: enablereturn base_anchors
base_anchors:[中心点坐标为7.5,7.5]
tensor([[  -6.,    3.,   21.,   12.], [左上x,左上y,右下x,右下y][ -20.,   -1.,   35.,   16.],[ -48.,  -10.,   63.,   25.],[-103.,  -29.,  118.,   44.],[-215.,  -66.,  230.,   81.],.......[ -10.,  -47.,   25.,   62.],[ -29., -103.,   44.,  118.],[ -66., -214.,   81.,  229.],[-140., -435.,  155.,  450.],[-288., -879.,  303.,  894.]])

到这一步为止,生成的anchor与特征图大小、步长无关
中心点坐标为base_size的一半
生成的anchor尺寸与训练分辨率大小对应,并非原图大小

各基础anchor尺寸 = base_size * anchor_ratios * anchor_scales
在以上示例代码中,anchor_ratios = h / w,anchor宽高的计算简单理解如下
hs = h * torch.sqrt(anchor_ratios) * anchor_scales
ws = w * (1 / torch.sqrt(anchor_ratios)) * anchor_scales

b) .生成特征图各位置的anchor,和有效anchor的索引

  • loss计算阶段完成
    def loss(self,cls_scores,bbox_preds,......img_meta):featmap_sizes = [featmap.size()[-2:] for featmap in cls_scores]anchor_list, valid_flag_list = self.get_anchors(featmap_sizes, img_metas, device=device)......
    def get_anchors(self, featmap_sizes, img_metas, device='cuda'):"""Get anchors according to feature map sizes.Args:featmap_sizes (list[tuple]): Multi-level feature map sizes.img_metas (list[dict]): Image meta info.device (torch.device | str): device for returned tensorsReturns:tuple: anchors of each image, valid flags of each image"""num_imgs = len(img_metas)num_levels = len(featmap_sizes)# since feature map sizes of all images are the same, we only compute# anchors for one timemulti_level_anchors = []for i in range(num_levels):#根据基础anchor、特征图大小和步长生成所有anchoranchors = self.anchor_generators[i].grid_anchors(featmap_sizes[i], self.anchor_strides[i], device=device)multi_level_anchors.append(anchors)anchor_list = [multi_level_anchors for _ in range(num_imgs)]
# for each image, we compute valid flags of multi level anchorsvalid_flag_list = []#根据特征图实际大小,生成有效anchor索引【过滤掉一些无效的anchor】for img_id, img_meta in enumerate(img_metas):multi_level_flags = []for i in range(num_levels):#num_levels=1anchor_stride = self.anchor_strides[i]feat_h, feat_w = featmap_sizes[i]h, w, _ = img_meta['pad_shape']#经过resize和pad后的图像大小,非原图尺寸valid_feat_h = min(int(np.ceil(h / anchor_stride)), feat_h)valid_feat_w = min(int(np.ceil(w / anchor_stride)), feat_w)flags = self.anchor_generators[i].valid_flags((feat_h, feat_w), (valid_feat_h, valid_feat_w),device=device)multi_level_flags.append(flags)valid_flag_list.append(multi_level_flags)return anchor_list, valid_flag_list
    def grid_anchors(self, featmap_size, stride=16, device='cuda'):base_anchors = self.base_anchors.to(device)feat_h, feat_w = featmap_size  #特征图尺寸#shift_x: [0,16,32,48,64...976,992,1008]数量等于特征图的宽【feat_w】;最值等于训练分辨率大小【保证每个位置都有anchor】;如果stride和下采样倍数不对应,此处生成的网格点最值与分辨率大小不对应,出现部分区域没有anchor设置或anchor超出图像区域#shift_y: [0,16,32,48,64...592,608,624]数量等于特征图的宽【feat_h】shift_x = torch.arange(0, feat_w, device=device) * stride#以相应步长为单位,生成对应到训练分辨率大小的横坐标shift_y = torch.arange(0, feat_h, device=device) * strideshift_xx, shift_yy = self._meshgrid(shift_x, shift_y) #将横纵坐标重复shifts = torch.stack([shift_xx, shift_yy, shift_xx, shift_yy], dim=-1)
#生成所#有坐标点(w*h,4)[x,y,x,y]【对应到训练分辨率】
#此处的x y即为网络训练分辨率上的像素点坐标,基础anchor坐标【可以理解为偏移量】加上各像素点坐标,得到每个像素点的anchor坐标
#tensor([[   0,    0,    0,    0],
#        [  16,    0,   16,    0],
#        [  32,    0,   32,    0],
#        ...,
#        [1024,  656, 1024,  656],
#        [1040,  656, 1040,  656]], device='cuda:0')shifts = shifts.type_as(base_anchors)all_anchors = base_anchors[None, :, :] + shifts[:, None, :]#生成所有的anchor [1, 35, 4] + [2232, 1, 4] =  [2232,35,4] 广播机制#         基础anchor[偏移量] + 各像素点坐标[x,y,x,y]all_anchors = all_anchors.view(-1, 4)return all_anchors

注意:生成的anchor并不是对应到相应像素点的,而是对应到两个像素点的中心点【因为基础anchor的中心点并不是原点】。如像素点(0,0)对应生成的anchor中心点为(7.5,7.5),往后像素点依此类推。

目标检测 --- Anchor的生成相关推荐

  1. 目标检测Anchor的What/Where/When/Why/How

    编译|yanwan,https://zhuanlan.zhihu.com/p/150332784 来源|https://www.wovenware.com/blog/2020/06/anchor-bo ...

  2. 科普:目标检测Anchor是什么?怎么科学设置?[附代码]

    文章来源于AIZOO,作者元峰 在基于anchor的目标检测网络(Faster RCNN.SSD.YOLO v2&v3等)中,一个至关重要的步骤就是科学的设置anchor,可以说,Anchor ...

  3. 五问目标检测Anchor

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 来自 | 知乎  作者 | yanwan 链接 | https:/ ...

  4. 目标检测_目标检测 | Anchor free的目标检测进阶版本

    今天说的是<Soft Anchor-Point Object Detection>,其也是最近关于anchor free的目标检测的论文,作者来自于CMU,一作同样也是FSAF(2019 ...

  5. 目标检测 | Anchor free之CenterNet深度解析

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 1 前言 本文接着上一讲对CornerNet的网络结构和损失函数的 ...

  6. anchor free 目标检测_《目标检测》系列之二:目标检测中的Anchor机制回顾

    前段时间,YOLOv4&v5大火,很多人忽视了yolov5在anchor上的一些细节变化,因此,本文从Faster RCNN着手,逐步分析SSD.YOLOv4&v5的anchor机制. ...

  7. 高效!Anchor DETR:旷视提出一种基于Transformer的目标检测神器!

    点上方计算机视觉联盟获取更多干货 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:Sophia知乎 https://zhuanlan.zhihu.com/p/412738375 985人工智能 ...

  8. 目标检测:Anchor【就是在图像上预设好的不同大小,不同长宽比的参照框】

    anchor到底是什么呢?如果我们用一句话概括--就是在图像上预设好的不同大小,不同长宽比的参照框.(其实非常类似于上面的滑窗法所设置的窗口大小) 下图来自<动手学深度学习>中的例子,假设 ...

  9. 遥感图像目标检测研究综述

    遥感图像目标检测 遥感图像特殊性 一.目标检测研究综述 1.介绍 2.传统目标检测 3.基于深度学习目标检测 R-CNN系列为代表的两阶段算法 YOLO.SSD为代表的一阶段算法 二.多尺度目标检测研 ...

最新文章

  1. 《ASP.NET MVC4 WEB编程》学习笔记------Web API 续
  2. python心得体会300字_有没有简单一点的 Python 小例子或小项目?
  3. 软件项目管理0824:招标前客户需要准备的资料
  4. 将C4C Service Request中的summary和其他附件同步到ERP的Billing Request去
  5. socket网络编程——多进程、多线程处理并发
  6. PL/SQL: Stop Making the Same Performance Mistakes
  7. 电话号码的字母组合Python解法
  8. Execution in the Kingdom of Nouns (名词王国中的死刑)
  9. 记号(notation)的学习
  10. [剑指Offer] 36.两个链表的第一个公共结点
  11. android 改变音乐格式,音乐速度变更器app-音乐速度变更器下载v9.4.4-hu安卓版-西西软件下载...
  12. ubuntu修改dns服务器,配置Ubuntu DNS服务器
  13. 设置QQ空间评论回复权限,包括日志、相册、说说、留言板的评论回复和留言权限,限制名单成员无评论回复权限
  14. weak_auth 小宁写了一个登陆验证页面,随手就设了一个密码。
  15. 360系统急救箱用在服务器上,360系统急救箱打开失败的处理操作
  16. 进程间通信(IPC (Inter-process communication))
  17. 阜和SAP FICO模块课程
  18. matlab水下机器人,水下机器人路径控制与仿真
  19. 超赞!每个设计师都应该了解的IOS编年史
  20. Python搭建开发环境

热门文章

  1. 数据库的连接 SQL Joins
  2. sql joins图示
  3. JS获取跨域的cookie实例
  4. JS跨域设置和取Cookie(二)
  5. Mysql创建用户与赋权限操作
  6. HTML中如何给代码添加注释
  7. matlab中字符串和变量一起显示输出eval()函数用法
  8. 入库订单(组合关系、主从表)模型
  9. JS 函数的递归算法
  10. 连连支付怎么样?最新连连跨境支付详情介绍!