5 -【Faster R-CNN】之 AnchorGenerator 代码精读

news2024/12/25 13:11:16

【Faster R-CNN】之 AnchorGenerator 代码精读

  • 1、anchor 的 size 和 aspect_ratios
  • 2、计算以中心坐标为 (0, 0) 的 anchor
  • 3、将 anchor 映射到原图上
  • 4、代码汇总

anchor 的作用:anchor 是用来做辅助计算的,用于和 (上节课说的,由RPN Head 计算出的)bounding box regression 一起,计算出 预测的 候选框的坐标信息。
** 我理解 bounding box regression 是一个 相对位置信息,且是一个系数。

1、anchor 的 size 和 aspect_ratios

  • anchor size :表示 anchor 的大小,一般取值为 anchor_sizes = (32, 64, 128, 256, 512)
  • anchor aspect_ratios :表示 anchor 的高宽比,一般取值为 (0.5, 1.0, 2.0),作者表示这个是经验值。

每个size 对应三个高宽比,会创建 3个 anchor。

比如,size=32, aspect_ratios= (0.5, 1.0, 2.0) 时, 会创建如下 3个 anchor :

  • 当高宽比为 1:1 时, size=32 为 anchor 的边长,即,height = width = 32
  • 当高宽比为 0.5 时,height / width = 0.5,anchor 面积为 3 2 2 32^2 322
  • 当高宽比为 2 时,height / width = 2,,anchor 面积为 3 2 2 32^2 322

在这里插入图片描述

因为有 (32, 64, 128, 256, 512) 这 5个size,每个 size 分别会生成 3个不同 aspect_ratios 的anchor,所以,一共会生成 15个 不同尺寸的 anchor。

2、计算以中心坐标为 (0, 0) 的 anchor

我们仍然 以 size=32, aspect_ratios= (0.5, 1.0, 2.0) 举例:

  • 当 aspect_ratios=0.5 时,假设 高为 x x x, 宽为 2 x 2x 2x,
    anchor 面积为: x ∗ 2 x = 3 2 2 x * 2x =32^2 x2x=322 , 解方程 得 x = 32 2 x = \frac{32}{\sqrt{2}} x=2 32
    所以, a n c h o r _ h e i g h t = x = 32 2 anchor\_height = x = \frac{32}{\sqrt{2}} anchor_height=x=2 32 a n c h o r _ w i d t h = 2 x = 32 2 anchor\_width = 2x = 32 \sqrt{2} anchor_width=2x=322

  • 当 aspect_ratios= 1时, a n c h o r _ h e i g h t = 32 anchor\_height = 32 anchor_height=32 a n c h o r _ w i d t h = 32 anchor\_width = 32 anchor_width=32

  • 当 aspect_ratios=2 时, a n c h o r _ w i d t h = x = 32 2 anchor\_width = x = \frac{32}{\sqrt{2}} anchor_width=x=2 32 a n c h o r _ h e i g h t = 2 x = 32 2 anchor\_height = 2x = 32 \sqrt{2} anchor_height=2x=322

为了计算方便,我们设计一个 h_ratios 和 w_ratios : h _ r a t i o s = [ 1 2 , 1 , 2 ] , w _ r a t i o s = [ 2 , 1 , 1 2 ] h\_ratios = [\frac{1}{\sqrt{2}}, 1, \sqrt{2}], \quad w\_ratios = [\sqrt{2}, 1, \frac{1}{\sqrt{2}}] h_ratios=[2 1,1,2 ],w_ratios=[2 ,1,2 1]

使得:
a n c h o r _ w i d t h = w _ r a t i o s ∗ s c a l e s = ( 2 , 1 , 1 2 ) ∗ 32 = [ 45.2548 , 32.0000 , 22.6274 ] anchor\_width = w\_ratios * scales = (\sqrt{2}, 1, \frac{1}{\sqrt{2}}) * 32 = [45.2548, 32.0000, 22.6274] anchor_width=w_ratiosscales=(2 ,1,2 1)32=[45.2548,32.0000,22.6274]
a n c h o r _ h e i g t h = h _ r a t i o s ∗ s c a l e s = ( 1 2 , 1 , 2 ) ∗ 32 = [ 22.6274 , 32.0000 , 45.2548 ] anchor\_heigth = h\_ratios * scales = (\frac{1}{\sqrt{2}}, 1, \sqrt{2}) * 32 = [22.6274, 32.0000, 45.2548] anchor_heigth=h_ratiosscales=(2 1,1,2 )32=[22.6274,32.0000,45.2548]

最后,我们将 anchor 中心位置的坐标作为 [0, 0],分别计算 3个 anchor 左上角的坐标和右下角的坐标:

  • size=32, aspect_ratios= 0.5 的 anchor:
    ( xmin, xmax, ymin, ymax)= (-ws, -hs, ws, hs) / 2 = [-22.6274, -11.3137, 22.6274, 11.3137]
  • size=32, aspect_ratios= 1 的 anchor:
    ( xmin, xmax, ymin, ymax)= (-ws, -hs, ws, hs) / 2 = [-16.0000, -16.0000, 16.0000, 16.0000]
  • size=32, aspect_ratios= 2 的 anchor:
    ( xmin, xmax, ymin, ymax)= (-ws, -hs, ws, hs) / 2 = [-11.3137, -22.6274, 11.3137, 22.6274]

最后,将坐标进行四舍五入, 得:
size=32, aspect_ratios= 0.5 的 anchor :( xmin, xmax, ymin, ymax)= [-23., -11., 23., 11.]
size=32, aspect_ratios= 0.5 的 anchor :( xmin, xmax, ymin, ymax)= [-16., -16., 16., 16.]
size=32, aspect_ratios= 0.5 的 anchor :( xmin, xmax, ymin, ymax)= [-11., -23., 11., 23.]

代码如下;

def generate_anchors(self, scales, aspect_ratios, dtype, device):
    scales = torch.as_tensor(scales, dtype=dtype, device=device)
    aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)
    h_ratios = torch.sqrt(aspect_ratios)
    w_ratios = 1.0 / h_ratios

    ws = (w_ratios[:, None] * scales[None, :]).view(-1)
    hs = (h_ratios[:, None] * scales[None, :]).view(-1)

    base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2
    return base_anchors.round()  # round 四舍五入

同理,我们可以求出 size 分别为 64、128、256、512 的 12个 anchor 的坐标信息。

一共15个 anchor 如下:
[ -23., -11., 23., 11.],
[ -16., -16., 16., 16.],
[ -11., -23., 11., 23.],
[ -45., -23., 45., 23.],
[ -32., -32., 32., 32.],
[ -23., -45., 23., 45.],
[ -91., -45., 91., 45.],
[ -64., -64., 64., 64.],
[ -45., -91., 45., 91.],
[-181., -91., 181., 91.],
[-128., -128., 128., 128.],
[ -91., -181., 91., 181.],
[-362., -181., 362., 181.],
[-256., -256., 256., 256.],
[-181., -362., 181., 362.]])


到现在为止,我们得到的 anchor 都是自己在跟自己玩,下面我们要把它映射到 原图上去

3、将 anchor 映射到原图上

我们的做法可以理解为:

  • 特征图上的每一个像素都会有这15个不同尺寸的 anchor, 比如 特征图尺寸为(3, 4), 每一个像素都会有这15个anchor,所以一共有 3 ∗ 4 ∗ 15 = 180 3 * 4 * 15=180 3415=180 个anchor
  • 将特征图上的每一个像素按照比例(高度缩放比例,和宽度缩放比例)映到原图上去,然后将anchor也映射过去。
    • 这里的原图指的是resize_and_padding 之后的,batch中的图片尺寸。后面我们都会称之为原图
    • 高度缩放比例和宽度缩放比例,是由backbone 决定的,RPN Head 并没有改变 图片的尺寸
  • 最后,我们得到 achor 在原图上的 坐标信息,形为 (xmin, ymin, xmax, ymax)

接下来,我们举例计算细节:
假设 原图的尺寸为 (10, 12), 特征图的尺寸为 (3, 4)
缩放尺寸为 (这里称为步幅) : stride=(10//3, 12//4)=(3, 3)

特征图上的 高和宽的坐标,按照步幅映射到原图,如下
x轴坐标 ( 0 , 1 , 2 ) × 3 = ( 0 , 3 , 6 ) ( 0, 1, 2) \times 3 = (0, 3, 6) (0,1,2)×3=(0,3,6)
y轴坐标 ( 0 , 1 , 2 , 3 ) × 3 = ( 0 , 3 , 6 , 9 ) ( 0, 1, 2, 3)\times 3 = (0, 3, 6, 9) (0,1,23)×3=(0,3,6,9)
在这里插入图片描述

然后通过 torch.meshgrid() 函数,将 每个元素的 x,y 坐标都复制出来,然后展平
在这里插入图片描述

通过函数 torch.stack([shift_x, shift_y, shift_x, shift_y], dim=1) 将他们叠起来,作为 anchor 在原图中的绝对坐标的中心

在这里插入图片描述

再把之前计算出的 以(0, 0)为中心的相对坐标加上,就会得到 anchor 在原图上的绝对坐标啦!
也就是上面的每一列 都加上 我们之前计算得到的 15个anchor相对坐标,一共会得到 12 *15 = 180个anchor

        [ -23.,  -11.,   23.,   11.]
        [ -16.,  -16.,   16.,   16.]
        [ -11.,  -23.,   11.,   23.]
        [ -45.,  -23.,   45.,   23.]
        [ -32.,  -32.,   32.,   32.]
        [ -23.,  -45.,   23.,   45.]
        [ -91.,  -45.,   91.,   45.]
        [ -64.,  -64.,   64.,   64.]
        [ -45.,  -91.,   45.,   91.]
        [-181.,  -91.,  181.,   91.]
        [-128., -128.,  128.,  128.]
        [ -91., -181.,   91.,  181.]
        [-362., -181.,  362.,  181.]
        [-256., -256.,  256.,  256.]
        [-181., -362.,  181.,  362.]

这一部分的代码

def grid_anchors(self, feature_map_size, strides):
    cell_anchors = self.cell_anchors

    grid_height, grid_width = feature_map_size
    stride_height, stride_width = strides
    device = cell_anchors[0].device

    shifts_x = torch.arange(0, grid_width, dtype=torch.float32, device=device) * stride_width
    shifts_y = torch.arange(0, grid_height, dtype=torch.float32, device=device) * stride_height

    shift_y, shift_x = torch.meshgrid([shifts_y, shifts_x], indexing='ij')
    shift_x = shift_x.reshape(-1)
    shift_y = shift_y.reshape(-1)

    shifts = torch.stack([shift_x, shift_y, shift_x, shift_y], dim=1)
    shifts_anchor = shifts.view(-1, 1, 4) + cell_anchors[0].view(1, -1, 4)
    return shifts_anchor.reshape(-1, 4)  # List[Tensor(all_num_anchors, 4)]

4、代码汇总

class AnchorsGenerator(torch.nn.Module):
    def __init__(self, sizes, aspect_ratios):
        # anchor_sizes = ((32,), (64,), (128,), (256,), (512,))
        # aspect_ratios = ((0.5, 1.0, 2.0),) * len(anchor_sizes)

        super(AnchorsGenerator, self).__init__()
        self.sizes = sizes
        self.aspect_ratios = aspect_ratios
        self.cell_anchors = None
        self._cache = {}

    def forward(self, image_list, feature_maps):
        feature_map_size = feature_maps.shape[-2:]
        image_size = image_list.tensors.shape[-2:]
        dtype, device = feature_maps.dtype, feature_maps.device

        strides = [torch.tensor(image_size[0] // feature_map_size[0], dtype=torch.int64, device=device),
                   torch.tensor(image_size[1] // feature_map_size[1], dtype=torch.int64, device=device)]

        cell_anchors = [
            self.generate_anchors(sizes, aspect_ratios, dtype, device)
            for sizes, aspect_ratios in zip(self.sizes, self.aspect_ratios)
        ]
        self.cell_anchors = [torch.concat(cell_anchors, dim=0)]

        anchors_over_all_feature_maps = self.grid_anchors(feature_map_size, strides)
        anchors = [anchors_over_all_feature_maps for i in range(feature_maps.shape[0])]
        return anchors

    def generate_anchors(self, scales, aspect_ratios, dtype, device):
        # # type: (List[int], List[float], torch.dtype, torch.device) -> Tensor
        scales = torch.as_tensor(scales, dtype=dtype, device=device)
        aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)
        h_ratios = torch.sqrt(aspect_ratios)
        w_ratios = 1.0 / h_ratios

        ws = (w_ratios[:, None] * scales[None, :]).view(-1)
        hs = (h_ratios[:, None] * scales[None, :]).view(-1)

        base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2
        return base_anchors.round()  # round 四舍五入

    def grid_anchors(self, feature_map_size, strides):
        # # type: (torch.Size([int, int]), List[Tensor, Tensor]) -> List[Tensor]
        cell_anchors = self.cell_anchors

        grid_height, grid_width = feature_map_size
        stride_height, stride_width = strides
        device = cell_anchors[0].device

        shifts_x = torch.arange(0, grid_width, dtype=torch.float32, device=device) * stride_width
        shifts_y = torch.arange(0, grid_height, dtype=torch.float32, device=device) * stride_height

        shift_y, shift_x = torch.meshgrid([shifts_y, shifts_x], indexing='ij')
        shift_x = shift_x.reshape(-1)
        shift_y = shift_y.reshape(-1)

        shifts = torch.stack([shift_x, shift_y, shift_x, shift_y], dim=1)
        shifts_anchor = shifts.view(-1, 1, 4) + cell_anchors[0].view(1, -1, 4)
        return shifts_anchor.reshape(-1, 4)  # List[Tensor(all_num_anchors, 4)]

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

共享模型之内存(一)

1.Java内存模型 1>.JMM即Java Memory Model,它定义了主存、工作内存抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等; 2>.JMM体现在以下几个方面: ①.原子性 - 保证指令不会受到线程上下文切换的影响; ②.可见性 - 保证指令不会受cpu缓存的影响; ③.有序…

大型会场活动线上保障方案

背景 为保证活动上线后的质量,大型会场活动上线前通常会预设一些线上可能出现的问题,提前制定保障方案。 这些与活动保障相关的问题可能与App端上的容器环境有关,也可能与大盘用户设备特征有关,问题的处理方案会影响活动的线上效…

《啊哈算法图的遍历》(14张图解)

目录 前言 一,dfs和bfs是什么 二,城市地图--图的深度优先遍历 三,最少转机--图的广度优先遍历 前言 🌼说爱你(超甜女声版) - 逗仔 - 单曲 - 网易云音乐 1月22日一个女孩加了我,她和我聊音…

adb常用指令合集

adb文件管理指令 1.复制设备里的文件到电脑 adb pull <设备里的文件路径> [电脑上的目录] 电脑上的目录 参数可以省略&#xff0c;默认复制到当前目录 例&#xff1a;adb pull /data/tsplogtool /home/jxq/文档/场景魔方 2.复制电脑里的文件到设备 adb push <电脑上的…

浅谈未来10年IT行业的变局与抉择,一文带你认识元宇宙

一. 困局据国家就业部门最新统计数据报告&#xff0c;2022年应届毕业生的数量首次突破1000万大关。其中研究生达到130万&#xff0c;985、211等名校毕业生75万&#xff0c;普通本科毕业生470万&#xff0c;专科生460万&#xff0c;另外还有几十万的归国留学生&#xff01;但这还…

《从0开始学大数据》之Spark性能优化案例

基于软件性能优化原则和 Spark 的特点&#xff0c;Spark 性能优化可以分解为下面几步。 性能测试&#xff0c;观察 Spark 性能特性和资源&#xff08;CPU、Memory、Disk、Net&#xff09;利用情况。分析、寻找资源瓶颈。分析系统架构、代码&#xff0c;发现资源利用关键所在&a…

【前端】Vue项目:旅游App-(17)home:页面滚动显示搜索栏、节流、时间同步

文章目录目标过程与代码页面滚动到目标位置显示搜索框优化&#xff1a;节流搜索栏显示时间同步效果总代码修改或添加的文件search-bar.vueuseScroll.jsstore的main.jsformatDate.jshome.vue参考本项目博客总结&#xff1a;【前端】Vue项目&#xff1a;旅游App-博客总结 目标 …

HDFS文件浏览器功能OOM排查

现象描述 涉及HDFS文件浏览器的某个功能运行一段时间后会出现OOM的情况 错误日志如下&#xff1a; service.log.2023-02-01-0.log:java.lang.OutOfMemoryError: Java heap space排查过程 需要查看dump文件排查一下造成OOM的原因 查看jvm参数如下&#xff1a; java -Duser.t…

一文讲明Docker的基本使用,常见Docker命令使用 、Docker的安装使用等【详细说明+图解+概念+实践】

一个混迹于Github、Stack Overflow、开源中国、CSDN、博客园、稀土掘金、51CTO等 的野生程序员。 目标&#xff1a;分享更多的知识&#xff0c;充实自己&#xff0c;帮助他人 GitHub公共仓库&#xff1a;https://github.com/zhengyuzh 以github为主&#xff1a; 1、分享前端后端…

【Python合集系列】2023兔年吉祥,新的一年希望放烟花的人跟看烟花的人都能平平安安哦~(附多种源码)

前言 希望放烟花的人跟看烟花的人都能平平安安。 &#x1f440; NICE TO MEET YOU :)&#x1f319; 所有文章完整的素材源码都在&#x1f447;&#x1f447; 粉丝白嫖源码福利&#xff0c;请移步至CSDN社区或文末公众hao即可免费。 ​哈喽&#xff01;我是木子&#xff0c;新…

设计模式之适配器模式,以C++为例。

今天来盘一盘适配器模式。适配器&#xff1a;顾名思义&#xff0c;就是让原本不合适的变为合适的&#xff0c;好似一对男女&#xff0c;没有中间的媒婆是不会互相了解的&#xff0c;好像不太恰当&#xff0c;就这么解释吧&#xff0c;只有有了这个中间人他们才会产生联系&#…

智能驾驶开启高精定位新赛道,这家供应商正加码布局海外市场

高工智能汽车研究院监测数据显示&#xff0c;2022年1-11月中国市场乘用车前装标配搭载NOA交付达到18.38万辆&#xff0c;同比增长91.86%&#xff1b;同时&#xff0c;NOA搭载的车型配置价格还在不断下滑&#xff0c;正在把NOA的配置拉至15万元价格区间。 而作为高精定位&#x…

面向对象——static(静态)Math类自定义工具类代码块

目录 static&#xff08;静态&#xff09;关键字 static的注意事项 static的优点和缺点 应用场景 自定义工具类 代码块 static&#xff08;静态&#xff09;关键字 static是一个修饰符&#xff0c;用于修饰成员&#xff08;成员变量 、成员方法&#xff09;static的特点…

Redis处理client连接数过多,大量空闲链接无法释放问题

打开redis命令终端&#xff0c;输入&#xff1a; client list 查看连接数&#xff0c;用于返回所有连接到服务器的客户端信息和统计数据 参数解析&#xff1a; id: 唯一的64位的客户端ID(Redis 2.8.12加入)。 addr: 客户端的地址和端口 fd: 套接字所使用的文件描述符 age…

python真的很骚可惜你不会

python基本语法 &#x1f4d2;博客主页&#xff1a; 微笑的段嘉许博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐留言&#x1f4dd; &#x1f4cc;本文由微笑的段嘉许原创&#xff01; &#x1f4c6;51CTO首发时间&#xff1a;&#x1f334;2023年1月日3…

redis分布式缓存

文章目录一、redis持久化1.1.RDB持久化1.1.1.执行时机1.1.2.RDB原理1.1.3.小结1.2.AOF持久化1.2.1.AOF原理1.2.2.AOF配置1.2.3.AOF文件重写1.2.4.小结1.3.RDB与AOF对比二、Redis主从集群2.1.集群结构2.2.准备实例和配置2.3.启动2.4.开启主从关系2.5.测试2.6.主从数据同步原理2.…

Codeforces Round #848 (Div. 2) A-E 赛时思路+正解

青大蒟蒻第一次在正式的div2div2div2中AcAcAc了五道题&#xff0c;也是小蒟蒻有史以来发挥最好的一场&#xff0c;这场过后我的cf也许可能也要变成黄了。 A. Flip Flop Sum 题意&#xff1a;给定一个a——ia——ia——i数组&#xff0c;权值仅为1或-1&#xff0c;我们选择相邻…

《死亡空间》重制回归!无法启动怎么办?

作为科幻生存恐怖系列的经典之作&#xff0c;《死亡空间》在推出15年后再次回归&#xff0c;果然引发热潮。精美震撼的科幻场景&#xff0c;强烈的视觉画面&#xff0c;加上阴森的3D 音效&#xff0c;重制版提升了身临其境之感&#xff0c;完全是沉浸式恐怖体验&#xff0c;只能…

红外遥控数码管显示

红外遥控器实物图红外遥控器接口电路数码管接口电路红外遥控数码管显示程序源代码/**************************红外遥控数码管显示************************** * 单片机&#xff1a;51单片机* 开发环境&#xff1a;keil * 名称:红外遥控数码管显示 * 功能&#xff1a;遥控器红外…

C语言常量

常量是固定值&#xff0c;在程序执行期间不会改变。这些固定的值&#xff0c;又叫做字面量。常量可以是任何的基本数据类型&#xff0c;比如整数常量、浮点常量、字符常量&#xff0c;或字符串字面值&#xff0c;也有枚举常量。常量就像是常规的变量&#xff0c;只不过常量的值…