{"id":13609038,"url":"https://github.com/JohannesBuchner/imagehash","last_synced_at":"2025-04-12T17:33:39.390Z","repository":{"id":7221519,"uuid":"8528872","full_name":"JohannesBuchner/imagehash","owner":"JohannesBuchner","description":"A Python Perceptual Image Hashing Module","archived":false,"fork":true,"pushed_at":"2024-10-09T08:38:40.000Z","size":8144,"stargazers_count":3531,"open_issues_count":23,"forks_count":339,"subscribers_count":62,"default_branch":"master","last_synced_at":"2025-02-23T02:44:50.633Z","etag":null,"topics":["image-hashing","image-hashing-algorithms","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"bunchesofdonald/photohash","license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JohannesBuchner.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-03-02T23:32:48.000Z","updated_at":"2025-02-20T23:20:52.000Z","dependencies_parsed_at":"2023-02-12T08:31:15.662Z","dependency_job_id":null,"html_url":"https://github.com/JohannesBuchner/imagehash","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohannesBuchner%2Fimagehash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohannesBuchner%2Fimagehash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohannesBuchner%2Fimagehash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohannesBuchner%2Fimagehash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JohannesBuchner","download_url":"https://codeload.github.com/JohannesBuchner/imagehash/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248605499,"owners_count":21132182,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["image-hashing","image-hashing-algorithms","python"],"created_at":"2024-08-01T19:01:31.966Z","updated_at":"2025-04-12T17:33:34.376Z","avatar_url":"https://github.com/JohannesBuchner.png","language":"Python","funding_links":[],"categories":["Python","Data Processing","图像数据与CV","Feature Extraction"],"sub_categories":["Data Management","Images and Video"],"readme":"===========\nImageHash\n===========\n\nAn image hashing library written in Python. ImageHash supports:\n\n* Average hashing\n* Perceptual hashing\n* Difference hashing\n* Wavelet hashing\n* HSV color hashing (colorhash)\n* Crop-resistant hashing\n\n|CI|_ |Coveralls|_ \n\nRationale\n=========\n\nImage hashes tell whether two images look nearly identical.\nThis is different from cryptographic hashing algorithms (like MD5, SHA-1)\nwhere tiny changes in the image give completely different hashes. \nIn image fingerprinting, we actually want our similar inputs to have\nsimilar output hashes as well.\n\nThe image hash algorithms (average, perceptual, difference, wavelet)\nanalyse the image structure on luminance (without color information).\nThe color hash algorithm analyses the color distribution and \nblack \u0026 gray fractions (without position information).\n\nInstallation\n============\n\nBased on PIL/Pillow Image, numpy and scipy.fftpack (for pHash)\nEasy installation through `pypi`_::\n\n\tpip install imagehash\n\nBasic usage\n===========\n::\n\n\t\u003e\u003e\u003e from PIL import Image\n\t\u003e\u003e\u003e import imagehash\n\t\u003e\u003e\u003e hash = imagehash.average_hash(Image.open('tests/data/imagehash.png'))\n\t\u003e\u003e\u003e print(hash)\n\tffd7918181c9ffff\n\t\u003e\u003e\u003e otherhash = imagehash.average_hash(Image.open('tests/data/peppers.png'))\n\t\u003e\u003e\u003e print(otherhash)\n\t9f172786e71f1e00\n\t\u003e\u003e\u003e print(hash == otherhash)\n\tFalse\n\t\u003e\u003e\u003e print(hash - otherhash)  # hamming distance\n\t33\n\nEach algorithm can also have its hash size adjusted (or in the case of\ncolorhash, its :code:`binbits`). Increasing the hash size allows an\nalgorithm to store more detail in its hash, increasing its sensitivity\nto changes in detail.\n\nThe demo script **find_similar_images** illustrates how to find similar\nimages in a directory.\n\nSource hosted at GitHub: https://github.com/JohannesBuchner/imagehash\n\nReferences\n-----------\n\n* Average hashing (`aHashref`_)\n* Perceptual hashing (`pHashref`_)\n* Difference hashing (`dHashref`_)\n* Wavelet hashing (`wHashref`_)\n* Crop-resistant hashing (`crop_resistant_hashref`_)\n\n.. _aHashref: https://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html\n.. _pHashref: https://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html\n.. _dHashref: https://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html\n.. _wHashref: https://fullstackml.com/wavelet-image-hash-in-python-3504fdd282b5\n.. _pypi: https://pypi.python.org/pypi/ImageHash\n.. _crop_resistant_hashref: https://ieeexplore.ieee.org/document/6980335\n\nExamples\n=========\n\nTo help evaluate how different hashing algorithms behave, below are a few hashes applied\nto two datasets. This will let you know what images an algorithm thinks are basically identical.\n\nExample 1: Icon dataset\n-----------------------\n\nSource: 7441 free icons on GitHub (see examples/github-urls.txt).\n\nThe following pages show groups of images with the same hash (the hashing method sees them as the same).\n\n* `phash \u003chttps://johannesbuchner.github.io/imagehash/index3.html\u003e`__ (or `with z-transform \u003chttps://johannesbuchner.github.io/imagehash/index9.html\u003e`__)\n* `dhash \u003chttps://johannesbuchner.github.io/imagehash/index4.html\u003e`__ (or `with z-transform \u003chttps://johannesbuchner.github.io/imagehash/index10.html\u003e`__)\n* `colorhash \u003chttps://johannesbuchner.github.io/imagehash/index7.html\u003e`__\n* `average_hash \u003chttps://johannesbuchner.github.io/imagehash/index2.html\u003e`__ (`with z-transform \u003chttps://johannesbuchner.github.io/imagehash/index8.html\u003e`__)\n\nThe hashes use hashsize=8; colorhash uses binbits=3.\nYou may want to adjust the hashsize or require some manhattan distance (hash1 - hash2 \u003c threshold).\n\nExample 2: Art dataset\n----------------------\n\nSource: 109259 art pieces from https://www.parismuseescollections.paris.fr/en/recherche/image-libre/.\n\nThe following pages show groups of images with the same hash (the hashing method sees them as the same).\n\n* `phash \u003chttps://johannesbuchner.github.io/imagehash/art3.html\u003e`__ (or `with z-transform \u003chttps://johannesbuchner.github.io/imagehash/art9.html\u003e`__)\n* `dhash \u003chttps://johannesbuchner.github.io/imagehash/art4.html\u003e`__ (or `with z-transform \u003chttps://johannesbuchner.github.io/imagehash/art10.html\u003e`__)\n* `colorhash \u003chttps://johannesbuchner.github.io/imagehash/art7.html\u003e`__\n* `average_hash \u003chttps://johannesbuchner.github.io/imagehash/art2.html\u003e`__ (`with z-transform \u003chttps://johannesbuchner.github.io/imagehash/art8.html\u003e`__)\n\nFor understanding hash distances, check out these excellent blog posts:\n* https://tech.okcupid.com/evaluating-perceptual-image-hashes-at-okcupid-e98a3e74aa3a\n* https://content-blockchain.org/research/testing-different-image-hash-functions/\n\nStoring hashes\n==============\n\nAs illustrated above, hashes can be turned into strings.\nThe strings can be turned back into a ImageHash object as follows.\n\nFor single perceptual hashes::\n\n\t\u003e\u003e\u003e original_hash = imagehash.phash(Image.open('tests/data/imagehash.png'))\n\t\u003e\u003e\u003e hash_as_str = str(original_hash)\n\t\u003e\u003e\u003e print(hash_as_str)\n\tffd7918181c9ffff\n\t\u003e\u003e\u003e restored_hash = imagehash.hex_to_hash(hash_as_str)\n\t\u003e\u003e\u003e print(restored_hash)\n\tffd7918181c9ffff\n\t\u003e\u003e\u003e assert restored_hash == original_hash\n\t\u003e\u003e\u003e assert str(restored_hash) == hash_as_str\n\nFor crop_resistant_hash::\n\n\t\u003e\u003e\u003e original_hash = imagehash.crop_resistant_hash(Image.open('tests/data/imagehash.png'), min_segment_size=500, segmentation_image_size=1000)\n\t\u003e\u003e\u003e hash_as_str = str(original_hash)\n\t\u003e\u003e\u003e restored_hash = imagehash.hex_to_multihash(hash_as_str)\n\t\u003e\u003e\u003e assert restored_hash == original_hash\n\t\u003e\u003e\u003e assert str(restored_hash) == hash_as_str\n\nFor colorhash::\n\n\t\u003e\u003e\u003e original_hash = imagehash.colorhash(Image.open('tests/data/imagehash.png'), binbits=3)\n\t\u003e\u003e\u003e hash_as_str = str(original_hash)\n\t\u003e\u003e\u003e restored_hash = imagehash.hex_to_flathash(hash_as_str, hashsize=3)\n\nEfficient database search\n-------------------------\n\nFor storing the hashes in a database and using fast hamming distance\nsearches, see pointers at https://github.com/JohannesBuchner/imagehash/issues/127\n(a blog post on how to do this would be a great contribution!)\n\n@KDJDEV points to https://github.com/KDJDEV/imagehash-reverse-image-search-tutorial and writes: \nIn this tutorial I use PostgreSQL and `this extension \u003chttps://github.com/fake-name/pg-spgist_hamming\u003e`_, \nand show how you can create a reverse image search using hashes generated by this library.\n\n\nChangelog\n----------\n\n* 4.3: typing annotations by @Avasam @SpangleLabs and @nh2\n\n* 4.2: Cropping-Resistant image hashing added by @SpangleLabs\n\n* 4.1: Add examples and colorhash\n\n* 4.0: Changed binary to hex implementation, because the previous one was broken for various hash sizes. This change breaks compatibility to previously stored hashes; to convert them from the old encoding, use the \"old_hex_to_hash\" function.\n\n* 3.5: Image data handling speed-up\n\n* 3.2: whash now also handles smaller-than-hash images\n\n* 3.0: dhash had a bug: It computed pixel differences vertically, not horizontally.\n       I modified it to follow `dHashref`_. The old function is available as dhash_vertical.\n\n* 2.0: Added whash\n\n* 1.0: Initial ahash, dhash, phash implementations.\n\nContributing\n=============\n\nPull requests and new features are warmly welcome.\n\nIf you encounter a bug or have a question, please open a GitHub issue. You can also try Stack Overflow.\n\nOther projects\n==============\n\n* https://github.com/commonsmachinery/blockhash-python\n* https://github.com/acoomans/instagram-filters\n* https://pippy360.github.io/transformationInvariantImageSearch/\n* https://www.phash.org/\n* https://pypi.org/project/dhash/\n* https://github.com/thorn-oss/perception (based on imagehash code, depends on opencv)\n* https://docs.opencv.org/3.4/d4/d93/group__img__hash.html\n\n.. |CI| image:: https://github.com/JohannesBuchner/imagehash/actions/workflows/testing.yml/badge.svg\n.. _CI: https://github.com/JohannesBuchner/imagehash/actions/workflows/testing.yml\n\n.. |Coveralls| image:: https://coveralls.io/repos/github/JohannesBuchner/imagehash/badge.svg\n.. _Coveralls: https://coveralls.io/github/JohannesBuchner/imagehash\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJohannesBuchner%2Fimagehash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJohannesBuchner%2Fimagehash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJohannesBuchner%2Fimagehash/lists"}