Sunday, August 11, 2013

Activity 9 - Color Image Segmentation

In this activity, we learned how to extract a colored region of interest (ROI) from a colored image. This is called color segmentation, as in the activity title. We learned two techniques: parametric and non-parametric segmentation.

First, I have this simple colored image of a clothes hook mounted on a white dresser. I wanted to be familiar first with the techniques so I began with an easy image. The first thing to do is to select a monochromatic ROI in the image, as I have done below.

 Figure 1. (a) The original image. (b) Cropped monochromatic
region of interest (ROI).

Next, I took the RGB channels of the image in Scilab. Remember in the previous post, I did not know how to do it in Scilab and so I had to use GIMP. Turns out it was just an additional three lines. I then transformed the RGB channels into the normalized chromaticity coordinates (NCC), given by
Although we should have three NCC terms corresponding to RGB, note that these are normalized values, and as such the sum r + g + b = 1. Therefore, we can express b in terms of r and g, b = 1 - r - g. In short, we only need two coordinates.


The first technique, parametric segmentation, involves assuming a Gaussian distribution along r and g and taking the joint probability p(r)p(g), or the probability that any given pixel lies along the NCC. We first compute for the mean and standard deviation for r and g and compute the probability as
of the original image. The joint probability is just the product p(r)p(g), which, for my example, results to this:

Figure 2. The segmented image using parametric 
segmentation.

We can see here that the method was even able to differentiate between the darker and lighter portions of the ROI. The black spots here represent the glitter speckles in the body of the clothes hook.

The second method, called non-parametric segmentation, involves back-projecting each pixel onto the histogram. The difference here is that we are no longer assuming a distribution, which removes the limitations of the previous method. What we're doing here essentially is using the actual probability density function (pdf) of the image rather than approximating by a Gaussian pdf. But first we need to create a 2d histogram of the image. Ma'am Jing provided a sample code to create a 2d histogram, which I just implemented. Supposedly it should be faster because there are no computations needed, just a look-up of histogram values as the handout explained. However, I noticed that the runtime is significantly slower for this part because of the two for loops that were used.

Here is the histogram that I obtained, and comparing it with the NCC space we see that the histogram corresponds with the expected distribution for the image used. I had to rotate it by 90 degrees counterclockwise to move the origin to the third quadrant, so I can compare the histogram plot with the color space.

Figure 3. (a) Histogram of the ROI in terms of the normalized color coordinates.
(b) The normalized color coordinates. We see that the color of the ROI falls in the
expected area in the NCC space.

Now comes the back-projection. First, for each r and g, I rounded them off to integers and obtained the corresponding value in the histogram. The code is below. Here is my result for non-parametric segmentation.


Figure 4. (a) The segmented image using non-parametric segmentation.
(b) Histogram of r. (c) Histogram of g.

Comparing the two results, there is not much significance, since the image consists of just one color. Also, if we look at the histogram of r and g, we can see that a Gaussian distribution approximates the pdf well. So I tried segmenting an image with different colors present. I also added here the histogram of r and g. Here are my results:

 Figure 5. Image with different colors. (b) Cropped monochromatic
region of interest.

Figure 6. Results for (a) parametric and (b) non-parametric color
image segmentation.

 Figure 7. Histogram of the image (a) in r; (b) in g.

From what I see, the parametric segmentation gave the better results, even if the histograms looks like the ones above. I actually don't know why the parametric technique works, so I cannot comment further than this. I think that it has something to do with the image not having a high contrast. If the colors appear more distinct from each other, I think we will have better results.

Grade I give myself: 10/10. I can't give myself the bonus points because, even if I was able to meet the minimum requirements, I was not able to extend the activity because I was not able to master this exercise completely. However I am fairly satisfied with my work.

Appendix: Code used in this activity

path = 'C:\mypath';

//load RGB for cropped image
im = imread(path+'\cropped14.png');
imR = mat2gray(im(:,:,1));
imG = mat2gray(im(:,:,2));
imB = mat2gray(im(:,:,3));

//obtain r,g for cropped image
I = (imR + imG) + imB;
I(find(I==0))=100000;
r = imR./I;
g = imG./I;
b = 1.0-r-g;
//imshow(I);

//HISTOGRAM for cropped image: from Act9 handout
BINS = 32;
rint = round(r*(BINS-1) + 1); //ranges from 1 to 32
gint = round(g*(BINS-1) + 1);
colors = gint(:) + (rint(:)-1)*BINS;
hist = zeros(BINS, BINS);
for row = 1:BINS
    for col = 1:(BINS-row+1)
        hist(row, col) = length(find(colors==( ((col + (row-1)*BINS)))));
    end;

end;

//compute for mean and stdev of r and g
mean_r = mean(r);
stdev_r = stdev(r);
mean_g = mean(g);
stdev_g = stdev(g);

//load entire image
im_whole = imread(path+'\photo0056_2.png');
imR = mat2gray(im_whole(:,:,1));
imG = mat2gray(im_whole(:,:,2));
imB = mat2gray(im_whole(:,:,3));

//obtain r,g for entire image
I = (imR + imG) + imB;
I(find(I==0))=100000;
r = imR./I;
g = imG./I;

//FOR PARAMETRIC SEGMENTATION//
//joint probability
pr = 1/(stdev_r * sqrt(2 * %pi)) * exp(-((r - mean_r).^2)/(2*(stdev_r^2)));
pg = 1/(stdev_g * sqrt(2 * %pi)) * exp(-((g - mean_g).^2)/(2*(stdev_g^2)));
joint_p = pr .* pg;
imshow(joint_p);       //result of parametric

//FOR NONPARAMETRIC SEGMENTATION//
//BACK-PROJECTION: slow, optimize by vectorizing
s = size(r);
rows = s(1);
columns = s(2);
im2 = zeros(rows, columns);
for i=1:rows
    for j=1:columns
        r_val = r(i, j);
        g_val = g(i, j);
        // round off since hist has only 32 bins
        r_int = round(r_val*(BINS-1) + 1);
        g_int = round(g_val*(BINS-1) + 1);
        // replace pixel with the value
        im2(i,j) = hist(r_int, g_int);
    end;
end;

imshow(im2);            //result of nonparametric

No comments:

Post a Comment