在 Pillow 和 OpenCV 中打开的图像并不相同
Images opened in Pillow and OpenCV are not equivelant
我从维基百科下载了一张测试图像(下面的树)来比较 python 中的 Pillow
和 OpenCV
(使用 cv2
)。从感知上看,这两张图片看起来是一样的,但它们各自的 md5
哈希值不匹配;如果我减去两个图像,结果甚至不接近纯黑色(原始图像下方显示的图像)。原始图像是 JPEG。如果我先将其转换为 PNG,则哈希匹配。
最后一张图片显示了像素值差异的频率分布。
正如 Catree 指出的那样,我的减法导致了整数溢出。我更新为在减法之前也转换为 dtype=int
(以显示负值),然后在绘制差值之前取绝对值。现在差异图像在感知上是纯黑色。
这是我使用的代码:
from PIL import Image
import cv2
import sys
import md5
import numpy as np
def hashIm(im):
imP = np.array(Image.open(im))
# Convert to BGR and drop alpha channel if it exists
imP = imP[..., 2::-1]
# Make the array contiguous again
imP = np.array(imP)
im = cv2.imread(im)
diff = im.astype(int)-imP.astype(int)
cv2.imshow('cv2', im)
cv2.imshow('PIL', imP)
cv2.imshow('diff', np.abs(diff).astype(np.uint8))
cv2.imshow('diff_overflow', diff.astype(np.uint8))
with open('dist.csv', 'w') as outfile:
diff = im-imP
for i in range(-256, 256):
outfile.write('{},{}\n'.format(i, np.count_nonzero(diff==i)))
cv2.waitKey(0)
cv2.destroyAllWindows()
return md5.md5(im).hexdigest() + ' ' + md5.md5(imP).hexdigest()
if __name__ == '__main__':
print sys.argv[1] + '\t' + hashIm(sys.argv[1])
频率分布已更新以显示负值。
这是我在实施 Catree 推荐的更改之前所看到的。
The original image is a JPEG.
JPEG 解码会产生不同的结果,具体取决于 libjpeg 版本、编译器优化、平台等。
检查 Pillow
和 OpenCV
使用的是哪个版本的 libjpeg。
有关详细信息,请参阅此答案:JPEG images have different pixel values across multiple devices or here。
顺便说一句,(im-imP)
会产生 uint8
溢出(没有办法在您的 frequency chart 中看到如此大量的大像素差异)。在进行频率计算之前尝试转换为 int
类型。
我从维基百科下载了一张测试图像(下面的树)来比较 python 中的 Pillow
和 OpenCV
(使用 cv2
)。从感知上看,这两张图片看起来是一样的,但它们各自的 md5
哈希值不匹配;如果我减去两个图像,结果甚至不接近纯黑色(原始图像下方显示的图像)。原始图像是 JPEG。如果我先将其转换为 PNG,则哈希匹配。
最后一张图片显示了像素值差异的频率分布。
正如 Catree 指出的那样,我的减法导致了整数溢出。我更新为在减法之前也转换为 dtype=int
(以显示负值),然后在绘制差值之前取绝对值。现在差异图像在感知上是纯黑色。
这是我使用的代码:
from PIL import Image
import cv2
import sys
import md5
import numpy as np
def hashIm(im):
imP = np.array(Image.open(im))
# Convert to BGR and drop alpha channel if it exists
imP = imP[..., 2::-1]
# Make the array contiguous again
imP = np.array(imP)
im = cv2.imread(im)
diff = im.astype(int)-imP.astype(int)
cv2.imshow('cv2', im)
cv2.imshow('PIL', imP)
cv2.imshow('diff', np.abs(diff).astype(np.uint8))
cv2.imshow('diff_overflow', diff.astype(np.uint8))
with open('dist.csv', 'w') as outfile:
diff = im-imP
for i in range(-256, 256):
outfile.write('{},{}\n'.format(i, np.count_nonzero(diff==i)))
cv2.waitKey(0)
cv2.destroyAllWindows()
return md5.md5(im).hexdigest() + ' ' + md5.md5(imP).hexdigest()
if __name__ == '__main__':
print sys.argv[1] + '\t' + hashIm(sys.argv[1])
频率分布已更新以显示负值。
这是我在实施 Catree 推荐的更改之前所看到的。
The original image is a JPEG.
JPEG 解码会产生不同的结果,具体取决于 libjpeg 版本、编译器优化、平台等。
检查 Pillow
和 OpenCV
使用的是哪个版本的 libjpeg。
有关详细信息,请参阅此答案:JPEG images have different pixel values across multiple devices or here。
顺便说一句,(im-imP)
会产生 uint8
溢出(没有办法在您的 frequency chart 中看到如此大量的大像素差异)。在进行频率计算之前尝试转换为 int
类型。