v9.1.1
Menu

Contrast Limited Adaptive Histogram Equalization

mediumFREEPoint OperatorsEnhancementCV: Image Processing

Implement Contrast Limited Adaptive Histogram Equalization (CLAHE) for local contrast enhancement, which is an improvement over traditional histogram equalization. CLAHE is essential in image processing as it helps to enhance the contrast of images by dividing them into smaller regions, called tiles, and applying histogram equalization to each tile.

The process involves dividing the image into square tiles of tile_size ×\times tile_size pixels (default 8×88 \times 8) and applying histogram equalization to each tile. Tiles at the right/bottom border may be smaller if the image size is not a multiple of tile_size. This is done by computing the histogram of each tile, which represents the distribution of pixel intensities, and then clipping the histogram at a threshold to limit contrast amplification. The clipping threshold is typically set to a fraction of the total number of pixels in the tile, preventing over-amplification of noise in homogeneous regions.

Here are the key steps:

  1. Divide the image into tiles of size n×nn \times n.
  2. Compute the histogram of each tile, which represents the distribution of pixel intensities.
  3. Clip the histogram at a threshold to limit contrast amplification. For a tile of NN pixels the threshold is T=clip_limit⋅N/256T = \text{clip\_limit} \cdot N / 256. The total clipped excess EE is shared equally among all 256 bins, adding ⌊E/256⌋\lfloor E / 256 \rfloor to every bin.
  4. Compute each tile's CDF from its clipped histogram and map that tile's pixels through it. Each tile is mapped independently, so this simplified version skips the bilinear blending between neighbouring tiles that full CLAHE uses to hide tile seams.

The mapping for intensity vv normalises the CDF to [0,255][0, 255], truncating to an integer:

out(v)=⌊CDF(v)−CDFmin⁡CDFmax⁡−CDFmin⁡×255⌋\text{out}(v) = \left\lfloor \frac{\text{CDF}(v) - \text{CDF}_{\min}}{\text{CDF}_{\max} - \text{CDF}_{\min}} \times 255 \right\rfloor

where CDFmin⁡\text{CDF}_{\min} is the smallest non-zero CDF value and CDFmax⁡\text{CDF}_{\max} the largest. If a tile is uniform (CDFmax⁡=CDFmin⁡\text{CDF}_{\max} = \text{CDF}_{\min}), its pixels are left unchanged. Return a uint8 array with the same shape as the input.

H(i)=∑x=1n∑y=1nδ(f(x,y)−i)H(i) = \sum_{x=1}^{n} \sum_{y=1}^{n} \delta(f(x,y) - i)

This technique is widely used in medical imaging to enhance the visibility of details in images.

Example

Input
image = 8×8 tile with rows of 100, 101, 102, 103, 100, 101, 102, 103
tile_size = 8
clip_limit = 2.0
Output
rows map to 0, 85, 170, 255, 0, 85, 170, 255
Reasoning
  • Input: one 8×88 \times 8 tile (N=64N = 64 pixels) whose rows cycle through the grey levels 100, 101, 102, 103, so each level fills 16 pixels. With clip_limit =2.0= 2.0 the threshold is T=2.0⋅64/256=0.5T = 2.0 \cdot 64 / 256 = 0.5.
  • Clip: each of the four occupied bins drops from 16 to 0.50.5. The excess is E=4×15.5=62E = 4 \times 15.5 = 62, and ⌊62/256⌋=0\lfloor 62 / 256 \rfloor = 0, so no bin gets anything back.
  • CDF: accumulating the clipped bins gives 0.5,1.0,1.5,2.00.5, 1.0, 1.5, 2.0 at levels 100–103, so CDFmin⁡=0.5\text{CDF}_{\min} = 0.5 and CDFmax⁡=2.0\text{CDF}_{\max} = 2.0.
  • Map: CDF(v)−0.51.5×255\frac{\text{CDF}(v) - 0.5}{1.5} \times 255 sends 100→0100 \to 0, 101→85101 \to 85, 102→170102 \to 170, 103→255103 \to 255. The rows therefore become 0, 85, 170, 255, 0, 85, 170, 255.
  • Notice: four grey levels only 3 apart get stretched across the full 00–255255 range. Clipping made all four bins equal, so the output steps are evenly spaced. A tile holding a single grey level would come back unchanged instead.

Constraints

  • image: 2D grayscale array [0-255]
  • tile_size: Size of each tile (default 8)
  • clip_limit: Histogram clip limit (default 2.0)
  • Return: Enhanced image

Learn this in

More from CV: Image Processing

solution.py

Test results

Sign in to run your code against the test cases.