![](/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.