pub fn chess_response_u8(
img: &[u8],
w: usize,
h: usize,
params: &ChessParams,
) -> ResponseMapExpand description
Compute the dense ChESS response for an 8-bit grayscale image.
The response at each valid pixel center is computed from a 16‑sample ring
around the pixel and a 5‑pixel cross at the center. For a given center
c, let s[0..16) be the ring samples in the canonical order:
-
SR(sum of “square” responses) compares four opposite quadrants on the ring:SR = sum_{k=0..3} | (s[k] + s[k+8]) - (s[k+4] + s[k+12]) | -
DR(sum of “difference” responses) enforces edge‑like structure:DR = sum_{k=0..7} | s[k] - s[k+8] | -
μₙis the mean of all 16 ring samples. -
μₗis the local mean of the 5‑pixel cross at the center (c,north,south,east,west).
The final ChESS response is:
R = SR - DR - 16 * |μₙ - μₗ|where high positive values correspond to chessboard‑like corners.
§Score contract
R is the unnormalized ChESS response defined by Bennett and
Lasenby (2014). The units are 8-bit pixel sums — not normalized
to [0, 1], not divided by a local scale, not divided by the
scene max. Every term is linear in the pixel values, so with 8-bit
input R is bounded by SR − DR − 16·MR ∈ [−24·255, 8·255]
(≈ [−6120, 2040]); in practice chessboard corners produce scores
well below that upper bound.
The paper’s acceptance criterion is simply R > 0. That is what
ChessParams::default() encodes via threshold = 0.0
combined with a strict comparison in
crate::detect_corners_from_response. The threshold field is an
absolute floor layered on top of the paper’s score — a
convenience for trading off sensitivity vs false positives, not part
of the score definition.
§Implementation strategy
Internally the image is processed row‑by‑row, but only pixels whose
full ring lies inside the image bounds are evaluated; border pixels
are left at zero in the returned ResponseMap.
- Without any features,
chess_response_u8uses a straightforward nestedfor y { for x { ... } }scalar loop and relies on the compiler’s auto‑vectorization in release builds. - With the
rayonfeature, the work is split into independent row slices and processed in parallel usingrayon::par_chunks_mut. - With the
simdfeature, the inner loop overxis rewritten to operate onLANESpixels at a time using portable SIMD vectors (currently 16 lanes ofu8). The ring samples and the 5‑pixel local-mean cross are gathered into SIMD registers,SR/DR/μₙ/μₗare accumulated in vector lanes, and the final response is stored a full vector at a time. - With both
rayonandsimdenabled, each row is processed in parallel and each row uses the SIMD‑accelerated inner loop.
All feature combinations produce the same output values (within a small tolerance for floating‑point rounding), and differ only in performance characteristics.
§Panics
Panics if img.len() != w * h.