API
RegisterCore — Module
Core types and utilities for image registration mismatch computations.
Types
NumDenom: a packed(numerator, denominator)pair; supports vector-space arithmetic for use withInterpolations.jlMismatchArray: aCenterIndexedArrayofNumDenomelements representing mismatch over a range of shiftsPreprocessSNF: shot-noise–filtering image preprocessor (bias subtract, square-root transform, band-pass filter)ColonFun: callable singleton returningColon(), for type-stable slicing
Functions
separate: unpack aNumDenomorMismatchArrayinto(num, denom)arraysratio: convertNumDenomto a scalar ratio, with threshold maskingmaxshift: return the maximum-shift half-size of aMismatchArraymismatcharrays: pack array-of-arrays pairs into an array ofMismatchArraysargmin_mismatch: find the shift index of the minimum mismatchhighpass/highpass!: high-pass filter an image (Gaussian-based, NaN-safe)paddedview/trimmedview: extend/trim aSubArrayto/from its parent
Types
RegisterCore.NumDenom — Type
x = NumDenom(num, denom)A packed (num, denom) pair with element type T. Access fields as x.num and x.denom. Arguments of type Gray are automatically unwrapped; mismatched numeric types are promoted.
NumDenom objects act as 2-vectors under arithmetic — addition and scalar multiplication operate component-wise on both fields:
nd1 + nd2 → NumDenom(nd1.num + nd2.num, nd1.denom + nd2.denom)
nd1 - nd2 → NumDenom(nd1.num - nd2.num, nd1.denom - nd2.denom)
c * nd → NumDenom(c*nd.num, c*nd.denom)
nd / c → NumDenom(nd.num/c, nd.denom/c)This vector-space algebra (rather than ratio algebra) is intentional: it allows Interpolations.jl to interpolate numerator and denominator jointly without recomputing interpolation weights, enabling efficient aperture-windowed mismatch computations.
As a consequence, convert(Float64, ::NumDenom) is deliberately not defined, because the component-wise arithmetic breaks the ratio interpretation. Use ratio to convert to a scalar ratio.
RegisterCore.MismatchArray — Type
MismatchArray{ND,N,A}A CenterIndexedArray whose elements are NumDenom pairs, representing packed numerator/denominator mismatch data over a range of shifts.
The axes are centered at zero, so axes(D, k) runs from -maxshift(D)[k] to +maxshift(D)[k]; an index value of (i, j, ...) corresponds to a shift of (i, j, ...) pixels.
D = MismatchArray(num::AbstractArray, denom::AbstractArray)Pack same-size arrays num and denom into a MismatchArray with centered axes of half-size size(num) .÷ 2. Element type is NumDenom{promote_type(eltype(num), eltype(denom))}.
D = MismatchArray(T, dims::Dims)
D = MismatchArray(T, dims::Integer...)Allocate an uninitialized MismatchArray with element type NumDenom{T} and the given dimensions. Useful for pre-allocating output before filling with copyto!.
RegisterCore.ColonFun — Type
ColonFun()(i::Int) -> Colon()A callable singleton that returns Colon() for any integer argument. Used in place of Colon() directly where type-stable, composable slicing is needed (e.g., constructing index tuples programmatically).
RegisterCore.PreprocessSNF — Type
pp = PreprocessSNF(bias, sigmalp, sigmahp)Construct a shot-noise–filtered preprocessor. Call it as pp(img) to preprocess an image. All arguments are stored as Float32 (or Vector{Float32}), so Float64 inputs are silently converted.
The "SNF" name stands for "shot-noise filtered": this preprocessor is designed for photon-counting (Poisson) data, where the variance equals the mean.
Processing steps:
- Subtract
biasand clamp to zero:A′ = max(0, img - bias) - Square-root transform to stabilize variance:
A″ = √A′ - High-pass filter with Gaussian width
sigmahp(subtracts a low-pass Gaussian) - Low-pass filter with Gaussian width
sigmalp
sigmalp and sigmahp must each be a vector of length ndims(img). Pass sigmalp = zeros(ndims(img)) to skip low-pass filtering; pass sigmahp = fill(Inf, ndims(img)) to skip high-pass filtering.
When called on a SubArray, pp extends the view to the full parent (via paddedview) before processing, then trims the result back to the original index range (via trimmedview). This preserves any padding context around the sub-region.
If ImageMetadata is loaded, pp also accepts ImageMeta arrays and propagates image properties to the output.
MismatchArray functions
RegisterCore.argmin_mismatch — Function
index = argmin_mismatch(numdenom::MismatchArray, thresh::Real)
index = argmin_mismatch(r::CenterIndexedArray{<:Number})Return the CartesianIndex of the minimum mismatch, excluding edge points.
The first form operates on a MismatchArray: it computes num/denom at each interior point and finds the minimum among points where denom > thresh. The second form operates on a pre-computed ratio array r of plain numbers and finds the interior minimum unconditionally.
"Edge points" are the outermost index value on each side of every dimension; they are always excluded from consideration.
If no valid point is found (e.g., all denom ≤ thresh), returns a zero CartesianIndex — check for this case before using the result as an array index.
RegisterCore.maxshift — Function
mxs = maxshift(D::MismatchArray)Return the half-size of the MismatchArray D as a tuple of integers — i.e., the maximum shift (in pixels, per dimension) that was searched when computing the mismatch. Equivalent to D.halfsize.
RegisterCore.mismatcharrays — Function
mms = mismatcharrays(nums, denom::AbstractArray{<:Number})
mms = mismatcharrays(nums, denoms::AbstractArray{<:AbstractArray})Pack array-of-arrays (num, denom) pairs into an Array{MismatchArray}.
The first form uses the same denom array for every entry in nums. The second form pairs each nums[i] with the corresponding denoms[i]; nums and denoms must have the same size.
Returns an Array{MismatchArray} with the same shape as nums.
RegisterCore.ratio — Function
r = ratio(nd::NumDenom, thresh; fillval=NaN)
r = ratio(r::Real, thresh; fillval=NaN)Return the ratio nd.num/nd.denom, or fillval (converted to the ratio type) when nd.denom < thresh. Setting thresh = 0 always returns the ratio.
The second form accepts a plain Real and returns it unchanged, regardless of thresh and fillval — thresh and fillval are silently ignored. This allows callers to handle both NumDenom and pre-computed ratio arrays uniformly without branching on the element type.
RegisterCore.separate — Function
num, denom = separate(data::AbstractArray{NumDenom{T}})
num, denom = separate(mm::MismatchArray)
nums, denoms = separate(mma::AbstractArray{<:MismatchArray})Split packed NumDenom data into separate numerator and denominator arrays.
- For a plain
AbstractArray{NumDenom{T}}, returns a pair ofArray{T}with the same size and linear indexing asdata. - For a
MismatchArray, returns a pair ofCenterIndexedArray{T}, preserving the centered axes (so index ranges correspond to shift values). - For an array of
MismatchArrays, returns a pair ofArray{CenterIndexedArray{T}}.
Utility functions
RegisterCore.highpass — Function
datahp = highpass([T], data, sigma)
highpass!(out, data, sigma)
highpass!(data, sigma)Return (or write in-place) a high-pass–filtered version of data with negative values clamped to zero. The high-pass is computed by subtracting a Gaussian-smoothed copy of data (via ImageFiltering.jl), which gracefully handles NaN values.
sigma must be an iterable (e.g., a tuple or vector) with one width per dimension of data. To skip filtering along a particular axis, set the corresponding entry to Inf (the input is then returned as-is, converted to Array{T}, with no subtraction or clamping applied).
For highpass, the optional first argument T sets the element type of the output:
highpass(T, data, sigma)— allocates an output of element typeThighpass(data, sigma)—Tdefaults toeltype(data)forAbstractFloatinputs, orFloat32forInteger/FixedPointinputs
For highpass!, the output element type is eltype(out):
highpass!(out, data, sigma)— writes result intoout;outanddatamay be distinct arrays (useful for pre-allocated buffers in hot loops)highpass!(data, sigma)— filtersdatain-place
See also PreprocessSNF for a combined shot-noise–filtering preprocessor.
RegisterCore.highpass! — Function
highpass!(out, data, sigma)
highpass!(data, sigma)In-place variant of highpass. See that function for full documentation.
RegisterCore.paddedview — Function
Apad = paddedview(A::SubArray)Return a SubArray of A's parent that extends to the full parent size along every dimension of A that was indexed by a UnitRange. Dimensions indexed by a scalar are still dropped (as usual for SubArray), and dimensions indexed by a Slice are unchanged.
Only Slice, Real, and UnitRange index types are supported; any other index type throws an error.
See also trimmedview.
RegisterCore.trimmedview — Function
B = trimmedview(Bpad::AbstractArray, A::SubArray)Return a view B of Bpad with axes(B) == axes(A).
Bpad must be an AbstractArray with the same size as paddedview(A) — typically it is the result of an operation applied to paddedview(A). Dimensions of A that were indexed by a scalar are skipped (they are dropped in A); all other dimensions are sliced with the original index range from A.
See also paddedview.