两张像素不同的图像如何检查相似度

37

我正在运行一个Python代码,检查Quora和Twitter用户的个人资料照片相似度,但是当图片相同时我没有得到积极的结果。

这是用于比较两张图片的代码:

path_photo_quora= "/home/yousuf/Desktop/quora_photo.jpg"
path_photo_twitter="/home/yousuf/Desktop/twitter_photo.jpeg"
if open(path_photo_quora,"rb").read() == open(path_photo_twitter,"rb").read():
     print('photos profile are identical')

尽管这些图片是一样的,控制台没有打印出“照片资料相同”的信息,我该怎么办?


3个回答

64
您可以使用imagehash库来比较相似的图像。
from PIL import Image
import imagehash
hash0 = imagehash.average_hash(Image.open('quora_photo.jpg')) 
hash1 = imagehash.average_hash(Image.open('twitter_photo.jpeg')) 
cutoff = 5  # maximum bits that could be different between the hashes. 

if hash0 - hash1 < cutoff:
  print('images are similar')
else:
  print('images are not similar')

由于这些图像并不完全相同,因此会存在一些差异,因此我们使用接受最大差异的截止值。哈希对象之间的差异是翻转的位数。但是即使图像被调整大小、压缩、使用不同的文件格式或者调整了对比度或颜色,imagehash仍然可以工作。

哈希(或指纹)是从图像的8x8单色缩略图中派生出来的。但即使使用如此简化的样本,相似度比较也可以给出相当准确的结果。调整截止值以找到可接受的误报率和漏报率之间的平衡点。

64位哈希中,0的差异意味着哈希完全相同。32的差异意味着完全没有相似之处。64的差异意味着一个哈希正好是另一个哈希的反码。


2
有没有办法在线操作这些图像而不必将它们下载下来?例如,可以通过提供代码中图片的 URL 而不是本地路径来实现吗? - Youcef
3
不在图书馆本身内。您必须使用类似于“requests”的工具通过http下载图片。这只需要几行代码。https://dev59.com/JY_ea4cB1Zd3GeqPQpxK#32859290 - Håken Lid
2
如果您使用我提供的代码,图像将仅在内存中处理。除非您明确要求,否则它们不会被存储到您的驱动器中。 - Håken Lid
2
@MDP,是的。因为在哈希之前,图像被调整为相同的微小尺寸。通常为8x8像素。 - Håken Lid
2
使用8x8像素或64位的哈希/指纹/位图,距离为5意味着两个哈希中的64位中有5个是不同的。以下是一篇文章,解释了图像哈希算法的工作原理,并包括示例图像。https://content-blockchain.org/research/testing-different-image-hash-functions/ - Håken Lid
显示剩余7条评论

7
这两张图片并不完全相同,只有被拍摄的物体相同。正如您自己所提到的,这些图像大小显然不同。因此,比较是无法成功的。
您需要采用某种相似性检查方法。第一步是将较小的图像缩放到较大的图像大小。然后,您需要使用某种方法来检测和定义相似性。有不同的方法和技术可以实现这一点,任何其中的组合都可能有效。
例如,请参见 使用OpenCV检查图像相似性

1
import cv2

class CompareImage(object):

    def __init__(self, image_1_path, image_2_path):
        self.minimum_commutative_image_diff = 1
        self.image_1_path = image_1_path
        self.image_2_path = image_2_path

    def compare_image(self):
        image_1 = cv2.imread(self.image_1_path, 0)
        image_2 = cv2.imread(self.image_2_path, 0)
        commutative_image_diff = self.get_image_difference(image_1, image_2)

        if commutative_image_diff < self.minimum_commutative_image_diff:
            print "Matched"
            return commutative_image_diff
        return 10000 //random failure value

    @staticmethod
    def get_image_difference(image_1, image_2):
        first_image_hist = cv2.calcHist([image_1], [0], None, [256], [0, 256])
        second_image_hist = cv2.calcHist([image_2], [0], None, [256], [0, 256])

        img_hist_diff = cv2.compareHist(first_image_hist, second_image_hist, cv2.HISTCMP_BHATTACHARYYA)
        img_template_probability_match = cv2.matchTemplate(first_image_hist, second_image_hist, cv2.TM_CCOEFF_NORMED)[0][0]
        img_template_diff = 1 - img_template_probability_match

        # taking only 10% of histogram diff, since it's less accurate than template method
        commutative_image_diff = (img_hist_diff / 10) + img_template_diff
        return commutative_image_diff


    if __name__ == '__main__':
        compare_image = CompareImage('image1/path', 'image2/path')
        image_difference = compare_image.compare_image()
        print image_difference

1
您好,感谢您的回答。如果您能解释您的答案为什么以及如何解决OP的问题,这将对我们的读者非常有帮助。 - Simas Joneliunas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接