Archive for August, 2010

Act 5. Enhancement by Histogram Manipulation

I’ve owned a digital camera for quite a while now and since then I have always wondered what the histogram option is for. I never really tried to understand it nor research about it, all I know was that it displays a graph and since it is named histogram it must be a graph of frequency of something. And then there was the third activity, my first encounter with histogram for image processing. From A3 – Image Types and Formats by Dr. Soriano it was stated that ” the histogram of a grayscale image is a plot which represents the number of pixels in an image having a certain grayscale value”. In other words, it is a graph that shows how many times a certain color value appeared in the whole image.  For this activity, we will be using Scilab to enhance a  grayscale image by manipulating its histogram.

Before we go on with the image manipulation, let me define some terms we will be dealing with for this activity:

  • Histogram – already given above
  • Probability Distribution Function (PDF) – this is the histogram divided by the number of pixels in an image
  • Cumulative Distribution Function (CDF) – the cumulative sum or integral of the PDF

And so we begin with the enhancement by histogram manipulation. The first task is to choose an image to be used preferably something dark. I chose an image I used for the 3rd activity although it is not a particularly problematic image it would do just fine.

I cropped the original image and made it smaller to save some time processing it since my laptop is not so young anymore.

In our previous activities, I used the command histplot() to obtain a histogram of the image however, histplot only shows the histogram and does not return its actual values. The command tabul() is a good alternative, unlike the first command this returns a tabulation of frequencies so plotting it afterwards will be necessary if you need/want to see how the histogram looks. Note that these values still refers to the histogram, to obtain the PDF we must first determine the total number of pixels in the image. Since we have a rectangular image, getting this value can be easily done by getting number of pixels in one row and one column and multiplying them. I did this by using the command size(). We then divide the histogram with this value to get the PDF, cumsum() was then applied to get the CDF.

To be able to enhance our image we generate a new CDF as we desire, say for example a linear CDF. We use backprojection to see the equivalent image of our new CDF this is done by:

  • first getting the gray scale value of a pixel then finding its CDF value
  • trace the CDF value in the y-axis of the desired CDF graph
  • obtain the equivalent gray scale value ( in the x-axis) in the new CDF graph and use it in place of the old one
  • do this for all pixels

The results I obtained were as follows:

Comparison of the effect of different CDF's. (click on the image for better resolution)

We could see that the original image is not so different from the 2nd one which uses the function ‘y=x’ this means that the original CDF is approximately linear. The third and fourth CDF’s (logx and x^3 respectively) show extreme effect to the image one being too bright while the other too dark. The fifth one is quite ok butI think the linear CDF is still better.

However, the enhancement above is not really categorically an ‘enhancement’ since the original image is better (or almost the same) with the processed images. It was actually more of an exploration of the technique presented in this activity so here is another application of the histogram manipulation technique, this time with an old picture of mine together with a couple of friends from highschool.

Me and my friends. In your left is the original gray scale image while in your right is the enhanced image

Comparison of the PDF's and CDF's. Left plots corresponds to the original images while right plots are those of the enhanced

See the ‘enhancement’ now? I used ‘y=x^.7’ for my desired CDF.

If you are not into programming, you could also use software for editing images such as the well known Adobe Photoshop and the free software Gimp.

Histogram Manipulation using Gimp

Scilab codes:

stacksize(10000000);

image= gray_imread(‘D:\files\kaye\186\grayscale2.jpg’);
[imx,imy] = size(image);
scf(0), subplot(1,2,1), imshow(image);
histogram = tabul(image,’i’);
s=imx*imy;
PDF = histogram/s;
scf(1), subplot(2,2,1), plot(PDF);  ;
cdf=cumsum(PDF);
CDF=cdf/max(cdf);
subplot(2,2,2), plot(CDF(:,1), CDF(:,2));
x=[]
y=[]
for i= 1:length(CDF(:,1));
x(i)=i;
y(i)=i^.7;  // vary for other CDF results
end
y=y/max(y);
CDF2=[x,y];
scf(1),subplot(1,2,1), plot(x,y);
adjusted = [];
for i=1:imx
for j=1:imy
a= find(histogram(:,1)==image(i,j));
adjusted(i,j)= y(a);
end
end
[adjx,adjy]=size(adjusted);
s_adj=adjx*adjy;
PDF2=(tabul(adjusted, ‘i’))/s_adj;
subplot(1,2,2), plot(PDF2(:,1),PDF2(:,2));
scf(0),subplot(1,2,2), imshow(adjusted);

So there, next time you take a picture and you find it too dark or too bright or just too boring try playing around with the histogram. Enjoy 😀

I would like to thank Gladys, Tisza, and Rob for their insights and tips.

I give myself a grade of 9 for this activity since I have completed the requirements but failed to submit on time.

Sources:

[1] Dr. Maricor Soriano. “A4 – Enhancement by Histogram Manipulation”, 2010

[2] Dr. Maricor Soriano. “A3 – Image Types and Formats”, 2010

[3]http://www.pixelperfectdigital.com/free_stock_photos/data/509/medium/grayscale_flower.jpg

Act 6. Fourier Transform Model of Image Formation

This activity explores the properties of the Fourier transform

The first part involves mainly the familiarization with basic Scilab commands for Fourier transform like fft2 and fftshift. Two images were observed for this part one being a circle and the other is the letter A. After calling the image via ‘imread’ fft2 was then used to obtain the Fourier transform of the images. The use of fft2 resulted into a matrix containing complex numbers which cannot be used to create images to visualize the result so the abs() command was also invoked to obtain the absolute values of the matrix elements. The fftshift on the othe

r hand works by taking the matrix element with highest value and shifting them towards the center. The images obtained for the whole process is presented in figure 1.

Figure 1. Applying the fast fourier transform command on images. From left to right: grayscale of the original image, invoking fft2, applying fftshift, applying fft2 for the second time.

Due to the scale and low resolution of the image, the results are not so clear. However, it can easily be said that the fourier transform of a fourier transform will result to the original state but in an inverted position.

Next analysis was done on the convolution of two images. In particular, a simulation of an imaging device was done. 2 128X128 pixels image was used, both having a black background. The image with a white ‘VIP’ text will our image of interest while a white circle in will serve as our aperture. The two images was convolved by getting the product of their individual fft’s following the rule that if h=f*g then H=FG where here, (*) represents convolution, the small letters are functions while the capital letters are fourier transform of their respective smaller letter. It was observed that the clarity of the resultant image is dependent upon the radius of the aperture, i.e., the resulting image blurs out as the radius of the aperture decreases. In figure 2 we can see two set of images. The left most images for each set is the aperture and the right most are the result.

Figure 2. Simulation of imaging device.

The third part of the activity uses fast fourier transform to obtain the correlation of two images. Correlation is a measure of similarity between two functions. This measure can be related to fourier transform such that if p is the correlation between functions f and g then P, F, and G, the fourier transforms of the functions denoted by their corresponding small letter, is given by the equation P=F*G where (*) indicates complex conjugate.

Figure 3. Top 2 images were the ones compared while the bottom image is their correlation.

For this, we compared  an image containing the phrase ‘THE RAIN IN SPAIN STAYS MAINLY IN THE PLAIN’ and an image containing the letter ‘A” of the same font. The images and their correlation can be seen in figure 3. Five bright spots can be seen in the resultant image, the same number of A’s found in the first image, these indicate the spots with highest correlation with the second image.

Finally, we were asked to do an edge detection using convolution integral. Here, we used the same ‘VIP’ image used for part two and convolved it with different 3×3 matrix patterns whose total sum is zero. I used the following matrices for my pattern:

pattern1= [-1 -1 -1; 2 2 2; -1 -1 -1];

pattern2= [-1 2 -1; -1 2 -1; -1 2 -1];

pattern3= [-1 -1 -1; -1 8 -1; -1 -1 -1];

pattern4 = [1 1 1; 1 -8 1; 1 1 1];

Figure 4. Edge detection using patterns 1-4.

Comparing the results for patterns 1 and 2 (top 2 images in figure 4) it could be seen that the horizontal edges of the letter is more defined for pattern 1 while the vertical edges is more defined for pattern 2 which are comparable to the position of the number ‘2’ in their respective patterns. Comparing results for patterns 3 and 4 (bottom 2 images in figure 4), it is noticeable that the dark outline of the letters for pattern 3 and 4 is at different positions. For pattern 3 the dark outline can be seen after the white outline while for pattern 4 it is the other way around. For both cases, however, the position of the outline corresponds to the position of the negative sign in the matrix patterns.

I will give myself a grade of 9 for being able to simulate what is asked.

I would like to thank Tisza, and Jonats from whom I confirmed if I was getting the right results

Sources:

[1] Dr. Maricor Soriano. “A6 – Fourier Transform Model of Image
Formation”, 2010

Scilab codes:

—//6A. circle
//x = [-1:0.01:1];
//[X,Y] = meshgrid(x);
//r = sqrt(X.^2 + Y.^2);
//circle = zeros(size(X,1), size(X,2));
//circle(find (r <=0.5)) = 1.0;
//subplot(1,5,1), imshow(circle,[]);
//Igray = im2gray(circle);
//FIgray = fft2(Igray); //remember, FIgray is complex
I = imread(‘D:\files\kaye\186\circle_6_3.bmp’);
//gray = im2gray(I);
//FIgray = fft2(Igray); //remember, FIgray is complex
//subplot(1,5,1), imshow(I, []);
//subplot(1,5,2), imshow(abs(FIgray),[]);
//subplot(1,5,3), imshow(fftshift(abs(FIgray)), []);
//subplot(1,5,4), imshow(abs(fft2(FIgray)),[]);
//subplot(1,5,5), imshow(abs(fft2(fft2(I))),[]);

//6A. letter A
//I= imread(‘D:\files\kaye\186\letterA.bmp’);
//image=(I-min(I))/(max(I)-min(I));
//subplot(1,5,1), imshow(image);
//Igray = im2gray(image);
//FIgray = fft2(Igray); //remember, FIgray is complex
//subplot(1,5,2), imshow(abs(FIgray),[]);
//subplot(1,5,3), imshow(fftshift(abs(FIgray)), []);
//subplot(1,5,4), imshow(abs(fft2(FIgray)));
//subplot(1,5,5), imshow(abs(fft2(fft2(image))));

//6B. convolution
//rgray = im2gray(I);
//image= imread(‘D:\files\kaye\186\VIP.bmp’);
//agray = im2gray(image);
//Fr = fftshift(rgray);
//aperture is already in the Fourier Plane andneed not be FFT’ed
//Fa = fft2(agray);
//FRA = Fr.*(Fa);
//IRA = fft2(FRA); //inverse FFT
//FImage = abs(IRA);
//final = (FImage-min(FImage))/(max(FImage)-min(FImage));
//imshow(final);
//imwrite(final, ‘D:\files\kaye\186\vip_mid_aperture.jpg’)

//6C. Template matching using correlation
//text = imread(‘D:\files\kaye\186\text.bmp’);
//text_gray= im2gray(text);
//a = imread(‘D:\files\kaye\186\a.bmp’);
//a_gray = im2gray(a);
//ftext = fft2(text_gray);
//fa = fft2(a_gray);
//im = fa.*(conj(ftext));
//FImage = fft2(im);
//FImage= abs(FImage);
//imshow(FImage, []);
//final = (FImage-min(FImage))/(max(FImage)-min(FImage));
//imwrite(final, ‘D:\files\kaye\186\correalation.jpg’);

//6D. Edge detection using the convolution integral
pattern1= [-1 -1 -1; 2 2 2; -1 -1 -1];
pattern2= [-1 2 -1; -1 2 -1; -1 2 -1];
pattern3= [-1 -1 -1; -1 8 -1; -1 -1 -1];
pattern4 = [1 1 1; 1 -8 1; 1 1 1];
pattern5 = [-3 -3 -3; 2 2 2; 1 1 1];
image= imread(‘D:\files\kaye\186\VIP.bmp’);
gray = im2gray(image);
result = imcorrcoef(gray, pattern1);
result = (result – min(result))/(max(result)/min(result));
imshow(result);
imwrite(result, ‘D:\files\kaye\186\6D_1.jpg’);
//repeat for all pattern

note: remove ‘//’ to un-comment