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