参考
差异
实际上,双线性插值给人造成困惑的地方在于如何确定放缩前后点的对应关系。
现有库的实现中,主要有三种策略:
- 直接规则放缩索引
cv2.warpAffine
tf.image.resize_bilinear(..., align_corners=False)
- 像素视为区域,中心对齐(两次偏移)
cv2.resize
torch.nn.interpolate(..., align_corner=False)
- 强制对其边界后均匀放缩(实际上这个更符合一般的理解)
tf.image.resize_bilinear(..., align_corners=True)
torch.nn.interpolate(..., align_corner=True)
mxnet.ndarray.contrib.BilinearResize2D
实践须知
实际上为了更好的对其边缘像素,我们在pytorch中可以考虑使用第三种策略,即 align_corners=True
,但是这样的对齐规则有一个小trick可以优化准确度,即尽可能使各个间隔为比较整齐的非无限小数,所以对于原始序列长度x和对应的目标序列长度y之间应该满足 x-1
和 y-1
之间是整数倍关系,间隔就会是比较整齐的小数。比如 x=5
而 y=9
,即放大2倍, scale_factor=2
,那么目标序列各点之间的间隔对应于原始序列的间隔的 (5-1)/(9-1)=0.5=1/scale_factor
。这也是deeplab团队使用的技巧。
Here is my own favorite set of rules that we have followed in our DeepLab semantic image segmentation system:
“DeepLab’s Four Alignment Rules”:
- Use of odd-sized kernels in all convolution and pooling ops.
- Use of SAME boundary conditions in all convolution and pooling ops.
- Use
align_corners=True
when upsampling feature maps with bilinear interpolation.- Use of inputs with height/width equal to a multiple of the output_stride, plus one (for example, when the CNN output stride is 8, use height or width equal to
8*n+1
, for somen
, e.g., imageHxW
set to321x513
).