为何torchvision.transforms.Resize与tensorflow.image.resize_images结果不一致?
双线性插值在PyTorch与TensorFlow中结果不一致的原因
问题描述
使用双线性插值分别调用torchvision.transforms.Resize与tensorflow.image.resize_images对同一张量进行缩放操作,却得到了不同的输出结果。测试代码如下:
import torch import torch.nn as nn size_psc = 128 torch.manual_seed(123) x0 = torch.randn(torch.Size([1, 64, 502, 502])) #using torchvision import torchvision.transforms as transforms resize = transforms.Resize((size_psc, size_psc)) torch_resize_out = resize(x0) #using tensorflow import tensorflow as tf tf_x0 = x0.permute(0, 2, 3, 1).contiguous() tf_resize = tf.image.resize_images(tf_x0, (size_psc, size_psc), 0) sess = tf.Session() tf_resize_out = sess.run(tf_resize) sess.close() tf_resize_out = torch.Tensor(tf_resize_out) tf_resize_out = tf_resize_out.permute(0, 3, 1, 2).contiguous() assert torch.max(abs(torch_resize_out - tf_resize_out)) < 1e-5
使用环境版本:torchvision(0.11.2)、torch(1.10.1)、tensorflow(1.10.0)。期望两者输出结果一致,但实际存在明显差异,需了解原因。
核心原因
两者结果不一致的本质是双线性插值的底层实现细节存在差异,具体体现在以下几点:
1. 坐标对齐方式不同
- PyTorch的
Resize(基于torch.nn.functional.interpolate)默认采用像素中心对齐:计算目标像素对应的源图像坐标时,以像素的中心点作为基准。例如源图像尺寸为H×W,目标为h×w,坐标映射会将目标像素位置对应到源图像的像素中心。 - TensorFlow 1.x的
resize_images默认采用像素角点对齐:将图像左上角视为坐标原点(0,0),右下角视为(H,W),目标像素坐标直接按比例映射到该范围,而非像素中心。这种坐标基准的差异会直接导致插值时选取的源像素权重不同。
2. 边界与权重计算逻辑差异
即使都是双线性插值,两者在边界像素处理、权重计算精度上也有区别:
- PyTorch会对超出源图像范围的坐标进行裁剪,仅使用有效像素插值;
- TensorFlow 1.x的
resize_images在边界处采用不同的填充/外推逻辑,当源图像尺寸无法被目标尺寸整除时,这种差异会被放大。
3. 版本特性差异
你使用的TensorFlow 1.10.0是较旧版本,其resize_images的双线性插值实现和PyTorch 1.10.x/vision 0.11.x的标准存在明显区别。后续TensorFlow 2.x的tf.image.resize已调整默认对齐方式,而PyTorch的Resize在该版本中已固化像素中心对齐逻辑。
对齐结果的思路
如果需要让两者输出一致,可以手动对齐坐标计算规则:
- 对TensorFlow 1.x手动调整坐标映射,改为像素中心对齐的方式;
- 或在PyTorch中使用
torch.nn.functional.interpolate并设置align_corners=True,该参数会让PyTorch的插值对齐方式接近TensorFlow 1.x的默认逻辑,但注意这会改变边界区域的插值效果。
内容的提问来源于stack exchange,提问作者lefthand927
相关产品推荐
相关产品推荐

