Cum identifici imagini similare folosind hashing și Python

  • 3 minute de citit
  • 7 exemple de cod
  • 1 imagine

Disponibil și în English

Pe această pagină

Salut 👋,

În acest articol vreau să vorbesc despre image hashing.

Algoritmii de image hashing sunt funcții de hashing specializate, care returnează hash-ul unei imagini pe baza proprietăților acesteia. Imaginile duplicate returnează aceeași valoare hash, iar imaginile vizual identice returnează o valoare hash care diferă puțin.

Pentru a simplifica:

hash("white_cat") = "aaaa"hash("brown_cat") = "aaba"hash("car") = "xkjwe"

Câteva cazuri de utilizare pentru image hashing sunt:

  • Detectarea imaginilor duplicate
  • Anti-impersonare / furt de imagini
  • Filtrarea imaginilor
  • Căutarea inversă de imagini

Să ne jucăm cu tehnicile de image hashing folosind Python și biblioteca ImageHash. Instalează biblioteca cu:

pip install imagehashpip install six

Pentru a obține câteva imagini de test am folosit Pexels și am căutat cuvinte precum „white cat”, „firetruck”.

Iată imaginile pe care le folosesc: cat1, cat2, cat3 și firetruck1.

Voi importa lucrurile necesare și voi adăuga o funcție care convertește șirul hexadecimal returnat de image hash într-un număr întreg.

from PIL import Imageimport imagehashdef hash_to_int(img_hash: imagehash.ImageHash):    return int(str(img_hash), 16)

Motivul pentru funcția hash_to_int este că sunt mult mai ușor de făcut calcule cu numere întregi decât cu șiruri de caractere. Dacă în viitor vom construi un serviciu care folosește image hashing și calculează distanțe Hamming, putem stoca hash-urile sub formă de numere întregi într-o bază de date OLAP, precum ClickHouse, și putem folosi bitHammingDistance pentru a calcula distanța Hamming.

Următorul fragment de cod deschide imaginile, calculează hash-urile average și color și, pentru fiecare imagine din set, calculează distanța Hamming: suma dintre distanța Hamming a hash-ului average și distanța Hamming a hash-ului color.

Cu cât distanța Hamming este mai mică, cu atât imaginile sunt mai similare. O distanță Hamming de 0 înseamnă că imaginile sunt identice.

def main():    images = [        Image.open("cat1.jpg"),        Image.open("cat2.jpg"),        Image.open("cat3.jpg"),        Image.open("firetruck1.jpg")    ]    average_hashes = [hash_to_int(imagehash.average_hash(image)) for image in images]    color_hashes = [hash_to_int(imagehash.colorhash(image)) for image in images]    image_hashes = list(zip(images, average_hashes, color_hashes))    source = image_hashes[0]    for image in image_hashes:        hamming_average_hash = bin(source[1] ^ image[1]).count("1")        hamming_color_hash = bin(source[2] ^ image[2]).count("1")        hamming_distance = hamming_average_hash + hamming_color_hash        print("Hamming Distance between", source[0].filename, "and", image[0].filename, "is", hamming_distance)if __name__ == '__main__':    main()

Pentru a calcula distanța Hamming, trebuie să faci XOR între cele două numere întregi și apoi să numeri biții de 1: bin(source[1] ^ image[1]).count("1"). Atât.

Dacă rulăm programul cu variabila source setată la cat1.jpg, source = image_hashes[0], obținem următorul rezultat:

Hamming Distance between cat1.jpg and cat1.jpg is 0Hamming Distance between cat1.jpg and cat2.jpg is 36Hamming Distance between cat1.jpg and cat3.jpg is 39Hamming Distance between cat1.jpg and firetruck1.jpg is 33

Dacă ne uităm la setul nostru de date, prima imagine, cat1, este oarecum vizual similară cu imaginea camionului de pompieri.

Dacă rulăm programul cu variabila source setată la cat2.jpg, vedem că cat2 este similară cu cat3, pentru că ambele imagini conțin pisici albe.

Hamming Distance between cat2.jpg and cat1.jpg is 36Hamming Distance between cat2.jpg and cat2.jpg is 0Hamming Distance between cat2.jpg and cat3.jpg is 23Hamming Distance between cat2.jpg and firetruck1.jpg is 47

Concluzie

Am folosit o bibliotecă Python de image hashing pentru a calcula hash-urile average și color ale unor imagini, apoi am determinat care imagini sunt similare între ele, calculând distanța Hamming a hash-urilor.

Mulțumesc că ai citit și construiește ceva interesant! 🔨

Referințe

Codul complet

"""pip install imagehashpip install six"""from PIL import Imageimport imagehashdef hash_to_int(img_hash: imagehash.ImageHash):    return int(str(img_hash), 16)def main():    images = [        Image.open("cat1.jpg"),        Image.open("cat2.jpg"),        Image.open("cat3.jpg"),        Image.open("firetruck1.jpg")    ]    average_hashes = [hash_to_int(imagehash.average_hash(image)) for image in images]    color_hashes = [hash_to_int(imagehash.colorhash(image)) for image in images]    image_hashes = list(zip(images, average_hashes, color_hashes))    source = image_hashes[0]    for image in image_hashes:        hamming_average_hash = bin(source[1] ^ image[1]).count("1")        hamming_color_hash = bin(source[2] ^ image[2]).count("1")        hamming_distance = hamming_average_hash + hamming_color_hash        print("Hamming Distance between", source[0].filename, "and", image[0].filename, "is", hamming_distance)if __name__ == '__main__':    main()