-1
% OTSU THRESHOLDING
% X=imread('cameraman.tif')
% a=ones(256,1)*[1:256];
% c2=double(X).*(a/2+50)+(1-double(X)).*a/2;
% c3=uint8(255*mat2gray(c2));
% IDX = otsu(c3,2); 
%----------------------------------------------------------
%
% function [IDX,sep] = otsu(I,n)

I = single(I);

    %% Convert to 256 levels
    I = I-min(I(:));
    I = round(I/max(I(:))*255);

    %% Probability distribution
    unI = sort((I));
    nbins = min(length(unI),256);

    [histo,pixval] = hist(I(:),256);

    P = histo/sum(histo);


    %% Zeroth- and first-order cumulative moments
    w = cumsum(P);
    mu = cumsum((1:nbins).*P);

    %% Maximal sigmaB^2 and Segmented image
    if n==2
        sigma2B =...
            (mu(end)*w(1:end-1)-mu(1:end-1)).^2./w(1:end-1)./(1-w(1:end-1));

        [maxsig,k] = max(sigma2B);
        k

This is the code i am using to find the Otsu threshold(2 class only). So after finding the optimal threshold ie k , How to compute the thresholded image?? how to change each image pixel value < k = 0 and >= k = 1 such that it creates a binary image?

Fleron-X
  • 182
  • 1
  • 11

2 Answers2

0

Given your threshold k, you can simply use a binary operation to compute your thresholded image.

Simply put, if I is your image, the thresholded image can be computed like so:

outThreshold = I >= k;

You can also use outThreshold = im2bw(I,k); that will do the same operation (thanks @Daniel!). It essentially performs what I just described above.

In any case, this returns a binary map where pixels that have an intensity that is greater than or equal to k get set to true / 1 while those that are less than k are set to false / 0. Here's an example using graythresh. MATLAB has a built-in threshold finding algorithm using Otsu by graythresh.

I = imread('cameraman.tif'); %// Built-in to MATLAB - A grayscale image
k = 255*graythresh(im); %// Output is scaled between 0 - 1.  
                        %//Multiply by 255 to get 8-bit intensity
subplot(1,2,1);
imshow(I);
outThresh = I >= k;
subplot(1,2,2);
imshow(outThresh);

As such, you get this figure:

enter image description here

Locations that are white denote those pixels that surpass the threshold while locations that are black are those that didn't.


From your comments (you really should have just updated your post), you wish to seek a method that performs multi-thresholding. This is still quite simple. Supposing you had an array of thresholds like so:

thresholds = [32 96 128 192];

What this is saying is that there are five regions we need to consider:

  • Pixels with intensity values between 0 to 31
  • Pixels with intensity values between 32 to 95
  • Pixels with intensity values between 96 to 127
  • Pixels with intensity values between 128 to 191
  • Pixels with intensity values between 192 to 255

Note that for this example, the upper end is exclusive. As such, we don't include the end interval, but we do include this number in the next interval and we assign this to be the lower end of the interval.

We can simply use a for loop and create a map variable that finds all pixels within each range and sets them to an ID number. Let's give these all an ID in increasing order, so the first region gets assigned an ID of 1, the next gets and ID of 2 and so on. This is the code that would do it:

map = zeros(size(I));

thresholdArray = [0 thresholds 255];

for k = 1 : numel(thresholdArray)-1
    lower = thresholdArray(k);
    upper = thresholdArray(k+1);

    map(I >= lower & I < upper) = k;
end

%// Rescale to 0 - 255
outMap = uint8(255*(map - min(map(:))) / (max(map(:)) - min(map(:))));

figure;
subplot(2,2,1);
imshow(I);
subplot(2,2,2);
imhist(I);
subplot(2,2,3);
imshow(outMap);
subplot(2,2,4);
imhist(outMap);

This is what the output looks like:

enter image description here

The code performs multi-thresholding, as well as displaying the original image with its histogram as well as the thresholded image with its histogram. Note that I have rescaled the output map so that it goes from 0 to 255. As such, each class gets assigned a value that is a multiple of (256 / numThresholds). In this case, it is 64.

rayryeng
  • 96,704
  • 21
  • 166
  • 177
0

im2bw(I,p) Converts the image I to a black and white image using the threshold p

Daniel
  • 36,007
  • 3
  • 31
  • 64
  • I was expecting more of a like logical algorithm using 'for loop' and 'if conditions' because what would i do if i have 2/3 threshold values and have to make a 3/4 class thresholded image, then?? Also only if u do it, can u upload the just thresholded image so that i may see it. if i put IDX= zeros(size(I)); IDX(I>=pixval(k)) = 1; figure;imagesc(IDX);title([pixval(k) k]);axis image off;colormap(gray); I know i am not changing the image to a binary form but still why does figure;hist(IDX); give me a multicoloured histogram of varying values?? & @rayryeng – Fleron-X Jun 18 '14 at 03:23
  • @bcool93 - That wasn't clear in your post. You only wanted the 2 class case. If you want to multi-threshold your image, you should set the pixel in your image corresponding to the **class** that it belongs to, and not just `1`. `0/1` was just for the binary case. I'll modify my post accordingly. – rayryeng Jun 18 '14 at 14:11