matching op• Data kinds: image2d × image2d → image2d
• Call: import fullseye as fs; fs.ledger.histogram_match(src, ref, bins=None, ties='average') (to call the implementation directly, import colortransport; colortransport.histogram_match(src, ref, bins=None, ties='average'); from the registry, opscolortransport.get("histogram_match"))
Match the value distribution of src to ref (exact 1-D optimal transport).
It replaces values with the reference's quantiles while preserving rank. Specifying bins approximates with the cumulative distribution at that many levels -- faster but no longer exact, so the default is None (exact).
How pixels with equal values are handled changes the meaning of the picture. For a monotone mapping, "equal inputs map to equal outputs" should hold, but naively replacing by rank tears equal values apart. Measured (an integer image with 4 pixels of value 2): the output split into the 4 values 0.2222 / 0.3333 / 0.4444 / 0.5556. That is, tones that were not in the original picture sprout in what was a flat region. Integer images are full of equal values, so this is the norm, not an exception.
• ties="average" (default) -- pixels with equal values are given, of the reference values assigned to them, the mean. Equal inputs map to equal outputs, and monotonicity is preserved. In exchange, the output distribution no longer matches the reference exactly (for each clump of equal values, the distribution is rounded into steps). For continuous input (no equal values) it stays an exact match.
• ties="break" -- tears them apart by raw rank. The output distribution matches the reference exactly, but false tones appear in flat areas. Only when the goal is matching the distribution exactly and you know you will not look at it as a picture.
Either choice loses something (exactness of the distribution or flatness of flat areas), so it is an argument rather than silently picking one.
Applied as is to a multi-channel picture, it breaks the correlation between channels. Each axis's marginal distribution matches, but the colour combinations can become ones that were not in the original. To transport the correlation as well, use method="gaussian" of color_transfer.
• colorimetry — Colorimetry and spectra — colour is fixed only by spectrum × illuminant × observer
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• The canonical algorithm (author, year) and its uses are named in the family usage guide above.
• color_transport — py -3.11 examples/color_transport.py
• poc_change_detection_misreg — py -3.11 examples/poc_change_detection_misreg.py
image2d as input)matching)color_transfer · gaussian_transport_map
*Provenance: colortransport.py — COLORTRANSPORT operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.