Thursday, July 3, 2008

Photomosaic final...Yay!

This is a continuation from a previous posting:

http://math5300blog.blogspot.com/2008/06/assign-9-q5.html

At this point I only got some of the ghosts done and ms. pac-man in some places only.

Here is my final image:



While I am please with how the mosaic turned out...I am not too sure why a 'thin' line to the right and below of some of my pixel-images can be noted. It almost looks like the 'pixel-pictures' were not big enough to fill in that 'little' sliver of piece to the right of it. Maybe I did not 'resize' some of the pixels enough??? I doubt this because I quickly found out what happens if you try and plug in a 'mis-sized' icon, while giving 20x20 coordinates (it does not work). I learned this because my orange ghost was not 20x20 when I tried to use it. If you look at my previous posting, where I showed the icons I used...you can see that the orange ghost is not the right size.

Well, I can account for the ms. pac-man icon because the screen grab I made of the image contains a small piece of the pacman 'maze' to the right and below of the pacman icon. As for the red ghost and pink ghost...I believe they were 'inside' the ghost house when I 'grabbed' them and so might have caught a small piece of the edge of the ghost house; thereby creating a small 'sliver' to the right of some 'pixel-icons'.

This was a fun project and if I had more time I would have liked to try and figure out how some people were able to create 'arrays' and in just a few steps plug in the icon-pics...instead of how I had to provide coordinates for each and EVERY icon on the mosaic...that was tedious!

Thanks for an interesting class Mike.

Assignment #2 - historgram equalization...

Here is my original picture.

a=imread("gdarkim.jpg");
A=double(a)/255;
imshow(im);



I chose this image because it is predominantly a dark picture with little observable detail in its present state. It was taken inside a moving car so you can see a slight blur and some smudges on the windshield. What I want to do is to produce a 'histogram equalization transform' for this picture to enhance it. Here are the steps to do it.


The histogram of the original image looks like this.



I used the following octave code to obtain it:

hist(b(:));

Next I need to normalize the histogram by using the octave code:

b=hist(A(:),256,1);
plot(b);

[Prof Zhu, I am not sure if I am normalizing the histogram properly here...I have a note that you wrote down for me in my notebook and I wasn't sure if this was a normalizing function in octave or if this simply plots the histogram of the original image.]

[I also tried using your matlab code for the im_nhist process but kept getting error messages in octave:

octave:171> function [pr, r] = im_nhist(im, bitdepth)
>
> M=375;
> N=500;
>
> r = 0:2^bitdepth-1;
> pr = zeros(size(r));
> for y = 1:M
> for x = 1:N
> rxy = im(y, x);
> pr(rxy+1) = pr(rxy+1) + 1;
> end
> end
> end
octave:172>
octave:172>
octave:172> % calculate the normalized histogram of the image
octave:172> [pr, r] = im_nhist(im, 8);
error: expecting integer index, found 1.517647
error: evaluating binary operator `+' near line 11, column 31
error: evaluating assignment expression near line 11, column 19
error: evaluating for command near line 9, column 5
error: evaluating for command near line 8, column 1
error: called from `im_nhist'
]

The normalized histogram using "b=hist(A(:),256,1);" as the normalizing process looks like this:



Next, I have to calculate the normalized histogram of the image by using:

r=0:255;
s = zeros(size(r));
for k = 1:256;
s(k) = round((2^8-1)*sum(b(1:k)));
end;
C= zeros(size(A));
for y = 1:375
for x = 1:500
C(y, x) = s(A(y, x)+1);
end;
end;

imshow(double(C)/255)

The image I get is:



I notice a couple of things. First of all it is 'lighter' i.e. it is not as dark as the original image. However, it is very grainy and not very clear or detailed. I'm not sure if this is just a natural side-effect of the histogram equalization with a bright background and dark foreground or if I am doing something wrong here.

If I did do something wrong then I am sure it has to do something with the normalization process...which I wasn't entirely sure if I was doing correctly in the first place.

I can't seem to let the 'flash' picture of my son go...I tried to normalize the histogram of this image to see what I could get.

Recall that the original image looks like this:



After applying the histogram equalization code I get the following image:




Notice how the flash washes out more of the image? This makes sense as this process tends to enhance the 'lighter' parts of the image and the darker parts.

The original and then normalized histograms look like this:




After these 2 experiments I believe that histogram equalization will not work well for images with a big difference between the dark and light regions, as in the 2 examples I used. I think that if I use a 'darkish' image with some light regions to it, the equalization process will not look grainy or washed out.

Here is the new picture I used and applied the histogram equalization to. Notice how the picture is no longer grainy and enhances the light and dark regions enough to make the picture crisper and with more detail.



The first image is the original and the second image is the 'fixed version'. Notice how the 2nd image does not look as 'drab' as the first image and that the stones on the shore appear to 'pop' out more with enhanced detail. Also, the sky in the 'fixed version' does not look as monotone as the original. There is a hint of the sun observed in the sky as well which further enhances the image.

Therefore, I believe if you try to histogram equalize an image that has a dark foreground and a bright background, it will yield an image that will be lighter but grainy i.e. not clear. Thus, if you want to select a picture that will benefit from histogram equalization, it must not have too much of a major difference between the dark and light regions, as was the case in my 'water' image used.

Sunday, June 29, 2008

2nd half of 5300 course - Assignment #1 - Dark and Low contrast grey scale corrections...

For this assignment, we were required to take a 'dark image' and a 'low contrast image', and try to make them look a bit clearer using Photoshop and Octave.

I wanted to test the extremes of photoshop's image adjustments via the 'curves' function, and so I took a really dark picture by turning off the flash but adjusting the ISO to its highest setting. The subject in the picture was taken in a dark closet with the door closed.

Here is the resulting picture.



...No this is not a mistake...the picture pretty much looks like a black colour chip...

However, after applying the image/adjust/curves... function in Photoshop, the results are quite interesting. Here is the resulting image:



If you tilt your head to the left, you will see that it is a picture of my son Andre, sitting on his 'play chair', with his hands on his stomach.

Can you see this?

The neat thing about this transformation is that 'detail' that you would not normally see, can now be seen after applying the image/adjust/curves...function in Photoshop.

Here is how the histogram and 'curve' adjustment looked like in Photoshop.



Notice how the histogram shows that the 'image' mainly resides in the 'dark regions', meaning that the image is predominantly 'dark'. Therefore, inorder to make this image 'clearer', we must magnify the dark regions while suppressing the bright regions. This technique is often used in sharpening 'medical scans'.

Also note that the curve produced resembles a 'power law transform' or 'gamma law transform' curve, where gamma is less than 1.

To make this image look clearer by using octave, I employed the following Octave code:

A=imread("andre.jpg");
B=(A(:,:,1)+A(:,:,2)+A(:,:,3))/3;
imwrite("andregray.jpg",B);

By doing this I changed my 'colour' image into a gray scale image.

I then applied the Power-Law / Gamma Transform using the following Octave code:

A=imread("andregray.jpg");
G=mat2gray(c*double(A)/255^0.25);
H=255*G;
imwrite("gammandre0_25.jpg", double(H)/255);

Recall that the Power Law/Gamma Transform = S = c*r^gamma. Here I selected c=1 and r=0.25.

The resulting image is very close to what I came up with using photoshop.



Just for fun. I wanted to see how the 'log' transform could 'improve' a reflected flash image. Here is the image I was working with.



I then tried to apply a 'log' curve to this image, to see if I could reproduce the 'sunglasses effect' and generate increased detail obscured by the 'flash'.

Here is the improved image using Photoshop.



Notice how more detail is evident in the 'transformed' picture. That is, you can see more of the camera lens, the details of my fingers under the flash are more evident, and my son's nose and toes are not as washed out by the flash as before.

However, notice how certain 'shadows'/grey regions become even more darker using this transformation. i.e. see my left arm appears darker and loses its detail.

I tried to create a log transform using Octave but I was not very successful.

The codes I tried were:

a=imread("flashgrey.jpg");
g=mat2gray(5*log(1+(double(a)/255)));
g1=g*255;
imwrite("newlogandre5.jpg",double(g1)/255);

This code resulted in the following image transformation, which you will notice is not much different from the original flash image. The 'sunglass' effect did not get applied here. Recall that the log transform = s = c*log(1+r) and that the 'sunglasses effect' works for 'r' greater than or equal to zero and for bigger 'c'. I tried making c=10, 20, 50 but the images all pretty much looked the same.



I then tried 'shifting' the log function to the 'left' by 'adding 1'.

The code I then tried using was:

g=mat2gray(1+5*log(1+double(a)/255));
g1=g*255;
imwrite("nnewlogandre7.jpg",double(g1)/255);

The resulting image was not any better than the others I tried previously. Which leads me to believe that I am doing something wrong with my log Octave code. Will have to confirm with Prof. Hong Mei.

Here is the picture I got by adding '+1'. That is, the log function I used was s=1+c*log(1+r)



I tried to amend the code by using the following octave commands:

g=mat2gray(2*log(1+(double(a))));
imshow(g);

However, the image looked 'lighter' as opposed to 'darker' and showing even less detail. Pretty much looked the same as the pictures above but washed out a bit more.

I then tried running the following code from Prof. Zhu, thinking that I had to have all of these codes running in order for the programmes to run properly...however the images did not get any better or resemeble the image I cleared up using PhotoShop.

The code I used was:

% read images
im = imread("flashgreysml.jpg");

% calculate image size
imsz = size(im);
NoPixels = imsz(1, 1) * imsz(1, 2);
imagesize = NoPixels*8/8;

% histogram code...
function [pr, r] = im_nhist(im, bitdepth)

% calculate number of pixels
[M, N] = size(im);
NoPixels = M*N;

r = 0:2^bitdepth-1;
pr = zeros(size(r));
for y = 1:M
for x = 1:N
rxy = im(y, x);
pr(rxy+1) = pr(rxy+1) + 1;
end
end

pr = pr/NoPixels;
end

% figure; bar(r, pr); axis tight;
% set(gca, 'xtick', 0:50:255)

% scale the image
f = im2double(im);
min_im = double(min(im(:)));
f = f - min_im;
f = f./max(f(:));
f = 255*f;
fsc = mat2gray(f);

% image negatives
g = mat2gray(2^8 - 1 - f);


% logarithmic transform;
c = 2;
g = mat2gray(c*log(1+f));
figure(1);
subplot(2, 2, 4), imshow(g);
title('logarithmic');

% power-law (Gamma) transform
c = 1;
gammas = [0.04, 0.2, 0.4, 1, 2.5, 10, 25];
for i = 1:length(gammas)
g = mat2gray(c*f.^gammas(i));
figure;
imshow(g);
axis off;
end;

However this code resulted in the following images (I selected the best ones...), which do not resemble the image I enhanced using photoshop:



I then finally tried the contrast stretching function but still did not get desired results...Here is the code and image I came up with.

% contrast-stretching transform;
figure(4);
m = 128;
i = 1;
for E = 0.1:5:10.1
g = 1/(1+(m/(double(im) + 0.0001))^E);
subplot(1, 3, i), imshow(mat2gray(g));
axis off;
i = i+1;
end



Will leave this assignment for now as I must work on my photomosaic and assignment #2.