detectron中图片产生anchor的函数是get_field_of_anchors,它位于data_utils.py,要生成anchor需要下列参数,因此该函数主要输入就是以下几个参数,不做过多的解释了。

  • stride:
  • anchor_sizes
  • anchor_aspect_ratios

该函数生成生成anchor的过程如下:

1.首先对一个cell生程anchor,此时这个anchor没有位置点信息,只有长宽而已,这个长宽满足我们设计的anchor_sizes和anchor_aspect_ratios,generate_anchors代码放在最后面。

    # Anchors at a single feature cell,在一个cell产生的anchorcell_anchors = generate_anchors(stride=stride, sizes=anchor_sizes, aspect_ratios=anchor_aspect_ratios)num_cell_anchors = cell_anchors.shape[0] #anchor的数量

2.之后根据我们输入图片的长宽,以及stride,计算在这样一张图片上以stride为步长要在哪些位置生成anchor,此时才有了放置这些anchor的点.

detectron是在fpn_max_size为基准构成的正方形上生成放置anchor的点的,怎么理解呢,这里举出两个例子,假设我输如的图片大小为1024×1024。

(1)这里设置训练需要的样本最大边长为1024,即cfg.TRAIN.MAX_SIZE = 1024。由于我们原本的图片就是1024,所以就不用缩放了。retinanet默认cfg.FPN.COARSEST_STRIDE = 128。所以fpn_max_size = 128×ceil(1024/128 ) = 1024。之后以stride为步长,在fpn_max_size×fpn_max_size大小的图上生成放置anchor的点,那么单个边放置的个数就是field_size = ceil(1024/8) = 128。所以生成的anchor的位置点个数为128×128个。

(2)这里设置训练需要的样本最大边长为800,即cfg.TRAIN.MAX_SIZE = 800。此时要对我们的样本最长边缩放至800,retinanet默认cfg.FPN.COARSEST_STRIDE = 128。所以fpn_max_size = 128×ceil(800/128 ) = 896。之后以stride为步长,在fpn_max_size×fpn_max_size大小的图上生成放置anchor的点,那么单个边放置的个数就是field_size = ceil(896/8) = 112。所以生成的anchor的位置点个数为112×112个。

最后放置anchor的点坐标为shifts.它的第一列和第三列相同,第二列和第四列相同。

ps:其实对cfg.FPN.COARSEST_STRIDE这个参数理解还不是非常透彻,希望能与大家交流

    fpn_max_size = cfg.FPN.COARSEST_STRIDE * np.ceil(cfg.TRAIN.MAX_SIZE / float(cfg.FPN.COARSEST_STRIDE))field_size = int(np.ceil(fpn_max_size / float(stride)))#以strid为步长,每隔一个stride,生成一个anchor,field_size表示最大的那个边长能生成多少个anchorshifts = np.arange(0, field_size) * strideshift_x, shift_y = np.meshgrid(shifts, shifts)shift_x = shift_x.ravel()shift_y = shift_y.ravel()shifts = np.vstack((shift_x, shift_y, shift_x, shift_y)).transpose()

3.有了这些放置点的位置,将a步骤的anchor挪过去,就相当于在该位置生成了一个anchor。

# Broacast anchors over shifts to enumerate all anchors at all positions# in the (H, W) grid:#   - add A cell anchors of shape (1, A, 4) to#   - K shifts of shape (K, 1, 4) to get#   - all shifted anchors of shape (K, A, 4)#   - reshape to (K*A, 4) shifted anchorsA = num_cell_anchorsK = shifts.shape[0]field_of_anchors = (cell_anchors.reshape((1, A, 4)) +shifts.reshape((1, K, 4)).transpose((1, 0, 2)))  field_of_anchors = field_of_anchors.reshape((K * A, 4))  #field_of_anchors的行数相当于anchor的数量

附录:generate_anchors代码:

def generate_anchors(stride=16, sizes=(32, 64, 128, 256, 512), aspect_ratios=(0.5, 1, 2)
):"""Generates a matrix of anchor boxes in (x1, y1, x2, y2) format. Anchorsare centered on stride / 2, have (approximate) sqrt areas of the specifiedsizes, and aspect ratios as given.#这里的stride可以理解为元anchor的边长(base_size)产生anchor的原理是:(1)先对元anchor生成不同aspect_ratios下的base_anchors(2)再根据该层实际设计的anchor的sizes,将base_anchors进行扩大,扩大的倍数就是下面的:np.array(sizes, dtype=np.float) / stride"""return _generate_anchors(stride,np.array(sizes, dtype=np.float) / stride,np.array(aspect_ratios, dtype=np.float))def _generate_anchors(base_size, scales, aspect_ratios):"""Generate anchor (reference) windows by enumerating aspect ratios Xscales wrt a reference (0, 0, base_size - 1, base_size - 1) window."""anchor = np.array([1, 1, base_size, base_size], dtype=np.float) - 1 #这个就是元anchoranchors = _ratio_enum(anchor, aspect_ratios)    #根据aspect_ratios,对元anchor生成不同ratio下的base_anchors#根据该层实际设计的anchor的边长size,以及size与stride的关系(size/stride =scales),将base_anchors的边长乘以scalesanchors = np.vstack([_scale_enum(anchors[i, :], scales) for i in range(anchors.shape[0])]   )return anchorsdef _whctrs(anchor):"""Return width, height, x center, and y center for an anchor (window)."""w = anchor[2] - anchor[0] + 1h = anchor[3] - anchor[1] + 1x_ctr = anchor[0] + 0.5 * (w - 1)y_ctr = anchor[1] + 0.5 * (h - 1)return w, h, x_ctr, y_ctrdef _mkanchors(ws, hs, x_ctr, y_ctr):"""Given a vector of widths (ws) and heights (hs) around a center(x_ctr, y_ctr), output a set of anchors (windows)."""ws = ws[:, np.newaxis] #由(3,)变为(3,1)hs = hs[:, np.newaxis]anchors = np.hstack(  #hstack横向拼接,保证行不变,列合并,所以是anchors的大小是(3,4)(x_ctr - 0.5 * (ws - 1), #anchor左上角的x,大小为(3,1)y_ctr - 0.5 * (hs - 1), #anchor左上角的y,大小为(3,1)x_ctr + 0.5 * (ws - 1), #anchor右上角的x,大小为(3,1)y_ctr + 0.5 * (hs - 1)  #anchor右上角的y,大小为(3,1)))return anchorsdef _ratio_enum(anchor, ratios):"""Enumerate a set of anchors for each aspect ratio wrt an anchor."""w, h, x_ctr, y_ctr = _whctrs(anchor)#返回高宽以及中心size = w * h  #面积#下面这三个是计算在面积相同情况固定长宽比下的长hs与宽wssize_ratios = size / ratiosws = np.round(np.sqrt(size_ratios))hs = np.round(ws * ratios)anchors = _mkanchors(ws, hs, x_ctr, y_ctr) #根据求取的长宽和中心seanchorreturn anchorsdef _scale_enum(anchor, scales):"""Enumerate a set of anchors for each scale wrt an anchor."""w, h, x_ctr, y_ctr = _whctrs(anchor) ws = w * scaleshs = h * scalesanchors = _mkanchors(ws, hs, x_ctr, y_ctr)return anchors

每次再看生成anchor的过程总是健忘的一点是:到底anchor生成的(绝对)大小是基于对应的FPN的大小,还是基于原图的大小
显然在计算IOU的时候anchor是与对应的GT进行计算,因此一定是基于原图的大小,要与与GT处于同一个尺度(比例)下。
搞混的原因是在不同的FPN层产生不同的大小的anchor,导致总以为anchor是在对应的FPN特征图上产生的。

其实在生产anchor中最重要的参数就是stride,不同的层在产生anchor的过程中stride是不一样的。这个stride实际上就是特征图相对于原图的下采样的倍数。
假设输入是512*512,经过经过层层卷积后得到C2层(经过横向链接对应于P2层),大小为64*64,也就是下采样了8倍。按照FPN的定义,这一层用来产生小anchor,对于64*64大小的特征图上每一点产生3种比例的面积为32*32的anchor(这个32是anchor大小,可以自定义,与GT同处于一个比例下)。截止到目前我们产生的anchor的位置都是基于当前特征图的,因此还需要转变为基于原图的。这时就用到了stride,通过stride可以将当前特征图上每一个点都映射回原图。可想而知,映射回原图后就是在原图每8个点处产生anchor。
同理对于C3层(经过横向链接对应于P3层),特征图大小为32*32,下采样了16倍,即stride = 16。在这一层产生大小为64*64的anchor,对应与原图就是每16个点处产生anchor。
依次类推。

基于上面的讲解,如果想要提升小目标的检测效果,通过简单调整FPN的方案有:
1. 设置更小的anchor_size
2. 利用分辨率更高的特征图。在上面的讲解中我们利用下采样8倍的特征图作为FPN中分辨率最高的特征图,在这种情况下对应于原图是每8个点产生anchor,anchor产生的还是不够密集,可能错过小目标。那么我们可以将下采样4倍的特征图作为FPN中分辨率最高的特征图,即大小为128*128,对应与原图是每4个点处产生anchor,小anchor的数量就明显多了,但是计算量也会随之上升。

【detectron】对输入样本如何产生anchor相关推荐

  1. Relu神经网络输出预测全为0或1,对所有输入样本的预测概率也相同

    现有一个使用Relu激活函数的网络,训练过程中发现,它对所有的输入样本都输出一样的预测概率,比如二分类,对所有样本的预测概率都是[0.4,0.6].由于预测概率都一样,因此预测标签也都一样,全预测为0 ...

  2. 【CV】PAA论文解读:在物体检测中利用概率分布来将anchor分配为正负样本

    本文转自|AI公园 导读 又一篇anchor匹配策略的文章,不过确实是简单有效,在ATSS上只需要很小的修改就可以提升性能.GFL2在框的预测上用上了概率分布,这里又在anchor匹配上用上了概率分布 ...

  3. 综述:解决目标检测中的样本不均衡问题

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者丨SFXiang 来源丨AI算法修炼营 编辑丨极市平台 极市导 ...

  4. 再谈对比学习:更好的对比样本选择,更好的对比效果

    ©PaperWeekly 原创 · 作者 | 张琨 学校 | 中国科学技术大学博士生 研究方向 | 自然语言处理 在之前的介绍中,我们对自监督学习(SSL)中的对比学习(CL)进行了简单介绍,然后针对 ...

  5. anchor free:CornerNet解读【目标检测】

    CornerNet: Detecting Objects as Paired Keypoints (anchor free)解读 CSDN地址:https://blog.csdn.net/hancod ...

  6. 目标检测中如何定义正负样本,和正负样本在学习过程中loss计算起的作用

    如何定义正负样本,和正负样本在学习过程中loss计算起的作用 正负样本定义 分类和回归head如何学习和利用划分后的正负样本(loss如何计算) 正负样本在分类中loss计算的处理 正样本在bbox ...

  7. 清华朱军团队包揽三项冠军 | NIPS 2017对抗样本攻防竞赛总结(附学习资料)

    来源:AI科技评论 作者:高云河 本文共8989字,建议阅读10分钟. 本次比赛总结由谷歌大脑.清华大学以及其它参与研究人员们联合撰写,为你介绍NIPS 2017 对抗样本攻防比赛的情况. 自 Ian ...

  8. EMNLP'21 | 基于相似样本检索的在线更新机器翻译系统

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 来自:AI科技评论 机器翻译指的是使用机器将一种语言的文本翻译成另一种语言的文本.机器 ...

  9. r语言 svm 大样本_r语言基于SVM模型的文本分类研究 附数据代码

    1 Perceptron 与 SVM 概念介绍 1.1 感知机 (Perceptron) 感知机( perceptron ) 1957 年由 Rosenblatt 提出,是神经网络与支持向 量机的基础 ...

最新文章

  1. 浅析COM的思想及原理
  2. 2048游戏C语言代码
  3. 使用Adaptive cards来构建Teams app的界面
  4. oracle中数据导入导出问题
  5. 【MySQL】MySQL 8 连接出现 2059 - Authentication plugin caching_sha2_password ca
  6. 河北金融学院计算机与科学,河北金融学院计算机科学与技术专业2016年在河北理科高考录取最低分数线...
  7. AcWing 788. 逆序对的数量
  8. win10 uwp 重启软件
  9. QQ音乐付费格式转换
  10. mmc驱动中的mmc_host结构体中rescan_disable变量的作用及使用
  11. 深刻剖析快速排序为什么不稳定?
  12. “新元宇宙”奇科幻小说原创作品系列连载《地球人奇游天球记》第三回零点惊魂
  13. 边境的悍匪—Kaggle—泰坦尼克号生还预测详细教程
  14. Java —— 日期时间 API
  15. mysql日期自动加1天
  16. 一张图了解大数据平台架构
  17. 遥感影像条带噪声去除
  18. 数据预处理之One-Hot(独热编码)编码
  19. android黑色背景图片,Android png透明图片转jpg时背景变黑的解决方法
  20. 游戏常用算法:冒泡排序

热门文章

  1. 64位驱动 hp630打印机_m351a驱动-HP 惠普 LaserJet Pro 300 Colour M351a 彩色激光打印机驱动下载5.0.12200.630官方版-东坡下载...
  2. 终于搞清楚了:TCP的SYN和ACK是什么意思
  3. 创新点定义,如何写创新点
  4. python怎么将删的代码恢复_找回丢失的Python代码--如果代码还驻留在内存中
  5. rtx2060相当于gtx多少 rtx2060属于什么档次的显卡 rtx2060显卡怎么样
  6. 成功WEB商务的7步走(7)——PDCA
  7. 2017 ACM Arabella Collegiate Programming Contest A. Sherlock Bones GYM101350A
  8. 跳过微信屏蔽APP扫描以及识别不同系统的手机
  9. rec卡刷root吗,卡刷需要root权限吗
  10. CDH和Hadoop的区别