3.2.1. Contrast Stretching

Consider a scalar (gray value) image \(f\) with values \(f(\v x)\) that are only in a subset of the possible scalar values (of course dependent on the range of the image). E.g. consider a gray value image \(f\) with possible range \(R=[0,1]\subset\setR\) but whose values are in the range from \(a\) to \(b\).


../../../_images/contraststretch.png

The point operator:

\[g(\v x) = \phi(f(\v x))\]

with:

\[\phi(v) = \frac{v-a}{b-a}\]

results in an image \(g\) that uses the entire range of gray values from 0 to 1.

Assuming we have overloaded the arithmetical operators to work on images we may write:

\[g = \frac{f-f_\text{min}}{f_\text{max}-f_\text{min}}\]

In Python/Numpy we can write:

g = (f-f.min())(f.max()-f.min())

3.2.1.1. Exercises

  1. Given an 8-bit gray value image \(f\), i.e. \(f(\v x)\in[0,255]\subset\setZ\), what is the point operator that stretches the contrast of the image to the entire possible range.
  2. Explain why contrast stretching of a digital image cannot always lead to satisfactory results when the original image was very very dark (or very very light).
  3. Contrast stretching of color images is not a trivial generalization of what is discussed for scalar images.
    1. Explain that scalar constrast stretching of the Red, Green and Blue channels (images) independently is not a good idea.
    2. Let’s first change the color model from RGB to HSV. And then stretch the contrast in the V image and use the new V values together with the original H and S values. Implement this contrast stretching algorithm. Why is this contrast stretching method leading to reasonable results?