繁体   English   中英

使用Python快速确定图像是否(模糊地)在集合中

[英]Quickly determining using Python whether an image is (fuzzily) in a collection

某个新图像X到达的图像,我想知道X是新图像还是以前已经遇到过。 我下面有代码,该代码会缩小图像,然后将其转换为哈希代码。 然后,我可以通过一次哈希查找来查看是否已经遇到了具有相同哈希码的图像,因此速度非常快。

我的问题是,是否有一种有效的方法让我查看是否已经看到了相似的图像,但是具有不同的哈希码? 如果要给这个问题加上标题,诸如“用于有效确定是否包含相似,不同的项目的数据结构”之类的东西,但认为这将是XY问题的一个实例。

当我说这个新图像“相似”时,我想到的是可能经过有损压缩的图像,因此看起来像原始图像,但并不完全相同。 通常情况下,缩小图像会消除差异,但并非总是如此,如果缩小图像过多,则会开始出现误报。

这是我当前的代码:

import PIL
seen_images = {} # This would really be a shelf or something

# From http://www.guguncube.com/1656/python-image-similarity-comparison-using-several-techniques
def image_pixel_hash_code(image):
    pixels = list(image.getdata())
    avg = sum(pixels) / len(pixels)
    bits = "".join(map(lambda pixel: '1' if pixel < avg else '0', pixels))  # '00010100...'
    hexadecimal = int(bits, 2).__format__('016x').upper()
    return hexadecimal

def process_image(filepath):
    thumb = PIL.Image.open(filepath).resize((128,128)).convert("L")
    code = image_pixel_hash_code(thumb)
    previous_image = seen_images.get(code, None)
    if code in seen_images:
        print "'{}' already seen as '{}'".format(filepath, previous_image)
    else:
        seen_images[code] = filepath

您可以将一堆图像文件的路径放入一个名为IMAGE_ROOT的变量,然后尝试使用以下代码:

import os
for root, dirs, files in os.walk(IMAGE_ROOT):
    for filename in files:
        filepath = os.path.join(root, filename)
        try:                
            process_image(filepath)
        except IOError:
            pass

有很多比较图像的方法,但是对于您给出的示例,我怀疑简单性和速度是关键因素(因此,为什么要尝试使用哈希作为首次通过)。 这里有一些建议-在所有情况下,我建议将图像缩小并裁剪为规则的大小和形状。

  1. 在缩小之前使图像平滑(高斯模糊),以最大程度地减少伪影的影响。 然后应用哈希或其他比较。
  2. 彼此相减图像(RGB)并检查其余部分。 相同的图像将返回零,压缩伪影将导致较小的细微变化。 您可以阈值,求和或取平均值,然后与截止值进行比较。
  3. 使用标准距离算法(请参阅scipy.spatial.distance )来计算两个图像之间的“距离”。 例如, euclidean距离将有效地提供与相减之和,而cosine将忽略强度,但匹配图像上变化的轮廓,即,同一图像的较暗版本将被视为等效。 对于这些,您将需要将图像展平为一维数组。

最后两个需要在上传时将每个图像与每个其他图像进行比较,这对于大量图像将在计算上变得非常昂贵。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM