Mercurial > hg > octave-image
changeset 631:b2bc91ce5697
graythresh: make build histogram common code and deal with different image types
author | carandraug |
---|---|
date | Sun, 30 Sep 2012 16:15:03 +0000 |
parents | 039a1c0141b3 |
children | d874709a9a27 |
files | inst/graythresh.m |
diffstat | 1 files changed, 76 insertions(+), 125 deletions(-) [+] |
line wrap: on
line diff
--- a/inst/graythresh.m +++ b/inst/graythresh.m @@ -145,7 +145,6 @@ ## MaxEntropy MaxLikelihood intermeans ## moments minerror concavity - function [varargout] = graythresh (img, algo = "otsu", varargin) # Input checking if (nargin < 1 || nargin > 3) @@ -161,44 +160,69 @@ img = rgb2gray (img); endif + ## the "mean" is the simplest of all, we can get rid of it right here + if (strcmpi (algo, "mean")) + varargout{i} = mean (im2double(img)(:)); + return + endif + + ## if image is uint we do nothing. If it's int, then we convert to uint since + ## it may mess up calculations later. If it's double we need some bins so we + ## choose uint8 by default... but should we adjust the histogram before? + if (isa (img, "uint16") || isa (img, "uint8")) + ## do nothing + elseif (isa (img, "int16")) + img = im2uint16 (img); + img_max = 65535; + else + img = im2uint8 (img); + endif + img_max = double (intmax (class (img))); + + ## all of this methods are based on the image histogram we can prepare it here + ## and avoid a lot of repeated code + ihist = hist (img(:), 0:img_max); + switch tolower (algo) - case {"concavity"}, thresh = concavity (img); - case {"intermeans"}, thresh = intermeans (img); - case {"intermodes"}, thresh = intermodes (img); - case {"maxlikelihood"}, thresh = maxlikelihood (img); - case {"maxentropy"}, thresh = maxentropy (img); - case {"mean"}, thresh = mean (img(:)); - case {"minimum"}, thresh = minimum (img); - case {"minerror"}, thresh = minerror_iter (img); - case {"moments"}, thresh = moments (img); - case {"otsu"}, thresh = otsu (img, nargout > 1); - case {"percentile"}, thresh = percentile (img, varargin{1}); + case {"concavity"}, thresh = concavity (ihist); + case {"intermeans"}, thresh = intermeans (ihist, floor (mean (img (:)))); + case {"intermodes"}, thresh = intermodes (ihist); + case {"maxentropy"}, thresh = maxentropy (ihist); + case {"maxlikelihood"}, thresh = maxlikelihood (ihist); + case {"minerror"}, thresh = minerror_iter (ihist, floor (mean (img (:)))); + case {"minimum"}, thresh = minimum (ihist); + case {"moments"}, thresh = moments (ihist); + case {"otsu"}, thresh = otsu (ihist, nargout > 1); + case {"percentile"}, thresh = percentile (ihist, varargin{1}); otherwise, error ("graythresh: unknown method '%s'", algo); endswitch - + ## normalize the threshold value to the [0 1] range + thresh{1} = double (thresh{1}) / img_max; + + ## some algorithms may return more than one value... for i = 1:numel (thresh) varargout{i} = thresh{i}; endfor endfunction -function [thresh] = otsu (img, compute_wcv) +function [thresh] = otsu (ihist, compute_wcv) ## this method is quite well explained at ## http://www.labbookpages.co.uk/software/imgProc/otsuThreshold.html ## ## The implemententation on the link above assumes that threshold is to be ## made for values "greater or equal than" but that is not the case (in im2bw ## and also not ImageJ) so we subtract 1 at the end. - bins = 0:255; - xx = hist (img(:), bins); + bins = 0:(numel (ihist) - 1); + total = sum (ihist); ## b = black, w = white - b_totals = cumsum ([0 xx(1:end-1)]); - b_weights = b_totals / sum (xx); - b_means = [0 cumsum(bins(1:end-1) .* xx(1:end-1))] ./ b_totals; + b_totals = cumsum ([0 ihist(1:end-1)]); + b_weights = b_totals / total; + b_means = [0 cumsum(bins(1:end-1) .* ihist(1:end-1))] ./ b_totals; - w_totals = sum (xx) - b_totals; - w_weights = w_totals / sum (xx); - w_means = (cumsum (bins(end:-1:1) .* xx(end:-1:1)) ./ w_totals(end:-1:1))(end:-1:1); + w_totals = total - b_totals; + w_weights = w_totals / total; + w_means = (cumsum (bins(end:-1:1) .* ihist(end:-1:1)) ./ w_totals(end:-1:1))(end:-1:1); ## the original method is to find the minimum within class variance. However ## this is more intensive and can be replaced by finding the maximum of the @@ -214,16 +238,8 @@ endif endfunction -function level = moments (I, n) - - if nargin == 1 - n = 255; - end - - I = double(I); - - % Calculate the histogram. - y = hist (I(:), 0:n); +function level = moments (y) + n = numel (y) - 1; % The threshold is chosen such that partial_sumA(y,t)/partial_sumA(y,n) is closest to x0. Avec = zeros (1, n+1); @@ -239,21 +255,11 @@ % And finally the threshold. [minimum, ind] = min (abs (Avec-x0)); - level = ind-1; - - ## Normalisation of the threshold - level /= n; + level{1} = ind-1; endfunction -function T = maxentropy(I,n) - if nargin == 1 - n = 255; - end - - I = double(I); - - % Calculate the histogram. - y = hist(I(:),0:n); +function T = maxentropy(y) + n = numel (y) - 1; warning off % The threshold is chosen such that the following expression is minimized. @@ -264,18 +270,11 @@ warning on [minimum,ind] = min(vec); - T = ind-1; + T{1} = ind-1; endfunction -function [T] = intermodes (I,n) - if nargin == 1 - n = 255; - end - - I = double(I); - - % Calculate the histogram. - y = hist(I(:),0:n); +function [T] = intermodes (y) + n = numel (y) - 1; % Smooth the histogram by iterative three point mean filtering. iter = 0; @@ -298,21 +297,11 @@ TT(ind) = k-1; end end - T = floor(mean(TT)); + T{1} = floor(mean(TT)); endfunction -function [T] = percentile (I, p, n) - if nargin == 1 - p = 0.5; - n = 255; - elseif nargin == 2 - n = 255; - end - - I = double(I); - - % Calculate the histogram. - y = hist(I(:),0:n); +function [T] = percentile (y, p) + n = numel (y) - 1; % The threshold is chosen such that 50% of pixels lie in each category. Avec = zeros(1,n+1); @@ -321,19 +310,12 @@ end [minimum,ind] = min(abs(Avec-p)); - T = ind-1; + T{1} = ind-1; endfunction -function T = minimum(I,n); - if nargin == 1 - n = 255; - end - - I = double(I); - - % Calculate the histogram. - y = hist(I(:),0:n); +function T = minimum(y) + n = numel (y) - 1; % Smooth the histogram by iterative three point mean filtering. iter = 0; @@ -343,7 +325,7 @@ iter = iter+1; % If the histogram turns out not to be bimodal, set T to zero. if iter > 10000; - T = 0; + T{1} = 0; return end end @@ -351,23 +333,14 @@ % The threshold is the minimum between the two peaks. for k = 2:n if y(k-1) > y(k) && y(k+1) > y(k) - T = k-1; + T{1} = k-1; end end endfunction -function [T] = minerror_iter (I,n) - if nargin == 1 - n = 255; - end +function [T] = minerror_iter (y, T) + n = numel (y) - 1; - I = double(I); - - % Calculate the histogram. - y = hist(I(:),0:n); - - % The initial estimate for the threshold is found with the MEAN algorithm. - T = floor (mean (I, img(:))); Tprev = NaN; while T ~= Tprev @@ -395,12 +368,12 @@ % The updated threshold is the integer part of the solution of the % quadratic equation. Tprev = T; - T = floor((w1+sqrt(sqterm))/w0); + T{1} = floor((w1+sqrt(sqterm))/w0); % If the threshold turns out to be NaN, return with the previous threshold. if isnan(T) warning('MINERROR:NaN','Warning: th_minerror_iter did not converge.') - T = Tprev; + T{1} = Tprev; end end @@ -438,19 +411,12 @@ endfunction #} -function T = maxlikelihood (I,n) - if nargin == 1 - n = 255; - end - - I = double(I); - - % Calculate the histogram. - y = hist(I(:),0:n); +function T = maxlikelihood (y) + n = numel (y) - 1; % The initial estimate for the threshold is found with the MINIMUM % algorithm. - T = th_minimum(I,n); + T = minimum (y); % Calculate initial values for the statistics. mu = partial_sumB(y,T)/partial_sumA(y,T); @@ -507,21 +473,12 @@ % The threshold is the integer part of the solution of the quadratic % equation. - T = floor((w1+sqrt(sqterm))/w0); + T{1} = floor((w1+sqrt(sqterm))/w0); endfunction -function T = intermeans (I,n) - if nargin == 1 - n = 255; - end +function T = intermeans (y, T) + n = numel (y) - 1; - I = double(I); - - % Calculate the histogram. - y = hist(I(:),0:n); - - % The initial estimate for the threshold is found with the MEAN algorithm. - T = floor (mean (I, img(:))); Tprev = NaN; % The threshold is found iteratively. In each iteration, the means of the @@ -533,17 +490,11 @@ Tprev = T; T = floor((mu+nu)/2); end + T{1} = T; endfunction -function T = concavity (I,n) - if nargin == 1 - n = 255; - end - - I = double(I); - - % Calculate the histogram and its convex hull. - h = hist(I(:),0:n); +function T = concavity (h) + n = numel (y) - 1; H = hconvhull(h); % Find the local maxima of the difference H-h. @@ -557,7 +508,7 @@ % The threshold is the local maximum with highest balance. E = E.*lmax; [dummy ind] = max(E); - T = ind-1; + T{1} = ind-1; endfunction ################################################################################