Expand description
Dense image correspondence: given two photographs of the same scene, work out where each pixel of the first one went in the second.
This is 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 — the pixelmap_model_3d crate in the
repository lifts a finished mapping into a textured 3D mesh.
§What it produces
Two views of the same statue (top) and the correspondence recovered between them, rendered at three settings (bottom). Regions left blank are those with no accepted match.
§Quick start
use pixelmap::{Correspondence, Photo, Quality};
let (w, h, rgba) = decode("a.jpg");
let a = Photo::from_rgba(w, h, rgba)?;
let (w, h, rgba) = decode("b.jpg");
let b = Photo::from_rgba(w, h, rgba)?;
let mapping = Correspondence::builder().quality(Quality::Low).run(a, b)?;
// Where did the pixel at (120, 84) end up?
match mapping.lookup(120.0, 84.0) {
Some((x, y)) => println!("({x:.1}, {y:.1})"),
None => println!("not mapped here"),
}§The contract
Input. Both photos must have the same dimensions and be at least
MIN_DIMENSION on each side. Violations come back as an Error, never a panic.
Output. Correspondence::lookup answers in the coordinates of the photos you
passed in. Underneath, the solver works at a reduced resolution and the two
DensePhotoMaps reached through Correspondence::forward and
Correspondence::backward are in that space; Correspondence::working_scale
relates the two. Regions the algorithm could not map — occlusions, featureless sky,
anything the consistency check rejected — are reported as None rather than as a
sentinel value.
Determinism. The order in which the solver drains its queue decides which local
optimum the relaxation settles into, so it is seeded, and the seed defaults to
DEFAULT_SEED. The same photos, schedule and seed give the same mapping — run to
run, thread to thread, and machine to machine. Use Builder::seed to vary it.
Enabling or disabling the parallel feature does not change the result.
Threading. Everything the caller holds is Send + Sync, so a mapping can be
computed on a worker thread and the result shared afterwards.
Cost. Roughly linear in pixels at the working resolution, times the number of
schedule steps. See Quality.
§Feature flags
parallel(default) — multi-threaded feature matching via rayon. Turn it off forwasm32-unknown-unknown, which has no threads to hand out; the matcher falls back to a serial search with the same result.image—From<image::RgbaImage>andFrom<image::DynamicImage>forPhoto.bench— compiles the matcher benchmark harness. Not part of the pipeline.
Re-exports§
pub use correspondence::correspond;pub use correspondence::Builder;pub use correspondence::Correspondence;pub use correspondence::Progress;pub use dense_photo_map::DensePhotoMap;pub use error::DecodeError;pub use error::Error;pub use photo::Photo;pub use photo::MIN_DIMENSION;pub use pixelmap_processor::PixelMapProcessor;pub use pixelmap_processor::DEFAULT_SEED;pub use processing_mode::IterationParams;pub use processing_mode::ParseProcessingModeError;pub use processing_mode::ProcessingMode;pub use processing_mode::Quality;
Modules§
- correspondence
- The crate’s entry point: run the pipeline over a pair of photos and hold the result.
- dense_
photo_ map - The dense correspondence grid produced by a run, and the operations over it.
- error
- The errors the crate’s fallible operations return.
- photo
- The crate’s image type: a plain RGBA byte buffer with its dimensions.
- pixelmap_
processor - The pipeline driver behind
crate::Correspondence. - processing_
mode - Ready-made iteration schedules for
PixelMapProcessor.