# II – Contrast Adjustment & Image Normalization

If you took a careful look at the previous subsection on histograms, you may have noticed that the narrower the histogram of an image is (ie: less variance in the histogram spectrum), the less contrast an image has. I’ll give another example below of an image with very low variance (poor contrast), and the same image with a contrast adjustment algorithm applied to it:

Low/High Contrast Images and Corresponding Histograms

In both cases, the original images have the same number of pixels, but the histogram for the second image with contrast enhancement applied to it has a much wider histogram (ie: greater variance/standard-deviation). There are several different ways to alter an image to improve contrast, but I will only cover one of them for now. I leave it up to the reader to use these guides to devise your own original methods for contrast enhancement.

First, consider a  gray-scale image with 256 different possible intensity values on the range [0,255]. As mentioned in the previous subsection, most of the time, when dealing with images, intensity values are stored as discrete numbers (ie: integers) rather than floating point numbers (which have a fractional component). Due to the internal workings of computers in general, we generally store numbers as binary values. Common limits for the maximum size of an integer could be 255 for an 8-bit unsigned number ($2^8-1=256-1=255$), 65535 for a 16-bit unsigned number ($2^{16}-1=65536-1=65535$) and so on. In the case of the examples I have been discussing so far, I have been converting color images to 8-bit gray-scale images to make the tutorials simpler. As I also mentioned in the first section in this tutorial, there is an easy way to extend all of these algorithms to deal with color images, not just gray-scale ones.

Anyhow, the images we are working with can have an intensity value between 0 and 255 (inclusive) assigned to each pixel. Let’s assume the image we are working with has poor contrast, and after histogram analysis, we realize that, for ALL of the pixels in the source image, the intensity values are on a sub-interval, [a,b], such that $a>0$ and $b<255$ (An example would be that the smallest intensity value is 17, and the largest is 40. That would imply that $a=17$ and $b=40$).

We want to scale and shift all of the intensity values in our source image so that we can recreate the original image with all of the intensity values reassigned to an appropriate value on [0,255]. One very simple approach to this is the following “single pixel operation” (ie: each pixel in the output image is a function of a single pixel in the source/input image. In this case, we calculate some statistics from the source image and perform a linear shifting/scaling operation on the pixels in the source image to generate the pixels in the output image):

• Define the upper and lower limits for intensity values in the final output image ($out_{max}$ and $out_{min}$; we are assuming that $out_{min}=0$, as we want the output histogram to be on the interval $[0,out_{max}]$)
• Determine the upper and lower limits for intensity values in the source image, either by a simple search algorithm or histogram analysis ($in_{max}$ and $in_{min}$)
• “Shift” all of the intensity values by subtracting the value $in_{min}$ from each of them
• “Scale” all of the intensity values by multiplying them by $\dfrac{out_{max}}{in_{max}-in_{min}}$

The following figures demonstrate the equivalent operation for a 1D data set: