Fondazione Bruno Kessler - Technologies of Vision

contains material from
Template Matching Techniques in Computer Vision: Theory and Practice
Roberto Brunelli 2009 John Wiley & Sons, Ltd

5.1 Histogram equalization

The use of the normalized correlation coefficient allows us to cope with global linear intensity remapping of the images being compared.

1 sampleimages     <- file.path(system.file(package="TeMa"), 
2 ...                               "sampleimages") 
3 img1 <- ia.scale(as.animage(getChannels(read.pnm( 
4 ...                   file.path(sampleimages, "sampleFace_01.pgm")))), 
5 ...                  255) 
6 m    <- animask(32,87,104,104) 
7 face <- ia.integerAnimage(ia.scale(ia.get(img1, m), 255))

However, in many cases, image intensity undergoes a non linear transformation, a typical case being that of gamma correction, routinely applied by cameras in order to provide images that are more readable from human inspectors. The following code snippet applies a darkening gamma correction:

1 dark   <- ia.matop(function(x) ((x/255)**(4))*255, face) 
2 tm.plot("figures/dark", 
3 tm.plot("figures/darkH", hist(dark))

If we compute the correlation between dark and face we do not get 1 but a lower value

1 ia.correlation(ia.realAnimage(dark), ia.realAnimage(face))[[4]]
1[1] 0.957491

even if the value is not as low as one would expect by the perceived image difference. Let us consider the following problem: given a set of face images, snapped under different illumination conditions, we want to compare each of them to every other one. This means that for each comparison, the two images may be characterized by two different illumination conditions. A possible solution is to equalize in turn one of the images, the one whose histogram has a lower entropy and hence less information, so that it approximates the histogram of the more informative image. By doing so, we ensure that we do not throw away information. Let us assume that we are working with 8 bits images (256 intensity levels).

1   tm.entropy <- function(img) { 
2 ...     fs <- (hist(img,plot=FALSE,breaks=0:256)$counts)/ia.size(img) 
3 ...     fs <- fs[fs > 0] 
4 ...     -sum(fs*log2(fs)) 
5 ...   } 
6   tm.entropy(dark)
1[1] 6.514707
1   tm.entropy(face)
1[1] 6.642061

As face has a higher entropy, we equalize dark using as target histogra the histogram of face:

1 darkEq <- tm.histogramEqualize(dark, 
2 ...                                list(type="target", 
3 ...                                     histo=tm.histogram(face))) 
4 ia.correlation(ia.realAnimage(darkEq), ia.realAnimage(face))[[4]]
1[1] 0.9999505

The histogram of darkEq is now very similar to that of face and the correlation value of the two images is higher than that of the couple (dark, face). The major drawback of this strategy is that every time we compare two (different) images we must perform a different equalization. An alternative is to choose a neutral equalization target, and normalize each image towards it. A natural choice is to choose a Gaussian distribution whose location paramters is 128 and whose standard deviation is such that no shadow or highlight clipping occurs when restricting to the interval [0.255]:

1 darkEq <- tm.histogramEqualize(dark, 
2 ...                      eqSpecs = list(type="Gaussian", 
3 ...                                     gMin=0, gMax=256, mu=128, sd=30)) 
4 faceEq <- tm.histogramEqualize(face, 
5 ...                      eqSpecs = list(type="Gaussian", 
6 ...                                     gMin=0, gMax=256, mu=128, sd=30)) 
7 tm.plot("figures/darkEq", 
8 tm.plot("figures/darkEqH", hist(darkEq))

Even in this case we get a better correlation value than the one we got when comparing directly dark and face:

1 ia.correlation(ia.realAnimage(darkEq), ia.realAnimage(faceEq))[[4]]
1[1] 0.999878


Figure 5.1: Image dark (top row) can be equalized so that the distributions of its intensity values approaches a Gaussian distribution (bottom row).