local_percentile_core#
Fast 2D percentile on uint16 images using a sliding histogram window.
Why this exists#
- For lightsheet correction background estimation you use:
selem = (200, 200, 1)
step = (2, 2, 1)
spacing = (25, 25, 1) with interpolation
- The original Python/Numpy implementation tends to:
reallocate per center
recompute overlapping regions
call np.percentile repeatedly
- This Cython implementation:
maintains a histogram (size = max_bin + 1)
slides the window along x, updating by removing/adding columns
updates to next row by removing/adding rows
computes percentile from the histogram in O(max_bin) worst case, but typically max_bin is 4096 and the scan is cache-friendly.
Important notes#
This is intended for uint16 (or values in [0, max_bin]) after preprocessing.
Mask is optional. If mask is provided, only masked-in pixels contribute.
Border handling: “cropped window” (window clipped to image bounds).
Separate loops: strict interior vs border pixels.
Performance knobs#
- If your downstream code tolerates approximation, do:
compute on a coarse grid (spacing)
upsample with cv2.INTER_LINEAR
- percentile2d_u16(image, q, max_bin, mask=None)#
Compute per-pixel percentile map for 2D uint16 image with cropped borders.
- Parameters:
image ((H, W) uint16) – Input slice.
q (float) – Quantile in [0, 1].
max_bin (int) – Maximum histogram bin (inclusive). Typical: 4095 (2**12 - 1) or 4096.
mask ((H, W) uint8 or bool, optional) – Non-zero values participate in the histogram. If None, all pixels used.
Returns
- out(H, W) uint16
Percentile at each pixel.
- percentile2d_u16_window(image, q, rx, ry, max_bin, mask=None)#
Fast percentile map with a rectangular window of radius (ry, rx).
- Window at (y, x) is:
y in [y-ry, y+ry], x in [x-rx, x+rx] clipped to image bounds.
Notes
Strict interior pixels (ry..H-ry-1, rx..W-rx-1) use constant window size.
Border pixels use cropped windows and are computed in a second pass.
Returns uint16 percentile values (bin index).
- percentile2d_u16_window_grid(image, q, rx, ry, grid_x, grid_y, max_bin, mask=None)#
Percentile map computed on a coarse grid using a sliding histogram.
- Centers are located at:
y = y0 + i*grid_y x = x0 + j*grid_x
where (y0, x0) match the legacy center placement as closely as possible for speed runs (we use y0=0, x0=0 in the grid image coordinates; the wrapper should handle the legacy ‘left’ offset if it matters).