【问题标题】:Images opened in Pillow and OpenCV are not equivelant在 Pillow 和 OpenCV 中打开的图像不等效
【发布时间】:2018-04-22 10:39:28
【问题描述】:

我从 Wikipedia(如下图所示的树)下载了一张测试图像,以在 python 中比较 PillowOpenCV(使用 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 建议的更改之前看到的。

【问题讨论】:

  • 我可能是错的,但我认为您可能在这里遇到了舍入错误np.array(Image.open(im)) 和 iirc imshow 拉伸颜色以满足范围(查看im-imP 的实际值,它们很可能非常小)
  • 我只是tried 它,但这里没有区别(win10 + python3.6 + opencv-python==3.4.0.12 + Pillow==5.1.0)。
  • @Nullman 有趣的想法,但我不确定您所说的舍入错误是什么意思。 np.array(Image.open(im)) 给出dtype=np.uunt8。我在im-imP 中发布了值分布图。
  • 因为 joost 成功地运行它而没有问题,也许在您的这些库版本中确实有些不同。你用的是什么版本?
  • @Joost 有趣...当我将图像上传到 SO 时,它可能被重新编码。如果您还没有尝试过with the original,您介意吗?

标签: python opencv python-imaging-library pillow cv2


【解决方案1】:

原始图像是 JPEG。

JPEG解码会根据libjpeg版本、编译器优化、平台等不同产生不同的结果。

检查 PillowOpenCV 正在使用哪个版本的 libjpeg。

有关更多信息,请参阅此答案:JPEG images have different pixel values across multiple deviceshere

顺便说一句,(im-imP) 产生uint8 溢出(如果没有在您的frequency chart 中看到它,就不可能有如此大量的大像素差异)。在进行频率计算之前尝试转换为 int 类型。

【讨论】:

  • 谢谢!不知道JPEG。我更新了频率图表以使用int。原来im-imP != 0 的所有值都是负数。我还没有找到确切的版本,但我的OpenCV 已经很老了,它使用libjpeg 的内置源代码
猜你喜欢
  • 2015-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多