Expand description
Median threshold bitmap alignment for handheld HDR exposures.
Ward (2003). Thresholding each exposure at its own median gives a bitmap that survives any monotonic change of exposure, so frames can be registered before the camera response is solved. Integer translation only.
use mtb_align::{Gray, Options, Shift, shift};
let scene = |x: i64, y: i64| (((x / 16) * 61) ^ ((y / 16) * 37)) as u8;
let read = |dx: i64, dy: i64| {
let samples = (0..256 * 256).map(|i| scene(i % 256 + dx, i / 256 + dy)).collect();
Gray::from_vec(samples, 256, 256)
};
let options = Options { bits: 4, ..Options::default() };
assert_eq!(shift(&read(0, 0), &read(5, -3), &options), Ok(Shift::new(5, -3)));align_stack does a whole bracket, common_crop the region left over.
Structs§
- Bitmap
- A one-bit-per-pixel image, least-significant bit first, each row padded to a word boundary so a shift never crosses a row. Ward flattens it instead.
- Bitmaps
- One exposure reduced to the two bitmaps the search compares. They travel together: the exclusion bitmap only means anything against its own threshold.
- Gray
- A single-channel 8-bit image: row-major samples carried with their dimensions.
- Options
- How the search is run.
- Percentile
- Which population split the threshold bitmap is cut at. Ward uses the median, falling back to the 17th or 83rd for exposures too dark or light for it.
- Rect
- A region of an image, in pixels from the top left.
- Shift
- How far the target image has to move to sit on top of the reference.
Enums§
- Error
- What can be wrong with a set of exposures.
- Shrink
- How a level of the pyramid is halved. Ward’s table calls
ImageShrink2a subsample; his text says “filtered down”. Both readings are available.
Functions§
- align_
stack - How far each exposure has to move to sit on
images[reference], measured between adjacent exposures and accumulated: one percentile fits two neighbours well and the ends of a bracket badly. - common_
crop - The region every exposure still covers once moved. What OpenCV’s
cuttrims to: outside it some frame contributes only padding. - compute_
bitmaps - Reduces one exposure to its threshold and exclusion bitmaps.
- disagreement
- Ward’s
BitmapTotalof(tb1 XOR shift(tb2)) AND eb1 AND shift(eb2), counted without materialising any of it. The exclusion terms mask the result of the XOR, never its operands — his footnote 4. - shift
- How far
targethas to move to sit on top ofreference. - shrink2
- Halves a plane, dropping an odd final row or column.
- threshold
- The sample value the bitmaps are cut at. A
u16because it can land one past the range: an image of nothing but 255s gives 256, as it does in OpenCV.