13.4. 锚框 部分

13.4. 锚框 — 动手学深度学习 2.0.0 documentation

tensor([0.00, 0.00, 0.01,  ..., 0.99, 1.00, 1.00]) 

torch.meshgrid()函数看不懂可以看这里

torch.meshgrid()函数解析_小娜美要努力努力的博客-CSDN博客

torch.meshgrid()实现x*y个组合 做成了每个x对应每个y的映射矩阵

w = torch.cat((size_tensor * torch.sqrt(ratio_tensor[0]),
                   sizes[0] * torch.sqrt(ratio_tensor[1:])))\
                   * in_height / in_width  # 处理矩形输入
#tensor([0.53, 0.35, 0.18, 0.75, 0.37])
h = torch.cat((size_tensor / torch.sqrt(ratio_tensor[0]),
                   sizes[0] / torch.sqrt(ratio_tensor[1:])))

因为只验证这些 (s1, r1),(s1, r2), . . . ,(s1, rm),(s2, r1),(s3, r1), . . . ,(sn, r1).

提取的是size_tensor * torch.sqrt(ratio_tensor[0]),   sizes[0] * torch.sqrt(ratio_tensor[1:])

一开始没看懂,看了很久

左边是(s2, r1),(s3, r1), . . . ,(sn, r1).     #ratio_tensor[0]一直没变

 右边是(s1, r1),(s1, r2), . . . ,(s1, rm)

multibox_prior函数部分:

目标检测SSD | Lee的个人博客

锚框 - #31 by HeartSea15 - pytorch - D2L Discussion

#@save
def multibox_prior(data, sizes, ratios):
    """生成以每个像素为中心具有不同形状的锚框"""
    in_height, in_width = data.shape[-2:]
    device, num_sizes, num_ratios = data.device, len(sizes), len(ratios)
    boxes_per_pixel = (num_sizes + num_ratios - 1)
    size_tensor = torch.tensor(sizes, device=device)
    ratio_tensor = torch.tensor(ratios, device=device)

    # 为了将锚点移动到像素的中心,需要设置偏移量。
    # 因为一个像素的高为1且宽为1,我们选择偏移我们的中心0.5
    offset_h, offset_w = 0.5, 0.5
    steps_h = 1.0 / in_height  # 在y轴上缩放步长
    steps_w = 1.0 / in_width  # 在x轴上缩放步长

    # 生成锚框的所有中心点
    center_h = (torch.arange(in_height, device=device) + offset_h) * steps_h
    center_w = (torch.arange(in_width, device=device) + offset_w) * steps_w
    shift_y, shift_x = torch.meshgrid(center_h, center_w, indexing='ij')
    shift_y, shift_x = shift_y.reshape(-1), shift_x.reshape(-1)

    # 生成“boxes_per_pixel”个高和宽,
    # 之后用于创建锚框的四角坐标(xmin,xmax,ymin,ymax)
    w = torch.cat((size_tensor * torch.sqrt(ratio_tensor[0]),
                   sizes[0] * torch.sqrt(ratio_tensor[1:])))\
                   * in_height / in_width  # 处理矩形输入
    h = torch.cat((size_tensor / torch.sqrt(ratio_tensor[0]),
                   sizes[0] / torch.sqrt(ratio_tensor[1:])))
    # 除以2来获得半高和半宽
    anchor_manipulations = torch.stack((-w, -h, w, h)).T.repeat(
                                        in_height * in_width, 1) / 2

    # 每个中心点都将有“boxes_per_pixel”个锚框,
    # 所以生成含所有锚框中心的网格,重复了“boxes_per_pixel”次
    out_grid = torch.stack([shift_x, shift_y, shift_x, shift_y],
                dim=1).repeat_interleave(boxes_per_pixel, dim=0)
    output = out_grid + anchor_manipulations
    return output.unsqueeze(0)

靠这个看懂了

原文:

1.1 书上代码解析

s 指的是长宽的缩放比例而非面积的缩放比例,比如 s=0.5,则面积就是原图像的 0.5^2=0.25 倍。r 是宽高比,指的是将原图像归一化为正方形后截取的锚框的宽高比;或者说是在原图像的宽高比基础上乘以 r,才是锚框的宽高比。锚框的实际宽高比即。之所以 r=1 时你看到的是方形,之后会解释。 由此,可得以下方程组解得和分别处以 w 和 h 进行归一化,可得而在代码中我们可以看到:

1
2
3
4
5
w0 = torch.cat((size_tensor * torch.sqrt(ratio_tensor[0]),
                   sizes[0] * torch.sqrt(ratio_tensor[1:])))\
                   * in_height / in_width
h0 = torch.cat((size_tensor / torch.sqrt(ratio_tensor[0]),
                   sizes[0] / torch.sqrt(ratio_tensor[1:])))

先不看 in_height / in_width。上面解得的归一化后的公式与代码所写的一模一样。代码中的和就是锚框归一化后的宽高(此时消除了原图像 w 和 h 的影响,可以认为,r 所代表的宽高比就是此时锚框的宽高比,r=1 时,是一个正方形锚框,也即此时和的值是一样的)。但是呢,由于我们显示的时候需要乘以图像的实际宽高所以,乘后的锚框实际宽高比就不是 1 了,所以才要乘以 in_height / in_width,作用就是抵消乘以实际图像长宽后 r 会改变的问题,当然这样做存粹是为了显示方便(也让你误以为 r 是指锚框的宽高比),带来的副作用就是,锚框的实际面积就不再是原始图像的。( ̄ε(# ̄)。

由于实际在我们进行目标检测时,特征图长和宽都是相同的,比如 (19, 19)、(7, 7),所以 in_height / in_width 恒等于 1,因此对于实际的使用并不会带来副作用。但此时,如果要将锚框显示出来,归一化后的锚框再乘以图像实际长宽后,所显示的锚框的长宽比会改变。如下图所示,特征图宽高是 (1, 1),当 r=1,s=0.5 时,最终锚框的宽高比并不是 r=1,而是。即上述代码中 in_height / in_width 这部分失效了。好消息是,面积是原图的,又符合定义了。\( ̄︶ ̄\))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值