Skip to main content

chess_response_u8

Function chess_response_u8 

Source
pub fn chess_response_u8(
    img: &[u8],
    w: usize,
    h: usize,
    params: &ChessParams,
) -> ResponseMap
Expand 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_abs = Some(0.0) combined with a strict comparison in crate::detect::detect_corners_from_response. The optional threshold_rel / threshold_abs fields are adaptive policies layered on top of the paper’s score — they are 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_u8 uses a straightforward nested for y { for x { ... } } scalar loop and relies on the compiler’s auto‑vectorization in release builds.
  • With the rayon feature, the work is split into independent row slices and processed in parallel using rayon::par_chunks_mut.
  • With the simd feature, the inner loop over x is rewritten to operate on LANES pixels at a time using portable SIMD vectors (currently 16 lanes of u8). The ring samples are gathered into SIMD registers, SR/DR/μₙ are accumulated in integer vectors, and the final response is written back per lane.
  • With both rayon and simd enabled, 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.