![](/img/trans.png)
[英]Python - Elegant method of determining whether any objects exist in a collection
[英]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
有很多比较图像的方法,但是对于您给出的示例,我怀疑简单性和速度是关键因素(因此,为什么要尝试使用哈希作为首次通过)。 这里有一些建议-在所有情况下,我建议将图像缩小并裁剪为规则的大小和形状。
scipy.spatial.distance
)来计算两个图像之间的“距离”。 例如, euclidean
距离将有效地提供与相减之和,而cosine
将忽略强度,但匹配图像上变化的轮廓,即,同一图像的较暗版本将被视为等效。 对于这些,您将需要将图像展平为一维数组。 最后两个需要在上传时将每个图像与每个其他图像进行比较,这对于大量图像将在计算上变得非常昂贵。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.