Adaptive Histogram Equalization

Description

Adaptive Histogram Equalization (AHE) is a variant of histogram equalization that computes several histograms, each corresponding to a different section (tile) of the image, and uses them to redistribute the lightness values of the image locally.

Unlike plain histogram equalization, which computes a single mapping for the whole image, AHE adapts to local contrast, which improves detail in both dark and bright regions at once. Applied without limits, however, it tends to over-amplify noise in flat (near-uniform) tiles. GIL implements the Contrast Limited variant (CLAHE), which clips each tile’s histogram at a configurable limit and redistributes the clipped, excess count uniformly over the other bins before computing the mapping.

non_overlapping_interpolated_clahe is named after the specific strategy it implements: the image is split into non-overlapping tiles, equalized independently, and the tile mappings are then bilinearly interpolated across the image to remove the tile-boundary artifacts that would otherwise appear.

Algorithm

  1. Split the image into non-overlapping tiles of size tile_width_x by tile_width_y.

  2. For each tile and channel, compute the histogram of pixel values, using bins of width bin_width.

  3. Clip the histogram: find the actual clip limit (a bin count) whose value, when every bin above it is clipped down to it, redistributes exactly clip_limit * (pixels in tile) excess pixels; then clip every bin to that limit and spread the removed excess uniformly across all bins.

  4. Compute the histogram equalization mapping for each (clipped) tile histogram, as in histogram equalization.

  5. For each pixel, bilinearly interpolate between the mappings of the (up to four) tiles whose centers surround it, so that intensities change smoothly across tile boundaries instead of jumping at them.

References:

Graphics Gems IV, Paul S. Heckbert (ed.), p. 474 (clip-and-redistribute algorithm).

Parameters

Parameter Description

src_view

Source image view.

dst_view

Destination image view, same color space and dimensions as src_view.

tile_width_x, tile_width_y

Tile size, in pixels, along the x and y axes. Defaults to 20 for both. Smaller tiles adapt more locally but increase the risk of amplifying noise.

clip_limit

Fraction of a tile’s pixel count above which a histogram bin is clipped, in the range (0, 1]. Defaults to 0.03. Lower values limit contrast amplification (and noise) more aggressively.

bin_width

Width of each histogram bin. Defaults to 1.

mask, src_mask

When mask is true, src_mask selects which pixels of src_view are copied unmodified to dst_view instead of being equalized. Defaults to no mask.

Demo

#include <boost/gil.hpp>
#include <boost/gil/extension/io/png.hpp>
#include <boost/gil/image_processing/adaptive_histogram_equalization.hpp>

using namespace boost::gil;

gray8_image_t img_in;
read_image("test_adaptive.png", img_in, png_tag{});
gray8_image_t img_out(img_in.dimensions());

non_overlapping_interpolated_clahe(view(img_in), view(img_out));
write_view("out-adaptive.png", view(img_out), png_tag{});

See also the full example at example/adaptive_histogram_equalization.cpp.