High-performance Python port of mapbox/pixelmatch for perceptual image comparison
Project description
pixelmatch-fast
High-performance Python port of mapbox/pixelmatch for image comparison.
Pixelmatch is a tool that automatically highlights differences between two images while ignoring anti-aliasing artifacts. For more information about pixelmatch capabilities and examples, see the mapbox/pixelmatch repository.
Installation
Install Python (v3.10 or higher) and install the package:
pip install pixelmatch-fast
CLI Usage
$ pixelmatch --help
Usage: pixelmatch [OPTIONS] IMG1 IMG2
Compare two images pixel-by-pixel and visualize differences.
Options:
--version Show the version and exit.
-o, --output PATH Path to save diff image (PNG format)
-t, --threshold FLOAT Matching threshold (0 to 1); smaller is more
sensitive [default: 0.1]
--include-aa Count anti-aliased pixels as different
-a, --alpha FLOAT Opacity of original image in diff output [default:
0.1]
--aa-color TEXT Color of anti-aliased pixels (R,G,B) [default:
255,255,0]
--diff-color TEXT Color of different pixels (R,G,B) [default: 255,0,0]
--diff-color-alt TEXT Alternative color to differentiate between "added" and "removed" parts (R,G,B)
--diff-mask Draw diff over transparent background
--help Show this message and exit.
Example (using test images from the mapbox/pixelmatch repository):
$ pixelmatch 1a.png 1b.png -o diff.png
Mismatched pixels: 106
The CLI exits with code 0 if images match and 1 if they differ (i.e., one or more mismatched pixels).
Library Usage
from pixelmatch import pixelmatch
# Compare two images and get mismatch count
num_diff = pixelmatch(
"image1.png",
"image2.png",
output="diff.png", # Optional: save diff image
)
print(f"Found {num_diff} mismatched pixels")
Arguments
img1,img2— Image paths (str or Path) or PIL Image objects to compare. Note: image dimensions must be equal.output— Image output for the diff. Can be a file path (str or Path) to save as PNG, a PIL Image object to fill with diff data, orNoneif diff output is not needed.threshold— Matching threshold, ranges from0to1. Smaller values make the comparison more sensitive.0.1by default.includeAA— Whether to count anti-aliased pixels as different.Falseby default.alpha— Blending factor of unchanged pixels in the diff output. Ranges from0for pure white to1for original brightness.0.1by default.aa_color— Tuple of(R, G, B)color for anti-aliased pixels in diff output.(255, 255, 0)(yellow) by default.diff_color— Tuple of(R, G, B)color for different pixels in diff output.(255, 0, 0)(red) by default.diff_color_alt— Tuple of(R, G, B)for an alternative color to use for dark on light differences to differentiate between "added" and "removed" parts. If not provided, all differing pixels usediff_color.diff_mask— Draw the diff over a transparent background (a mask), rather than over the original image.Falseby default.
Similar Projects
- mapbox/pixelmatch: The original pixelmatch implementation (JavaScript).
- pixelmatch-py: A pure-Python port with no dependencies. Best for environments where speed isn't critical or where you cannot install heavy libraries.
- pybind11-pixelmatch: Python bindings for the C++ port of pixelmatch. Offers the highest raw performance but may require a C++ compiler if wheels aren't available for your platform and can encounter issues with modern installers like
uv.
Performance Comparison
Test conditions: 500×100 RGBA images, Python 3.11.2.
| Variant | Cold Start | Warm Start (JIT) | Relative Speed |
|---|---|---|---|
| mapbox/pixelmatch (JS) | 139 ms | 113 ms | 1.00x |
| pixelmatch-py | 12,397 ms | 12,216 ms | 0.01x |
| pybind11-pixelmatch | 88 ms | 81 ms | 1.40x |
| pixelmatch-fast | 1972 ms | 101 ms | 1.12x |
Why is the warm start faster?
pixelmatch-fast leverages numba for Just-In-Time (JIT) compilation. The "Cold Start" includes the one-time overhead of Numba compiling the Python code into optimized machine code. Subsequent "Warm Start" executions run at full compiled speed.
Why choose pixelmatch-fast?
While pybind11-pixelmatch is faster, pixelmatch-fast tries to stay up to date with the current mapbox/pixelmatch version (currently v7.1.0), provides a more Pythonic experience and is compatible with modern tooling like uv. It delivers a 100x speedup over the pure-Python baseline without the complexities of C++ extensions.
Development
Install uv. Then, install dependencies & activate the automatically generated virtual environment:
uv sync --locked
source .venv/bin/activate
Skip --locked to use the newest dependencies (this might modify uv.lock)
Testing
Run tests:
pytest
Run tests with coverage (disables numba JIT compilation):
NUMBA_DISABLE_JIT=1 pytest --cov
Quality Assurance (QA)
Automatically run code quality checks before every commit using pre-commit:
pre-commit install
This installs git hooks that run ruff, type checks, and other checks before each commit. You can run manually at any time with:
pre-commit run --all-files
The CI workflow automatically runs tests both with and without numba enabled, ensuring both the optimized and fallback code paths are tested.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pixelmatch_fast-1.3.2.tar.gz.
File metadata
- Download URL: pixelmatch_fast-1.3.2.tar.gz
- Upload date:
- Size: 1.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5e9b722d755596eedc6bf8e0ded2b867d4984b366621282daecaf858e5888fd
|
|
| MD5 |
ece546986c012316d795b2797de70139
|
|
| BLAKE2b-256 |
48a6b9bdb57f18defc2bf9b4e5d945f03ad98378f2ca410de0353d600960c245
|
Provenance
The following attestation bundles were made for pixelmatch_fast-1.3.2.tar.gz:
Publisher:
pypi-publish.yml on JustusRijke/pixelmatch-fast
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pixelmatch_fast-1.3.2.tar.gz -
Subject digest:
e5e9b722d755596eedc6bf8e0ded2b867d4984b366621282daecaf858e5888fd - Sigstore transparency entry: 832782239
- Sigstore integration time:
-
Permalink:
JustusRijke/pixelmatch-fast@72c0ebef2cda35e06f1b94c5e8f62741d5d11831 -
Branch / Tag:
refs/tags/1.3.2 - Owner: https://github.com/JustusRijke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@72c0ebef2cda35e06f1b94c5e8f62741d5d11831 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pixelmatch_fast-1.3.2-py3-none-any.whl.
File metadata
- Download URL: pixelmatch_fast-1.3.2-py3-none-any.whl
- Upload date:
- Size: 9.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
195876155e7ccb4e174688e14df34653aa20b5ce4d35c53135ddcf4bd361dfc5
|
|
| MD5 |
ba34087ff843c1f6e4fa1c774322e03a
|
|
| BLAKE2b-256 |
3e47e90de1e1684ec37ca2c3cd97698751d3ea8bab5ebec174c5bfd2ce977e12
|
Provenance
The following attestation bundles were made for pixelmatch_fast-1.3.2-py3-none-any.whl:
Publisher:
pypi-publish.yml on JustusRijke/pixelmatch-fast
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pixelmatch_fast-1.3.2-py3-none-any.whl -
Subject digest:
195876155e7ccb4e174688e14df34653aa20b5ce4d35c53135ddcf4bd361dfc5 - Sigstore transparency entry: 832782240
- Sigstore integration time:
-
Permalink:
JustusRijke/pixelmatch-fast@72c0ebef2cda35e06f1b94c5e8f62741d5d11831 -
Branch / Tag:
refs/tags/1.3.2 - Owner: https://github.com/JustusRijke
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@72c0ebef2cda35e06f1b94c5e8f62741d5d11831 -
Trigger Event:
release
-
Statement type: