Point operations modify the intensity of a pixel using only that pixel’s own value, in isolation from its neighbours. May use statistical data relating to other pixels, such as the image histogram.
Homogeneous iff the operation is independent of pixel location.
Lookup Table
A lookup table (LUT) maps the current pixel value to an index, returning a new value from the table.
- Enables on the fly processing, especially on hardware platforms
- Changing table content changes the operation without changing any code
Examples:
- Pseudo colouring, e.g. mapping thermal image temperature to RGB
- Compensating for non-linearity in sensor elements
Grey Level Histogram
The grey level histogram shows the frequency of occurrence of each intensity level in an image, regardless of pixel position. Its shape describes overall brightness and contrast.
Normalized histogram:
Here:
- : number of pixels with intensity
- : total number of pixels
Defines the probability of intensity level in the image.
Accumulated histogram:
Defines the accumulated probability of pixels with intensity level .
Brightness and Contrast
Brightness and contrast are the position and the width of the same histogram. Both are described as point operations mapping input intensity to output intensity .
- Brightness
Mean intensity. A shift slides the histogram along the intensity axis, keeping its shape and width. - Contrast
Spread of intensities. Histogram width, the gap between the darkest and brightest points, measures it. A gain stretches the histogram wider.
Here:
- : input intensity
- : output intensity
- : shift constant, added to move brightness
- : gain constant, multiplied to change contrast
Shifting the histogram changes brightness only. Every pair of pixels keeps the same intensity gap, so contrast is unaffected.
Point Processing Functions
Common transformations applied to each pixel, typically implemented as a LUT mapping input intensity to output intensity .
- Identity
. - Digital negative
Inverts intensity: , where is the number of grey levels. - Square root
Compresses bright values and expands dark ones. - Contrast stretching
Piecewise linear expansion of a chosen intensity range. - Normalizing
Rescales intensities to use the full available range. - Clipping
Forces values outside a chosen range to the range boundary. - Intensity level slicing
Highlights a chosen intensity band, suppressing all others. - Bit slicing
Extracts one bit-plane of the pixel value. - Range stretching or compression
Maps a chosen input range onto a different output range. - Histogram equalization
Redistributes intensities to make the histogram more uniform.
Histogram Matching
Aka. histogram specification. The process of adjusting a test image so its grey level distribution follows a given reference distribution.
The reference is supplied as a 256-element array holding the reference CDF, one value per grey level.
Procedure:
- Compute the test image histogram, then its CDF
- For each test level , find the reference level whose CDF value is closest to
- Store in a 256-entry LUT
- Apply the LUT to every pixel
Here:
- : accumulated probability of test level
- : accumulated probability of reference level
Histogram equalization is the special case where the reference CDF is linear. Matching 2 levels through equal CDF values preserves their relative ordering.
For a colour image, each channel is matched independently against the reference channel.
def cdf(pixels):
# count how many pixels have each intensity
hist = [0] * 256
for v in pixels:
hist[v] += 1
# accumulate the counts and divide by the total to get the CDF
total = len(pixels)
running, out = 0, [0.0] * 256
for i, c in enumerate(hist):
running += c
out[i] = running / total
return out
def match(test_pixels, ref_cdf):
ct = cdf(test_pixels)
# build the LUT: for each test level g, pick the reference
# level r whose CDF value is closest to the test CDF value
lut = [0] * 256
for g in range(256):
best_r = 0
best_diff = abs(ref_cdf[0] - ct[g])
for r in range(1, 256):
diff = abs(ref_cdf[r] - ct[g])
if diff < best_diff:
best_diff = diff
best_r = r
lut[g] = best_r
# remap every pixel through the LUT
out = []
for v in test_pixels:
out.append(lut[v])
return out
For a colour image, match each channel against that channel’s reference CDF.
Worked Example
Match a 4-pixel test image to a reference CDF over 4 grey levels .
Test pixels: .
Test histogram: , total .
Test CDF : .
Reference CDF : .
Mapping:
- , : closest is , so
- , : closest is , so
- , :
- , : , so
Output pixels: .