Skip to main content

pixelmap-python

PyPI Python versions License: MIT

Dense image correspondence: given two photographs of the same scene, work out where each pixel of the first one went in the second.

Python bindings for the pixelmap Rust crate, the reference implementation of the PIXELMAP framework (white paper). Every cell of an affine correspondence grid acts as an autonomous agent holding its own local affine transform; agents refine their transform against the image data and propagate what they find to their neighbours, and a forward/backward consistency check culls the ones that disagree. Repeating that coarse-to-fine yields a dense, geometrically consistent mapping.

Useful for optical flow, image registration and stitching, stereo matching, morphing, and as the front half of a 3D reconstruction.

PIXELMAP applied to two photos of a monkey statue

Install

pip install pixelmap-python

The package installs as pixelmap-python but imports as pixelmap — PyPI will not accept pixelmap as a distribution name, because it collides with the unrelated pixel-map project under PyPI's similarity rule.

Wheels are published for Linux (x86-64, aarch64, musl), macOS (Apple silicon and Intel) and Windows (x86-64), for CPython 3.9 and newer. NumPy is the only runtime dependency; no Rust toolchain is needed unless you build from source.

Quick start

import numpy as np
import pixelmap
from PIL import Image

a = np.asarray(Image.open("a.jpg").convert("RGB"))
b = np.asarray(Image.open("b.jpg").convert("RGB"))  # same dimensions as a

mapping = pixelmap.correspond(a, b, quality="low")

flow = mapping.flow()  # (H, W, 2) float32: how far each pixel moved
print(f"{mapping.coverage:.1%} of the image was mapped")

# Where did the pixel at (120, 84) end up?
print(mapping.lookup(120.0, 84.0))  # (114.2, 80.6), or None if unmapped

flow[y, x] is (dx, dy) in the source photos' own pixel coordinates. Regions the algorithm could not map — occlusions, featureless sky, anything the consistency check rejected — are NaN rather than a plausible-looking coordinate:

unmapped = np.isnan(flow[..., 0])

Coverage well below 1.0 is normal and not a failure. A very low value means the two photos had little in common, or are related by something an affine grid cannot express.

Warping one photo onto the other

flow(absolute=True) returns destination coordinates instead of displacements, which is what OpenCV's remap wants:

import cv2

dst = mapping.flow(absolute=True)
warped = cv2.remap(a, dst[..., 0], dst[..., 1], cv2.INTER_LINEAR)

There is also a built-in morph, which interpolates the first photo t of the way towards the second:

halfway = mapping.morph(0.5, detail=2)  # (h, w, 4) uint8, at working resolution

Watching a long run

mapping = pixelmap.correspond(
    a,
    b,
    quality=pixelmap.Quality.HIGH,
    progress=lambda step, total: print(f"{step}/{total}"),
)

The GIL is released while the solver runs, so correspond can be called from a worker thread without blocking the rest of your program.

API

correspond(photo1, photo2, *, quality, seed, max_round_trip_error, progress) Run the pipeline.
Correspondence.flow(*, backward=False, absolute=False) The dense field as (H, W, 2) float32.
Correspondence.lookup(x, y, *, backward=False) One point, or NumPy arrays of them.
Correspondence.morph(t, *, detail=1) The first photo warped towards the second.
Correspondence.coverage Fraction of the image that got a mapping.
Correspondence.comparisons Region comparisons performed.
Correspondence.source_dimensions / .working_dimensions / .working_scale Geometry.
Correspondence.to_bytes() / .from_bytes(data, photo1, photo2) Save and reload a mapping.
Quality.LOW / .MEDIUM / .HIGH Presets, or the equivalent strings.

Input. Photos are uint8 arrays of shape (H, W), (H, W, 1), (H, W, 3) or (H, W, 4) — Pillow images work directly. Both must have the same dimensions and be at least 32 pixels on each side. Violations raise SizeMismatchError, PhotoTooSmallError or ValueError, all of which are ValueError subclasses.

Quality. LOW, MEDIUM and HIGH run 4, 10 and 13 refinement steps and finish at a working width of 400, 800 and 1600 pixels respectively, so cost grows faster than the step count suggests. flow and lookup answer in your photos' coordinates regardless; use working_scale if you need to reason about the solver's effective resolution.

Determinism. The same photos, quality and seed give the same mapping — run to run, thread to thread, and machine to machine. Pass seed= to vary it.

Building from source

Requires Rust 1.83 or newer.

git clone https://github.com/d4per/pixelmap-python
cd pixelmap-python
pip install maturin
maturin develop --release
pytest

maturin develop without --release builds an unoptimised solver that is many times slower; use it only for iterating on the bindings themselves.

See also

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pixelmap_python-0.1.0.tar.gz (25.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pixelmap_python-0.1.0-cp39-abi3-win_amd64.whl (253.1 kB view details)

Uploaded CPython 3.9+Windows x86-64

pixelmap_python-0.1.0-cp39-abi3-musllinux_1_2_x86_64.whl (586.7 kB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ x86-64

pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (375.0 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (368.8 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

pixelmap_python-0.1.0-cp39-abi3-macosx_11_0_arm64.whl (334.4 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

pixelmap_python-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl (345.1 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file pixelmap_python-0.1.0.tar.gz.

File metadata

  • Download URL: pixelmap_python-0.1.0.tar.gz
  • Upload date:
  • Size: 25.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pixelmap_python-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4c4fe356189c5401dc244a2940f62ce432d1efe3d0a180d39a739ad011709580
MD5 1ca68f03d8626af0afd35620abba94cd
BLAKE2b-256 013db2ccdaeda6c62ff48cd3c086ed7551baf4c301813b02aeae91de6b2b6dbe

See more details on using hashes here.

Provenance

The following attestation bundles were made for pixelmap_python-0.1.0.tar.gz:

Publisher: release.yml on d4per/pixelmap-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pixelmap_python-0.1.0-cp39-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for pixelmap_python-0.1.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 34503721696663b984884139f065cfaaba41dca2f8ad26149267ec59a33434ff
MD5 911bd1beaaae9a107d7d233d89657ac0
BLAKE2b-256 06004d869b25827fd5dcbdfbd6ea72cb728cc479624d16796a7221dc6b2480eb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pixelmap_python-0.1.0-cp39-abi3-win_amd64.whl:

Publisher: release.yml on d4per/pixelmap-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pixelmap_python-0.1.0-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pixelmap_python-0.1.0-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 dc7b0d2d5e0e019423a86c983f942491cccd0dfbf6283a562e8256b05d1e9c1a
MD5 8ab2ba82b5277c2bc777d173d214b31c
BLAKE2b-256 bd364502174b1a61cc20514825644d9a04d4ae48479667a366007b534ae4a3f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pixelmap_python-0.1.0-cp39-abi3-musllinux_1_2_x86_64.whl:

Publisher: release.yml on d4per/pixelmap-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a861fa57218ac9e5439765b4da503378dd77862613880c46d48558e5a7f48e44
MD5 47fab0e99f74260f6844d86fbc857889
BLAKE2b-256 ff15aeb4fe843392372690b108734c7c829956507c90da87d5096156ee7516a2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on d4per/pixelmap-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e931873f281a3f599bc2fe5fc3eb0fad43bd44c3815eeee3edb6c2f106c91ec1
MD5 3613afd1f463fa92d04c343bd09c3627
BLAKE2b-256 4700ce646f2bec35f7bb776bc891418e90cdbbf773d1002a8cd1e5c849f6e395

See more details on using hashes here.

Provenance

The following attestation bundles were made for pixelmap_python-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on d4per/pixelmap-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pixelmap_python-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pixelmap_python-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d7539fd06ba12bcc3a28e230a06ed1a1561ece040e1d87c3382fd982d67f0e1e
MD5 3fe6c90efe08e9784fe6997586417549
BLAKE2b-256 05b888e1a201babb17207610fd6dd8d903011db6f91502e524fc1cfa49e8b54b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pixelmap_python-0.1.0-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on d4per/pixelmap-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pixelmap_python-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pixelmap_python-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 5484839f0bfb33f7650da87b985dec544c4ac7319660c8c67e6dbb9e9940162c
MD5 05d1a74430422d7744986ffbb1fc680f
BLAKE2b-256 2f5690d9ec044ff18a16ff0bb8e3e9cc15b1e3051c228ffd9809faeb525816d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pixelmap_python-0.1.0-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on d4per/pixelmap-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

7 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page