two-dimensional Otsu's method
3 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Harsha
el 29 de En. de 2016
Comentada: Image Analyst
el 13 de Nov. de 2020
I am trying to implement 2D Otsu segmentation method, but i am facing problem in my code. in 2D otsu the gray-level value of each pixel as well as the average value of its immediate neighborhood is studied so that the binarization results are greatly improved. I am attaching code,but it is not working and also hyperlink http://en.wikipedia.org/wiki/Otsu%27s_method
function inputs and output:
%hists is a 256\times 256 2D-histogram of grayscale value and neighborhood average grayscale value pair.
%total is the number of pairs in the given image.
%threshold is the threshold obtained.
function threshold = 2D_otsu(hists, total)
maximum = 0.0;
threshold = 0;
helperVec = 0:255;
mu_t0 = sum(sum(repmat(helperVec',1,256).*hists));
mu_t1 = sum(sum(repmat(helperVec,256,1).*hists));
p_0 = zeros(256);
mu_i = p_0;
mu_j = p_0;
for ii = 1:256
for jj = 1:256
if jj == 1
if ii == 1
p_0(1,1) = hists(1,1);
else
p_0(ii,1) = p_0(ii-1,1) + hists(ii,1);
mu_i(ii,1) = mu_i(ii-1,1)+(ii-1)*hists(ii,1);
mu_j(ii,1) = mu_j(ii-1,1);
end
else
p_0(ii,jj) = p_0(ii,jj-1)+p_0(ii-1,jj)-p_0(ii-1,jj-1)+hists(ii,jj);
mu_i(ii,jj) = mu_i(ii,jj-1)+mu_i(ii-1,jj)-mu_i(ii-1,jj-1)+(ii-1)*hists(ii,jj);
mu_j(ii,jj) = mu_j(ii,jj-1)+mu_j(ii-1,jj)-mu_j(ii-1,jj-1)+(jj-1)*hists(ii,jj);
end
if (p_0(ii,jj) == 0)
continue;
end
if (p_0(ii,jj) == total)
break;
end
tr = ((mu_i(ii,jj)-p_0(ii,jj)*mu_t0)^2 + (mu_j(ii,jj)-p_0(ii,jj)*mu_t0)^2)/(p_0(ii,jj)*(1-p_0(ii,jj)));
if ( tr >= maximum )
threshold = ii;
maximum = tr;
end
end
end
3 comentarios
Prabhu Bevinamarad
el 13 de Nov. de 2020
Hi,
I am new to Matlab. I wanted to apply two-dimensional Otsu's method for thresholding. I am not getting how to find hists i.e. 2D-histogram of grayscale value and neighborhood average grayscale value pair and total is the number of pairs in the given image which are passed as a parameters for otsu_2D function.Can anybody suggest which functions are used.
Thank you
Respuesta aceptada
Geoff Hayes
el 29 de En. de 2016
pramod - the error message is telling you that the code is trying to access an element within your matrix using an index that is zero. I realize that you are considering the neighbourhood surrounding each cell within your 256x256 matrix, but your code will have to account for the edge cases when subtracting one from the index leads to a zero which "falls" outside of your matrix. You will have to guard against this code as follows
for ii = 1:256
for jj = 1:256
if jj == 1
if ii == 1
p_0(1,1) = hists(1,1);
else
p_0(ii,1) = p_0(ii-1,1) + hists(ii,1);
mu_i(ii,1) = mu_i(ii-1,1)+(ii-1)*hists(ii,1);
mu_j(ii,1) = mu_j(ii-1,1);
end
else
% here is the new code ***** guard against ii==1
if ii==1
p_0(ii,jj) = p_0(ii,jj-1)+hists(ii,jj);
mu_i(ii,jj) = mu_i(ii,jj-1)+(ii-1)*hists(ii,jj);
mu_j(ii,jj) = mu_j(ii,jj-1)+(jj-1)*hists(ii,jj);
else
p_0(ii,jj) = p_0(ii,jj-1)+p_0(ii-1,jj)-p_0(ii-1,jj-1)+hists(ii,jj);
mu_i(ii,jj) = mu_i(ii,jj-1)+mu_i(ii-1,jj)-mu_i(ii-1,jj-1)+(ii-1)*hists(ii,jj);
mu_j(ii,jj) = mu_j(ii,jj-1)+mu_j(ii-1,jj)-mu_j(ii-1,jj-1)+(jj-1)*hists(ii,jj);
end
end
I don't know for sure if the above is correct but it will guard against the case where jj is greater than one and ii is equal to one (the pattern is similar to what is already there for the case where jj is one and ii is one). A note should be added to the Wikipedia article indicating that there is a bug with the code.
ImageAnalyst would have a better idea as to whether the above makes sense or not.
And, rather than posting a binary zip file which some of us may be reluctant to open, just attach each file individually (since there are just three).
10 comentarios
Image Analyst
el 13 de Nov. de 2020
No idea what this means exactly but as far as I can tell, it's this:
% Read in input image f(x,y) with L = 256 gray levels:
fxy = imread('cameraman.tif');
% No idea what "The local average gray level is also divided into the same L values" means,
% but to get an image where each pixel is the average in a square window around the pixel, do thi
windowWidth = 3; % Whatever you want.
kernel = ones(windowWidth, windowWidth) / windowWidth^2;
gxy = imfilter(fxy, kernel);
% Now get the total number of pixels in fxy and gxy:
total = numel(fxy)
Note that images are indexed fxy(y, x), which is fxy(row, column), and NOT as fxy(x, y).
But gxy is simply a blurred input image -- the local average. It is not a 2-D histogram. I'm wondering if he wants 256 histograms, one for the neighbors of each pixel (not including the pixel itself), like
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
fprintf('Beginning to run %s.m ...\n', mfilename);
echo off;
%===============================================================================
% Get the name of the demo image the user wants to use.
% Let's let the user select from a list of all the demo images that ship with the Image Processing Toolbox.
folder = fileparts(which('cameraman.tif')); % Determine where demo folder is (works with all versions).
% Demo images have extensions of TIF, PNG, and JPG. Get a list of all of them.
imageFiles = [dir(fullfile(folder,'*.TIF')); dir(fullfile(folder,'*.PNG')); dir(fullfile(folder,'*.jpg'))];
for k = 1 : length(imageFiles)
% fprintf('%d: %s\n', k, files(k).name);
[~, baseFileName, extension] = fileparts(imageFiles(k).name);
ca{k} = [baseFileName, extension];
end
% Sort the base file names alphabetically.
[ca, sortOrder] = sort(ca);
imageFiles = imageFiles(sortOrder);
button = menu('Use which gray scale demo image?', ca); % Display all image file names in a popup menu.
% Get the base filename.
baseFileName = imageFiles(button).name; % Assign the one on the button that they clicked on.
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
grayImage = imread(fullFileName);
[rows, columns, numberOfColorChannels] = size(grayImage);
if numberOfColorChannels == 3
grayImage = rgb2gray(grayImage);
end
subplot(2, 1, 1);
imshow(grayImage);
caption = sprintf('Original gray scale image : %s', baseFileName);
title('Original gray scale image');
drawnow;
% Intantiate 2-D histogram
hist2d = zeros(256, 256);
for col = 2 : columns-1
fprintf('Processing column %d of original image...\n', col);
for row = 2 : rows-1
% Get 3x3 subimage, except for center pixel, so that's 8 pixels.
subImage = [grayImage(row-1, col-1);...
grayImage(row-1, col);...
grayImage(row-1, col+1);...
grayImage(row, col-1);...
grayImage(row, col+1);...
grayImage(row+1, col+1);...
grayImage(row+1, col+1);...
grayImage(row+1, col+1)];
% Get the gray levle of the center pixel
centerGL = grayImage(row, col) + 1; % Add 1 so we don't get 0 because matrices can't have a zeroeth row or column.
for k = 1 : length(subImage)
% Get this gray level
thisGL = subImage(k) + 1; % Add 1 so we don't get 0 because matrices can't have a zeroeth row or column.
% Increment the histogram at the column for the center pixel's gray level
hist2d(centerGL, thisGL) = hist2d(centerGL, thisGL) + 1;
end
end
end
% Display the 2-D histogram
subplot(2, 1, 2);
imshow(hist2d, [], 'Colormap', jet(256));
title('2D histogram');
colorbar

Más respuestas (1)
Harsha
el 4 de Dic. de 2016
5 comentarios
Image Analyst
el 23 de Feb. de 2018
Madhava, I don't understand what you said.
MAS
el 5 de Abr. de 2018
It works absolutely fine for two clusters. Any suggestions to update it for handling multi-level thresholding!?
Ver también
Categorías
Más información sobre Computer Vision with Simulink en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!