pytorch中的F.grid_sample使用方法及应用代码(align_corners参数详细解释)

首先Pytorch中grid_sample函数的接口声明如下:

torch.nn.functional.grid_sample(input, grid, mode='bilinear', padding_mode='zeros', align_corners=None)

简单来说就是,提供一个input的Tensor以及一个对应的grid网格,然后根据grid中每个位置提供的坐标信息(这里指input中pixel的坐标),将input中对应位置的像素值填充到grid指定的位置,得到最终的输出。

其中,input、grid和output分别表示输入Tensor,映射网格Tensor和输出Tensor,其尺寸如下所示:
i n p u t : ( N , C , H , W ) g r i d : ( N , H , W , 2 ) o u t p u t : ( N , C , H , W ) input: (N,C,H,W)\\ grid:(N,H,W,2)\\ output:(N,C,H,W) input:(N,C,H,W)grid:(N,H,W,2)output:(N,C,H,W)
其中grid中的2表示x,y方向的两个通道的映射,H,W是尺寸。这里一般会将(x,y)归一化到[-1,1],其中[-1,-1]代表左上角的像素,[1,1]代表右下角的像素。首先,以下代码先生成一个恒等的采样矩阵,然后进行采样。这里的恒等采样矩阵就是指左上角是[-1,-1],右上角是[-1,1],左下角是[1,-1],右下角是[1,1],并且元素均匀分布的矩阵,该矩阵是我们采样的原始参考grid网格。

import torch.nn.functional as F
import torch
featSize = 5
#生成恒等网络采样grid
gridY = torch.linspace(-1, 1, steps = featSize).view(1, -1, 1, 1).expand(1, featSize, featSize, 1)
gridX = torch.linspace(-1, 1, steps = featSize).view(1, 1, -1, 1).expand(1, featSize,  featSize, 1)
grid = torch.cat((gridX, gridY), dim=3).type(torch.float32)

#生成输入tensor(input),大小为[1,1,featSize,featSize],数据分布[1,2,...,featSize*featSize]
predict_roof = torch.linspace(1,featSize**2,steps=featSize**2,dtype=torch.float32).reshape(featSize,featSize)
predict_roof = (predict_roof.unsqueeze(dim=0)).unsqueeze(dim=0)

#使用恒等采样矩阵grid对input进行采样
trans_feature = F.grid_sample(predict_roof,grid,align_corners=True)
print(predict_roof)
print(grid.permute(0,3,1,2))
print(trans_feature)

输出结果为:可见恒等采样矩阵的采样结果是不改变原始的数据分布。
恒等采样矩阵采样结果
值得注意的是,F.grid_sample()中存在一个bool参数(align_corners)

  • 当该参数设置为True时:采样网格的坐标被视为指向像素的角点。这种设置通常用于对齐图像边缘的像素。
  • 当该参数设置为False时:采样网格的坐标被视为指向像素之间的中心点。这种设置通常用于保持图像的整体形状和分辨率。

以下对上述两个设置进行详细的说明:
首先,我们如何看待一副图像中像素的组成。这里又两种方式:1、看作是方块;2、看作是点。如下图所示。对于一个 5 × 5 5\times 5 5×5的一副图像。
像素分布示意图

  • align_corners = False:
    -原始像素可以看作是一个点,如上述右图所示。映射网格grid的数据点被视为指向像素之间的中心点。计算过程示意图如下所示。需要注意的是,原始图像大小为 5 × 5 5\times 5 5×5,输出Tensor大小为 6 × 6 6\times6 6×6,并且F.grid_sample()的padding方式是zeros填充方式。
    align_corners = False映射结果

上述输出tensor左上角的像素对应(-1,-1),右下角像素对应(1,1)。代码计算结果如下所示。
代码输出结果

  • align_corners = True:
    原始像素可以看作是一个像素方框,如上述左图所示。映射网格grid的数据点被视为指向像素之间的角点。计算过程如下所示。输入Tensor大小为 5 × 5 5\times 5 5×5,输出大小为 5 × 5 5\times 5 5×5
    align_corners = True计算示意图

左上角对应的grid坐标为(-1,-1),右下角对应的grid坐标为(1,1)。上述grid为恒等采样矩阵时,输出Tensor和输入Tensor是一样的。为了说明上述的运算过程,现在假设某一个像素点的grid映射坐标为(-0.9,-1),即上述示意图中的紫色点,该点距离左点0.1,距右点0.4。即有如下计算:
0.1 0.4 + 0.1 × 2 + 0.4 0.4 + 0.1 × 1 = 1.2 \frac{0.1}{0.4+0.1}\times2+\frac{0.4}{0.4+0.1}\times1 = 1.2 0.4+0.10.1×2+0.4+0.10.4×1=1.2
代码中设置映射grid[0,0,0,:] = [-0.9,-1],即输出左上角映射到[-0.9,1],经过以上计算,左上角点应该是1.2。结果如下所示。
代码运行示意图
总结:本质上来说,align_corners 设置映射的网格grid是否与输入Tensor对齐,False代表不对齐,True代表对齐。以后提供应用代码,今天有点累,想摆烂了。未完待续…

<think>好的,我现在需要向用户解释PyTorch中的F.affine_grid和F.grid_sample这两个函数。首先,我得回忆一下这两个函数的作用和常见用法,确保自己理解正确。 用户之前问了关于正态分布的函数,现在转向PyTorch的图像处理部分,可能是在进行图像增强或空间变换,比如在深度学习模型中应用仿射变换。用户可能在使用这些函数时遇到了问题,或者想更深入了解它们的原理和用法。 首先,F.affine_grid应该是用来生成仿射变换的网格,而F.grid_sample则根据这个网格对输入图像进行采样。我需要明确这两个函数各自的输入输出,参数的意义,以及它们是如何配合使用的。 对于F.affine_grid参数包括theta(仿射矩阵)、size(输出尺寸),可能还有align_corners。需要说明theta的形状,比如对于N个样本,theta是Nx2x3的矩阵,而输出的网格是NxHxWx2,这里的H和W是目标尺寸的高和宽。每个网格点的坐标对应目标图像的位置,经过仿射变换后映射到原图的哪个位置。 然后是F.grid_sample,它接受输入图像和由affine_grid生成的网格,根据网格中的坐标对输入进行采样。需要解释采样方式,比如双线性插值,padding_mode如何处理越界坐标,以及align_corners的影响。同时,要提到输入可以是4D或5D张量,对应图像或体积数据。 用户可能想知道为什么需要这两个函数配合使用,以及它们在具体任务中的应用场景,比如数据增强、空间变换网络(STN)等。需要举一个例子,比如旋转、平移、缩放图像,或者更复杂的仿射变换,说明如何使用这两个函数实现。 此外,可能需要注意常见的参数错误,比如theta的形状是否正确,网格和输入的尺寸是否匹配,align_corners的设置是否一致。同时,提醒用户梯度问题,因为在训练中这些操作可能需要反向传播。 总结时,要强调两个函数的协作关系:affine_grid生成映射关系,grid_sample执行实际的像素采样,从而完成图像的空间变换。确保解释清晰,步骤分明,帮助用户理解如何正确使用它们。如果有必要,可以添加简单的代码示例,展示从生成仿射矩阵到应用变换的完整流程。</think>在PyTorch中,`F.affine_grid` 和 `F.grid_sample` 是用于实现图像或张量的**空间变换**(如平移、旋转、缩放等)的核心函数,常用于数据增强、空间变换网络(Spatial Transformer Networks, STN)等任务。以下是它们的详细说明: --- ### **1. `F.affine_grid`:生成仿射变换的采样网格** #### 功能 根据给定的仿射变换矩阵(`theta`),生成一个**采样网格**,描述如何将输入图像映射到目标图像。 #### 参数 - **`theta` (Tensor)**:仿射变换矩阵,形状为 `(N, 2, 3)`(2D变换)或 `(N, 3, 4)`(3D变换)。 - 对于2D图像:每个变换矩阵形如: \[ \begin{bmatrix} \theta_{11} & \theta_{12} & t_x \\ \theta_{21} & \theta_{22} & t_y \end{bmatrix} \] 其中前两列控制旋转/缩放,最后一列控制平移。 - `N` 是批量大小(batch size)。 - **`size` (tuple)**:目标图像的尺寸 `(N, C, H, W)`。 - **`align_corners` (bool)**:是否对齐像素角点(影响坐标计算方式,需与后续操作一致)。 #### 输出 - **`grid` (Tensor)**:形状为 `(N, H, W, 2)` 的网格,每个位置 `(i,j)` 存储目标图像中该点对应的**原始图像坐标** `(x, y)`。 --- ### **2. `F.grid_sample`:根据网格对输入进行采样** #### 功能 利用 `F.affine_grid` 生成的网格,对输入图像(或特征图)进行**双线性插值采样**,生成变换后的图像。 #### 参数 - **`input` (Tensor)**:输入图像或特征图,形状为 `(N, C, H_in, W_in)`。 - **`grid` (Tensor)**:由 `F.affine_grid` 生成的采样网格,形状为 `(N, H_out, W_out, 2)`。 - **`mode` (str)**:采样模式,可选 `'nearest'`(最近邻)或 `'bilinear'`(双线性插值,默认)。 - **`padding_mode` (str)**:处理越界坐标的方式,可选 `'zeros'`(补零)、`'border'`(边缘复制)、`'reflection'`(镜像反射)。 - **`align_corners` (bool)**:需与 `F.affine_grid` 的设置一致。 #### 输出 - **`output` (Tensor)**:变换后的图像,形状为 `(N, C, H_out, W_out)`。 --- ### **协作流程** 1. **定义仿射矩阵 `theta`**:指定所需的变换(如旋转角度、平移量等)。 2. **生成网格 `grid = F.affine_grid(theta, size)`**:计算每个输出像素对应的输入坐标。 3. **采样图像 `output = F.grid_sample(input, grid)`**:根据网格坐标从输入中插值生成输出。 --- ### **示例代码(2D图像旋转)** ```python import torch import torch.nn.functional as F # 输入图像:1张3通道的256x256图像 input = torch.randn(1, 3, 256, 256) # (N, C, H, W) # 定义仿射矩阵(逆时针旋转30度) theta = torch.tensor([[ [0.866, -0.5, 0], # cos(30°)=0.866, sin(30°)=0.5 [0.5, 0.866, 0] ]]) # (1, 2, 3) # 生成目标网格(输出尺寸与输入相同) grid = F.affine_grid(theta, input.size(), align_corners=False) # 对输入进行采样(得到旋转后的图像) output = F.grid_sample(input, grid, align_corners=False) ``` --- ### **关键点** 1. **坐标归一化**:网格坐标范围为 `[-1, 1]`,左上角为 `(-1, -1)`,右下角为 `(1, 1)`。 2. **反向映射**:`F.affine_grid` 计算的是**目标图像到输入图像的坐标映射**(逆向变换)。 3. **梯度传播**:两者均支持自动求导,可直接用于神经网络训练。 4. **应用场景**: - 数据增强(随机旋转、裁剪、仿射变换)。 - 空间变换网络(STN)中的可学习变换。 - 多视角图像对齐、医学图像配准等。 --- ### **常见问题** - **为什么输出有黑色区域?** 越界坐标会被填充(由 `padding_mode` 控制),例如旋转后超出原图范围的区域默认补零(黑色)。 - **如何实现更复杂的变换?** 可组合多个仿射变换,或使用 `F.grid_sample` 直接自定义网格(如薄板样条变换)。 - **对齐模式(`align_corners`)的影响?** 若设为 `True`,网格坐标会严格对齐像素角点;否则按边缘中心对齐(通常推荐 `False`)。 通过这两个函数,可以高效实现图像的空间变换,并集成到深度学习模型中。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值