{"id":2067,"library":"imagehash","title":"ImageHash","description":"ImageHash is a Python library that provides tools for generating perceptual hash values for images. These hashes can be used to compare images based on their visual content, making it useful for finding similar or duplicate images. It supports various hashing algorithms like aHash, pHash, dHash, wHash, colorhash, and crop-resistant hashing. The current version is 4.3.2, and it receives updates periodically to add features, improve performance, and address bugs. [1, 3, 8]","status":"active","version":"4.3.2","language":"en","source_language":"en","source_url":"https://github.com/JohannesBuchner/imagehash","tags":["image hashing","perceptual hashing","image comparison","duplicate image detection","computer vision","PIL","Pillow"],"install":[{"cmd":"pip install Pillow imagehash","lang":"bash","label":"Install with Pillow dependency"}],"dependencies":[{"reason":"Required for image loading and manipulation. ImageHash operates on PIL/Pillow Image objects. [1, 2, 3, 5]","package":"Pillow"},{"reason":"Required for numerical operations underlying various hashing algorithms. [2, 3, 5]","package":"numpy"},{"reason":"Required for `fftpack` (used by pHash) and other scientific computing functions. [2, 3, 5]","package":"scipy"},{"reason":"Required specifically for the Wavelet Hashing (whash) algorithm. [5]","package":"PyWavelets"}],"imports":[{"symbol":"Image","correct":"from PIL import Image"},{"symbol":"imagehash","correct":"import imagehash"}],"quickstart":{"code":"from PIL import Image\nimport imagehash\nimport os\n\n# Create a dummy image for demonstration if not available\ndummy_image_path = 'dummy_image.png'\nif not os.path.exists(dummy_image_path):\n    try:\n        from PIL import ImageDraw\n        img = Image.new('RGB', (200, 200), color = 'red')\n        d = ImageDraw.Draw(img)\n        d.text((10,10), \"Hello\", fill=(0,0,0))\n        img.save(dummy_image_path)\n        print(f\"Created dummy image: {dummy_image_path}\")\n    except ImportError:\n        print(\"Pillow is needed to create a dummy image. Please install it.\")\n        exit()\n\ntry:\n    # Load an image\n    image = Image.open(dummy_image_path)\n\n    # Generate a perceptual hash (e.g., average hash)\n    hash_value = imagehash.average_hash(image)\n    print(f\"Hash for '{dummy_image_path}': {hash_value}\")\n\n    # You can also generate other types of hashes:\n    # phash_value = imagehash.phash(image)\n    # dhash_value = imagehash.dhash(image)\n    # whash_value = imagehash.whash(image)\n    # colorhash_value = imagehash.colorhash(image)\n\n    # To compare with another image:\n    # For demonstration, let's pretend to load a slightly different image\n    # In a real scenario, this would be another actual image file\n    slightly_different_image = Image.new('RGB', (200, 200), color = 'red')\n    d = ImageDraw.Draw(slightly_different_image)\n    d.text((15,15), \"Hello\", fill=(0,0,0)) # slight shift\n    \n    other_hash_value = imagehash.average_hash(slightly_different_image)\n    print(f\"Hash for a slightly different image: {other_hash_value}\")\n\n    # Calculate the Hamming distance (difference) between hashes\n    difference = hash_value - other_hash_value\n    print(f\"Difference between hashes: {difference}\")\n\n    # A smaller difference indicates greater similarity\n    if difference < 5:\n        print(\"The images are considered similar (difference < 5).\")\n    else:\n        print(\"The images are considered different (difference >= 5).\")\n\nexcept FileNotFoundError:\n    print(f\"Error: Image file not found at {dummy_image_path}\")\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\n","lang":"python","description":"This quickstart demonstrates how to load an image using Pillow, generate an average perceptual hash using `imagehash.average_hash`, and compare it to another hash by calculating their Hamming distance. A smaller difference typically indicates greater visual similarity. [1, 3, 8, 14]"},"warnings":[{"fix":"To convert hashes from the old encoding to the new format, use the `imagehash.old_hex_to_hash` function.","message":"Version 4.0 introduced a change in the binary to hex implementation for hashes, breaking compatibility with hashes generated by previous versions. [3, 6]","severity":"breaking","affected_versions":">=4.0"},{"fix":"If you relied on the previous (buggy) vertical difference calculation, use `imagehash.dhash_vertical` which retains the old behavior. Otherwise, `dhash` now works as intended.","message":"Version 3.0 fixed a bug in the `dhash` algorithm where it computed pixel differences vertically instead of horizontally. The corrected `dhash` behavior now follows the standard. [3, 6, 16]","severity":"breaking","affected_versions":">=3.0"},{"fix":"Convert NumPy arrays to PIL Image objects before passing them to ImageHash functions using `Image.fromarray(numpy_array)`.","message":"ImageHash functions expect a `PIL.Image.Image` object as input. Passing a NumPy array directly (e.g., from OpenCV) will result in an `AttributeError` because NumPy arrays do not have `convert` or `resize` methods expected by the library. [19]","severity":"gotcha","affected_versions":"All"},{"fix":"Always verify the `requests` response's status code (`resp.status_code`) and content type before attempting to open it as an image. You might also need to read `resp.content` into a `BytesIO` object for `Image.open()`.","message":"When loading images from URLs using libraries like `requests`, directly passing `resp.raw` to `Image.open()` can fail if the URL does not return raw image bytes (e.g., an HTML error page instead of an image). [21]","severity":"gotcha","affected_versions":"All"},{"fix":"Experiment with different threshold values on your specific dataset to find what best defines 'similar' for your application. There's no one-size-fits-all value.","message":"Determining an appropriate 'similarity threshold' (Hamming distance) for comparing hashes is empirical and highly dependent on the use case. A smaller difference indicates more similarity. Common recommendations range from 1 to 10 for 'similar' images. [1, 14]","severity":"gotcha","affected_versions":"All"},{"fix":"For robust matching against such transformations, consider preprocessing images to normalize them (e.g., consistent sizing, minor rotations corrected) or use more advanced techniques like crop-resistant hashing if available and suitable for your specific deformation types.","message":"Significant image transformations like extensive cropping, rotations beyond 15 degrees, or substantial color adjustments can drastically alter perceptual hashes, potentially making perceptually similar images appear completely different. [14, 22]","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}