PIL、OpenCV中resize算子实现不同的问题
测试图像:https://raw.githubusercontent.com/TropComplique/ssd-pytorch/master/images/dogs-and-cats.jpg (直接 wget 可获得)
测试版本:
- opencv-python 4.4.0.46
- Pillow 8.0.1
测试代码:
import cv2
from PIL import Image
import numpy as np# read images
path = './dogs-and-cats.jpg'
b = Image.open(path)
a = cv2.imread(path)[:, :, ::-1]# they are equal
c = np.asarray(b)
print(np.abs(np.int16(b) - np.int16(a)).mean())# resize images
a_0 = cv2.resize(a, (300, 300))
b_0 = b.resize((300, 300))a_1 = cv2.resize(a, (300, 300), interpolation=cv2.INTER_NEAREST)
b_1 = b.resize((300, 300), Image.NEAREST)# results of resizing are different, but visually they are equal
print(np.abs(np.int16(b_0) - np.int16(a_0)).mean())
print(np.abs(np.int16(b_1) - np.int16(a_1)).mean())
测试结果:
0.0
1.785388888888889
7.455274074074074
结论:
- PIL 和 OpenCV 在读取图像文件的结果基本(也不是完全)是一致的;
- 但是在按照各自默认的差值方式进行插值后,结果却有一定差异;
- 即使指定相同的插值方式(本例中为最近邻插值)之后,结果也有较大的差异。
注意事项:
- 注意 opencv 中的默认数据类型是
np.uint8
,用以表示 0-255 之间的像素值,在计算两个 np 数组的像素值的差异时,要转换为np.int16
并取绝对值,因为np.uint8
中没有负数,如果像素值作差得到负数,则会被转换为 uint8 的正数,如 -1 -> 255。 - PIL 和 OpenCV 读取图像文件的结果在本例中是一样的(误差为0.0),但是笔者亲测这是与图像有关的,换一张图大概率就不能做到误差为 0 了,但是误差基本也都在 1 以内。
- PyTorch 中的
torchvision.transforms.Resize
就是采用的 PIL 的 resize 。
Ref:
Pillow
vs cv2
resize