nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1,
padding=0, output_padding=0, groups=1, bias=True,
dilation=1, padding_mode=‘zeros’)
torch.nn.Upsample(size=None, scale_factor=None, mode=‘nearest’, align_corners=None)
对输入的多通道数据进行上采样
size (tuple ,optional)– 是输出矩阵大小([optional D_out], [optional H_out], W_out)的元组。
scale_factor (int / tuple of python:ints, optional) – 图像宽/高/深度的倍数
mode – (string, optional) – 上采样方法: 有nearest, linear, bilinear, bicubic and trilinear. 默认是: nearest
align_corners (bool, optional) – 如果为true,则输入和输入tensor的角点像素对齐,从而保留这些像素的像素值。 默认值: False
两者都是用来实现上采样,假设采样倍数为scale, 则把(H, W, C) -->变为(H*scale, W*scale,C)
下面以2倍上采样为例。
nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
其中mode为选择的插值方法。
双线性插值原理及公式:
所以为了求P点需要根据P得到Q11,Q12,Q21以及Q22的坐标以及值!
步骤如下:
1)求P点坐标。对于目标图上的一个点Pdst,先求取对应的在源图上的点P,一般以像素中心为标准.(如果标准不同会导致最后的resize结果不同, 如opencv和matlab)
2)利用P点坐标求Q11,Q12,Q21以及Q22的坐标以及值。因为P点一般为小数,则对应的4个点就是相邻整数,如下图所示,则值也可以求出
3)套用公式,得到目标图上Pdst的值。
代码如下:
for n in range(3): # 对channel循环
for dst_y in range(dst_h): # 对height循环
for dst_x in range(dst_w): # 对width循环
# 目标在源上的坐标
src_x = (dst_x + 0.5) * scale_x - 0.5
src_y = (dst_y + 0.5) * scale_y - 0.5
# 计算在源图上四个近邻点的位置
src_x_0 = int(np.floor(src_x))
src_y_0 = int(np.floor(src_y))
src_x_1 = min(src_x_0 + 1, src_w - 1)
src_y_1 = min(src_y_0 + 1, src_h - 1)
# 双线性插值
value0 = (src_x_1 - src_x) * src[src_y_0, src_x_0, n] + (src_x - src_x_0) * src[src_y_0, src_x_1, n]
value1 = (src_x_1 - src_x) * src[src_y_1, src_x_0, n] + (src_x - src_x_0) * src[src_y_1, src_x_1, n]
dst[dst_y, dst_x, n] = int((src_y_1 - src_y) * value0 + (src_y - src_y_0) * value1)
return dst
2.ConvTranspose2d可以理解为卷积的逆过程。所以可以训练参数
nn.ConvTranspose2d(mid_channels, mid_channels, kernel_size=4, stride=2, padding=1)
其中输出尺寸与输入关系如下,所以,k=4, s=2, p=1即2倍上采样。
具体执行过程为通过对原图插值0,扩大尺寸,然后改变卷积参数,对扩大尺寸后的进行卷积即nn.ConvTranspose2d:
1)原图插值,在两两元素之间插0。
2)改变参数。新的卷积核:Stride′=1, kernel的size′ = size padding' 为Size−padding−1
3)卷积
如图所示:(3*3)--> (6*6)