代码之家  ›  专栏  ›  技术社区  ›  chew socks

在Pillow和OpenCV中打开的图像并不等同

  •  4
  • chew socks  · 技术社区  · 6 年前

    我从Wikipedia下载了一个测试图像(见下面的树)来比较 Pillow OpenCV (使用 cv2 )在python中。从视觉上看,这两幅图像看起来是一样的,但它们各自不同 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])
    

    Original photo of a tree (from Wikipedia "Tree" article)

    频率分布更新为显示负值。

    Updated difference


    这就是我在实施Catree建议的更改之前看到的情况。

    Difference

    Dist

    1 回复  |  直到 6 年前
        1
  •  5
  •   Catree    6 年前

    原始图像是JPEG。

    JPEG解码可能会产生不同的结果,具体取决于libjpeg版本、编译器优化、平台等。

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

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

    顺便提一下 (im-imP) 生产 uint8 溢出(如果不在 frequency chart ).尝试转换到 int 在进行频率计算之前键入。