Keras load_img target_size与PIL resize输出结果不一致问题
两段图像缩放代码输出结果差异显著的核心原因
两者逻辑看似一致,实际上调用的底层缩放规则有两个关键差异,在目标尺寸极小(3*3)的场景下差异会被放得很大:
- 默认重采样(插值)算法完全不同
手动调用PIL图像的resize()方法时,新版Pillow默认使用双线性插值,缩放时会对采样点周边的像素做加权平均计算,同时大幅缩小图像时默认开启抗锯齿预滤波,输出是平滑处理后的像素值。
而load_img传入target_size触发内部缩放时,默认使用最近邻插值,直接取距离采样点最近的原图像素作为结果,不做加权平滑、默认也不开抗锯齿。当原图分辨率很高、直接缩到3*3这种极小尺寸时,两种算法的采样点取值偏差会非常明显。 - 尺寸参数的语义顺序不一致
PIL原生resize()接收的尺寸参数格式是(width, height)(宽在前、高在后),但Keras的load_img的target_size参数要求的格式是(height, width)(高在前、宽在后)。虽然你传入的(3,3)宽高数值相等,不会出现图像拉伸,但Keras内部会做尺寸顺序的转换,极小尺寸缩放下采样点坐标计算会和直接传同数值给PIL原生resize出现偏移,进一步拉大结果差异。
复现验证方法:给两段代码指定完全一致的插值规则、对齐尺寸顺序即可得到相同输出。比如第一段代码手动指定
image = image.resize((target_size[1], target_size[0]), resample=Image.NEAREST),或者第二段代码调用load_img时传入interpolation='bilinear'参数,两边输出的numpy数组就会完全匹配。
内容的提问来源于stack exchange,提问作者Ansh
相关产品推荐
相关产品推荐

