Otsu Algorithm Segmentation
Otsu Algorithm Segmentation
ECE 661
Aziza Satkhozhina
[email protected]
Goals
The goal of this homework is to implement Otsu’s binary segmentation and
contour extraction algorithm.
Otsu’s algorithm
Otsu’s segmentation algorithm automatically clusters pixels into two groups:
background and foreground. The main idea of Otsu’s algorihtm is to find
threshold that would maximize between-class variance and minimize within-
class variance. Then, all pixels are classified into 2 classes using that threshold.
First step is to create a histogram of pixel values. Since we are taking 8-bit
image, there are 256 possible values for pixels. We compute histogram h with
256 bins where the height of each bin corresponds to number of pixels that have
that pixel value (from 0 to 255).
1
Pk 1
P256
µ1 = w0 i=1 ipi and µ2 = i=k+1 ipi
w1
.
It is sufficient to increase between class variance σb2 = w0 w1 (µ0 − µ1 )2 . This
will decrease within-class variance too. I calculated the between-class variance
for each threshold k and picked the threshold that maximizes the variance.
Depending on the image, sometimes Otsu’s algorithm was run several times for
better results.
Each of the RGB channels of color image was segmented separately. Then,
1
I combined results from RGB channels using AND operator, where I set the
final segmented image pixel to 1 only if all three segmented channels have 1 at
that pixel location. I also had to specify manually which class is foreground and
which is background.
Texture segmentation
To perform texture segmentation, I first converted RGB image into grayscale
using standard formula: I = 0.2989R + 0.5870G + 0.1140B. I then followed a
simple approach by calculating the variance of gray scale image in N xN window.
I performed texture segmentation for three values of N = 3, 5, 7 and combined
all three results into one 3-channel image. Then, texture image is fed into Otsu’s
algorithm the same way as RGB image.
Step 1) Set n = 0.
Step 2) For pixel img(x, y), define its 4 neighbors as pixels located at the
following locations (x − 1, y), (x − 1, y − 1), (x, y − 1), (x + 1, y − 1). If all of its
neighboring pixels have value of 0, then increment the value of n by 1 and set
img(x, y) to n. Otherwise, find the minimum non-zero value of its neighbors, and
set img(x, y) to that value. Record the values of the neighbors into equivalence
list.
Step 4) After all pixels were processed and united into connected compo-
nents, it is necessary to unite connected components using the equivalence list.
Do a second pass on the image and unite all connected components.
Step 6) Optional. Delete connected components whose size is less than 100
pixels to get rid of noise.
2
Contour extraction
I implemented Square Tracing algorithm, one of the earliest contour detection
algorithms. The pseudocode is below and it is applied to each connected com-
ponent ci separately.
Step 2) Scan the pixels and find first non-zero pixel of ci at location px, py.
Insert the locations of the pixel into list B.
Step 4) At location x, y if the current pixel value is 1, then insert the location
into set B and move to the left. If current pixel value is 0, move to the right.
Left and right are defined as follows. Initially, if you are at pixel location
x, y, ”North” is defined as moving to the pixel at location x, y − 1, ”South” to
location x, y + 1, ”West” to location x − 1, y, and ”East” to location x + 1, y.
However, once we start moving, the direction is defined by the previous move.
Every move changes the coordinate system, therefore ”right”, ”left” is relative
to the previos move. It is summarized below:
If (prevDirection == “N orth00 )
lef t => W est
right => East
elseif (prevDirection == “South00 )
lef t => East
right => W est
elseif (prevDirection == “W est00 )
lef t => South
right => N orth
elseif (prevDirection == “East00 )
lef t => N orth
right => South
end
Results
Otsu’s algoruthm applied on the texture features performs much better than
RGB channels. In Pic 1. for example, the lake and the trees have approximately
same amount of red and green, however lake has much more blue color in it.
Therefore Blue color would be suitable for segmentation, while red and green
channels make the result more noisy. Texture feature looks at the smootheness
3
of the region, therefore it is a better feature for extracting objects from an image
(especially for the lake). Pic 2 was a difficult image to segment as the tiger has
multiple colors, and the colors match his background. Also the texture of the
tiger is not uniform, so it is difficult to segment it using texture segmentation
as well.
Output images
(c) B channel
4
Figure 3: Pic.1 Texture Image
5
Figure 4: Otsu segmentation of Pic. 1
6
Figure 5: Pic.1 Connected Component
7
Figure 7: Original pic. 2
8
Figure 9: Otsu segmentation of Pic. 2
9
Figure 10: Pic. 2 Connected Component
10
Matlab code
%****************************************************************************
%****************************************************************************
img = imread('pic2.jpg');
str = 'pic2';
s = size(img);
%****************************************************************************
%****************************************************************************
%****************************************************************************
%****************************************************************************
for i = 1+w:s(1)-w
for j = 1+w:s(2)-w
patch = img(i-w:i+w, j-w:j+w);
patch = patch(:);
m = mean(patch);
tim(i,j) = 1/length(patch)*sum((patch-m).^2);
end
end
%****************************************************************************
%****************************************************************************
s = size(img);
n = 1;
cnt = 0;
for i = 1:s(1)
for j = 1:s(2)
if(img(i,j)>1)
ind = find(k==img(i,j));
img(i,j) = ind;
end
end
end
%****************************************************************************
%****************************************************************************
k = unique(unique(img));
k(find(k==0))=[];
for i = 1:length(k)
[row col] = find(img == k(i));
if(length(row)< N)
for j = 1:length(row)
img(row(j),col(j))=0;
end
end
end
%****************************************************************************
%****************************************************************************
for i = 1:length(k)
[row col] = find(img_con == k(i));
I = zeros(size(img_con));
x = x - 1;
for i = 1:size(B,1)
cont(B(i,1),B(i,2))=1;
end
end