Mercurial > forge
changeset 10961:61f55d704990 octave-forge
graythresh: implementation of concavity, intermeans, intermodes, MaxEntropy, MaxLikelihood, mean, minimum, MinError, moments and percentile methods from the HistThresh toolbox
author | carandraug |
---|---|
date | Wed, 26 Sep 2012 17:47:56 +0000 |
parents | fdc0d1b65f8d |
children | 78f697849281 |
files | main/image/NEWS main/image/inst/graythresh.m |
diffstat | 2 files changed, 550 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/main/image/NEWS Wed Sep 26 15:30:09 2012 +0000 +++ b/main/image/NEWS Wed Sep 26 17:47:56 2012 +0000 @@ -41,8 +41,17 @@ GPL license. Currently, the following algorithms have been implemented (see graythresh for notes and references): + concavity + intermeans + intermodes + MaxEntropy + MaxLikelihood + mean + minimum + MinError moments otsu + percentile ** The following functions have been deprecated (see their help text for the recommended alternatives): @@ -109,4 +118,6 @@ ** Package is now dependent on GNU Octave version 3.6.0 or later. + ** Package is now dependent on the signal package version 1.2.0 or later.. + ** Package is no longer automatically loaded.
--- a/main/image/inst/graythresh.m Wed Sep 26 15:30:09 2012 +0000 +++ b/main/image/inst/graythresh.m Wed Sep 26 17:47:56 2012 +0000 @@ -19,6 +19,7 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img}) ## @deftypefnx {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img}, @var{algo}) +## @deftypefnx {Function File} {[@var{level}] =} graythresh (@var{img}, "percentile", @var{fraction}) ## Compute global image threshold. ## ## Given an image @var{img} finds the optimal threshold value @var{level} for @@ -29,48 +30,95 @@ ## Otsu). The available algorithms are: ## ## @table @asis -## @item "Otsu" (default) +## @item Otsu (default) ## Implements Otsu's method as described in @cite{Nobuyuki Otsu (1979). "A -## threshold selection method from gray-level histograms". IEEE Trans. Sys., +## threshold selection method from gray-level histograms", IEEE Trans. Sys., ## Man., Cyber. 9 (1): 62-66}. This algorithm chooses the threshold to minimize ## the intraclass variance of the black and white pixels. The second output, ## @var{sep} represents the ``goodness'' (or separability) of the threshold at ## @var{level}. ## +## @item concavity +## Find a global threshold for a grayscale image by choosing the threshold to +## be in the shoulder of the histogram @cite{A. Rosenfeld, and P. De La Torre +## (1983). "Histogram concavity analysis as an aid in threshold selection", IEEE +## Transactions on Systems, Man, and Cybernetics, 13: 231-235}. +## ## @item Huang ## Not yet implemented. ## ## @item ImageJ +## A variation of the intermeans algorithm, this is the default for ImageJ. ## Not yet implemented. ## ## @item intermodes -## Not yet implemented. +## This assumes a bimodal histogram and chooses the threshold to be the mean of +## the two peaks of the bimodal histogram @cite{J. M. S. Prewitt, and M. L. +## Mendelsohn (1966). "The analysis of cell images", Annals of the New York +## Academy of Sciences, 128: 1035-1053}. +## +## Images with histograms having extremely unequal peaks or a broad and flat +## valley are unsuitable for this method. ## -## @item IsoData -## Not yet implemented. +## @item intermeans +## Iterative procedure based on the iterative intermeans algorithm of @cite{T. +## Ridler, and S. Calvard (1978). "Picture thresholding using an iterative +## selection method", IEEE Transactions on Systems, Man, and Cybernetics, 8: 630-632} +## and @cite{H. J. Trussell (1979). "Comments on 'Picture thresholding using an +## iterative selection method'", IEEE Transactions on Systems, Man, and Cybernetics, +## 9: 311}. +## +## Note that several implementations of this method exist. See the source code +## for details. ## ## @item Li ## Not yet implemented. ## ## @item MaxEntropy -## Not yet implemented. +## Implements Kapur-Sahoo-Wong (Maximum Entropy) thresholding method based on the +## entropy of the image histogram @cite{J. N. Kapur, P. K. Sahoo, and A. C. K. Wong +## (1985). "A new method for gray-level picture thresholding using the entropy +## of the histogram", Graphical Models and Image Processing, 29(3): 273-285}. +## +## @item MaxLikelihood +## Find a global threshold for a grayscale image using the maximum likelihood +## via expectation maximization method @cite{A. P. Dempster, N. M. Laird, and D. B. +## Rubin (1977). "Maximum likelihood from incomplete data via the EM algorithm", +## Journal of the Royal Statistical Society, Series B, 39:1-38}. ## ## @item mean -## Not yet implemented. +## The mean intensity value. It is mostly used by other methods as a first guess +## threshold. ## ## @item MinError -## Not yet implemented. +## An iterative implementation of Kittler and Illingworth's Minimum Error +## thresholding @cite{J. Kittler, and J. Illingworth (1986). "Minimum error +## thresholding", Pattern recognition, 19: 41-47}. +## +## This implementation seems to converge more often than the original. +## Nevertheless, sometimes the algorithm does not converge to a solution. In +## that case a warning is displayed and defaults to the initial estimate of the +## mean method. ## ## @item minimum -## Not yet implemented. +## This assumes a bimodal histogram and chooses the threshold to be in the +## valley of the bimodal histogram. This method is also known as the mode +## method @cite{J. M. S. Prewitt, and M. L. Mendelsohn (1966). "The analysis of +## cell images", Annals of the New York Academy of Sciences, 128: 1035-1053}. +## +## Images with histograms having extremely unequal peaks or a broad and flat +## valley are unsuitable for this method. ## ## @item moments ## Find a global threshold for a grayscale image using moment preserving -## thresholding method @cite{W. Tsai (1985), "Moment-preserving thresholding: -## a new approach," Computer Vision, Graphics, and Image Processing, 29: 377-393} +## thresholding method @cite{W. Tsai (1985). "Moment-preserving thresholding: +## a new approach", Computer Vision, Graphics, and Image Processing, 29: 377-393} ## ## @item percentile -## Not yet implemented. +## Assumes a specific @var{fraction} of pixels to be background. If no value is +## given, assumes a value of 0.5 (equal distribution of background and foreground) +## @cite{W Doyle (1962). "Operation useful for similarity-invariant pattern +## recognition", Journal of the Association for Computing Machinery 9: 259-267} ## ## @item RenyiEntropy ## Not yet implemented. @@ -92,11 +140,15 @@ ## * Otsu's method is a function taken from ## http://www.irit.fr/~Philippe.Joly/Teaching/M2IRR/IRR05/ Søren Hauberg ## added texinfo documentation, error checking and sanitised the code. -## * Moment's algorithm was adapted from http://www.cs.tut.fi/~ant/histthresh/ +## * The following methods were adapted from http://www.cs.tut.fi/~ant/histthresh/ +## intermodes percentile minimum +## MaxEntropy MaxLikelihood intermeans +## moments minerror concavity -function [level, good] = graythresh (img, algo = "otsu") + +function [level, good] = graythresh (img, algo = "otsu", varargin) ## Input checking - if (nargin < 1 || nargin > 2) + if (nargin < 1 || nargin > 3) print_usage(); elseif (!isgray (img) && !isrgb (img)) error ("graythresh: input must be an image"); @@ -108,8 +160,17 @@ endif switch tolower (algo) - case {"otsu"}, [level, good] = otsu (img); - case {"moments"}, [level] = moments (img); + case {"concavity"}, [level] = concavity (img); + case {"intermeans"}, [level] = intermeans (img); + case {"intermodes"}, [level] = intermodes (img); + case {"maxlikelihood"}, [level] = maxlikelihood (img); + case {"maxentropy"}, [level] = maxentropy (img); + case {"mean"}, [level] = mean (img(:)); + case {"minimum"}, [level] = minimum (img); + case {"minerror"}, [level] = minerror_iter (img); + case {"moments"}, [level] = moments (img); + case {"otsu"}, [level, good] = otsu (img); + case {"percentile"}, [level] = percentile (img, varargin{1}); otherwise, error ("graythresh: unknown method '%s'", algo); endswitch endfunction @@ -155,6 +216,37 @@ level /= n; endfunction +#{ + ##The following is another implementation of Otsu's method from the HistThresh + ##toolbox + if nargin == 1 + n = 255; + end + + % This algorithm is implemented in the Image Processing Toolbox. + %I = uint8(I); + %T = n*graythresh(I); + + % The implementation below uses the notations from the paper, but is + % significantly slower. + + I = double(I); + + % Calculate the histogram. + y = hist(I(:),0:n); + + warning off MATLAB:divideByZero + for j = 0:n + mu = partial_sumB(y,j)/partial_sumA(y,j); + nu = (partial_sumB(y,n)-partial_sumB(y,j))/(partial_sumA(y,n)-partial_sumA(y,j)); + vec(j+1) = partial_sumA(y,j)*(partial_sumA(y,n)-partial_sumA(y,j))*(mu-nu)^2; + end + warning on MATLAB:divideByZero + + [maximum,ind] = max(vec); + T = ind-1; +#} + function level = moments (I, n) if nargin == 1 @@ -166,7 +258,7 @@ % Calculate the histogram. y = hist (I(:), 0:n); - % The threshold is chosen such that A(y,t)/A(y,n) is closest to x0. + % The threshold is chosen such that partial_sumA(y,t)/partial_sumA(y,n) is closest to x0. Avec = zeros (1, n+1); for t = 0:n @@ -186,6 +278,325 @@ level /= n; endfunction +function T = maxentropy(I,n) + if nargin == 1 + n = 255; + end + + I = double(I); + + % Calculate the histogram. + y = hist(I(:),0:n); + + warning off + % The threshold is chosen such that the following expression is minimized. + for j = 0:n + vec(j+1) = negativeE(y,j)/partial_sumA(y,j) - log10(partial_sumA(y,j)) + ... + (negativeE(y,n)-negativeE(y,j))/(partial_sumA(y,n)-partial_sumA(y,j)) - log10(partial_sumA(y,n)-partial_sumA(y,j)); + end + warning on + + [minimum,ind] = min(vec); + T = 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); + + % Smooth the histogram by iterative three point mean filtering. + iter = 0; + while ~bimodtest(y) + h = ones(1,3)/3; + y = conv2(y,h,'same'); + iter = iter+1; + % If the histogram turns out not to be bimodal, set T to zero. + if iter > 10000; + T = 0; + return + end + end + + % The threshold is the mean of the two peaks of the histogram. + ind = 0; + for k = 2:n + if y(k-1) < y(k) && y(k+1) < y(k) + ind = ind+1; + TT(ind) = k-1; + end + end + T = 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); + + % The threshold is chosen such that 50% of pixels lie in each category. + Avec = zeros(1,n+1); + for t = 0:n + Avec(t+1) = partial_sumA(y,t)/partial_sumA(y,n); + end + + [minimum,ind] = min(abs(Avec-p)); + T = 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); + + % Smooth the histogram by iterative three point mean filtering. + iter = 0; + while ~bimodtest(y) + h = ones(1,3)/3; + y = conv2(y,h,'same'); + iter = iter+1; + % If the histogram turns out not to be bimodal, set T to zero. + if iter > 10000; + T = 0; + return + end + end + + % 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; + end + end +endfunction + +function [T] = minerror_iter (I,n) + if nargin == 1 + n = 255; + end + + 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 + + % Calculate some statistics. + mu = partial_sumB(y,T)/partial_sumA(y,T); + nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T)); + p = partial_sumA(y,T)/partial_sumA(y,n); + q = (partial_sumA(y,n)-partial_sumA(y,T)) / partial_sumA(y,n); + sigma2 = partial_sumC(y,T)/partial_sumA(y,T)-mu^2; + tau2 = (partial_sumC(y,n)-partial_sumC(y,T)) / (partial_sumA(y,n)-partial_sumA(y,T)) - nu^2; + + % The terms of the quadratic equation to be solved. + w0 = 1/sigma2-1/tau2; + w1 = mu/sigma2-nu/tau2; + w2 = mu^2/sigma2 - nu^2/tau2 + log10((sigma2*q^2)/(tau2*p^2)); + + % If the next threshold would be imaginary, return with the current one. + sqterm = w1^2-w0*w2; + if sqterm < 0 + warning('MINERROR:NaN','Warning: th_minerror_iter did not converge.') + return + end + + % The updated threshold is the integer part of the solution of the + % quadratic equation. + Tprev = T; + T = 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; + end + + end +endfunction +#{ + ## this was not an implementatino of the original minerror algorithm but seems + ## to converg more often than the original. The original is (also from the + ## HistThresh toolbox + function T = th_minerror(I,n) + if nargin == 1 + n = 255; + end + + I = double(I); + + % Calculate the histogram. + y = hist(I(:),0:n); + + warning off + % The threshold is chosen such that the following expression is minimized. + for j = 0:n + mu = partial_sumB(y,j)/partial_sumA(y,j); + nu = (partial_sumB(y,n)-partial_sumB(y,j))/(partial_sumA(y,n)-partial_sumA(y,j)); + p = partial_sumA(y,j)/partial_sumA(y,n); + q = (partial_sumA(y,n)-partial_sumA(y,j)) / partial_sumA(y,n); + sigma2 = partial_sumC(y,j)/partial_sumA(y,j)-mu^2; + tau2 = (partial_sumC(y,n)-partial_sumC(y,j)) / (partial_sumA(y,n)-partial_sumA(y,j)) - nu^2; + vec(j+1) = p*log10(sqrt(sigma2)/p) + q*log10(sqrt(tau2)/q); + end + warning on + + vec(vec==-inf) = NaN; + [minimum,ind] = min(vec); + T = ind-1; + endfunction +#} + +function T = maxlikelihood (I,n) + if nargin == 1 + n = 255; + end + + I = double(I); + + % Calculate the histogram. + y = hist(I(:),0:n); + + % The initial estimate for the threshold is found with the MINIMUM + % algorithm. + T = th_minimum(I,n); + + % Calculate initial values for the statistics. + mu = partial_sumB(y,T)/partial_sumA(y,T); + nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T)); + p = partial_sumA(y,T)/partial_sumA(y,n); + q = (partial_sumA(y,n)-partial_sumA(y,T)) / partial_sumA(y,n); + sigma2 = partial_sumC(y,T)/partial_sumA(y,T)-mu^2; + tau2 = (partial_sumC(y,n)-partial_sumC(y,T)) / (partial_sumA(y,n)-partial_sumA(y,T)) - nu^2; + + mu_prev = NaN; + nu_prev = NaN; + p_prev = NaN; + q_prev = NaN; + sigma2_prev = NaN; + tau2_prev = NaN; + + while abs(mu-mu_prev) > eps || abs(nu-nu_prev) > eps || ... + abs(p-p_prev) > eps || abs(q-q_prev) > eps || ... + abs(sigma2-sigma2_prev) > eps || abs(tau2-tau2_prev) > eps + for i = 0:n + phi(i+1) = p/q * exp(-((i-mu)^2) / (2*sigma2)) / ... + (p/sqrt(sigma2) * exp(-((i-mu)^2) / (2*sigma2)) + ... + (q/sqrt(tau2)) * exp(-((i-nu)^2) / (2*tau2))); + end + ind = 0:n; + gamma = 1-phi; + F = phi*y'; + G = gamma*y'; + p_prev = p; + q_prev = q; + mu_prev = mu; + nu_prev = nu; + sigma2_prev = nu; + tau2_prev = nu; + p = F/partial_sumA(y,n); + q = G/partial_sumA(y,n); + mu = ind.*phi*y'/F; + nu = ind.*gamma*y'/G; + sigma2 = ind.^2.*phi*y'/F - mu^2; + tau2 = ind.^2.*gamma*y'/G - nu^2; + end + + % The terms of the quadratic equation to be solved. + w0 = 1/sigma2-1/tau2; + w1 = mu/sigma2-nu/tau2; + w2 = mu^2/sigma2 - nu^2/tau2 + log10((sigma2*q^2)/(tau2*p^2)); + + % If the threshold would be imaginary, return with threshold set to zero. + sqterm = w1^2-w0*w2; + if sqterm < 0; + T = 0; + return + end + + % The threshold is the integer part of the solution of the quadratic + % equation. + T = floor((w1+sqrt(sqterm))/w0); +endfunction + +function T = intermeans (I,n) + if nargin == 1 + n = 255; + end + + 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 + % pixels below (mu) the threshold and above (nu) it are found. The + % updated threshold is the mean of mu and nu. + while T ~= Tprev + mu = partial_sumB(y,T)/partial_sumA(y,T); + nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T)); + Tprev = T; + T = floor((mu+nu)/2); + end +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); + H = hconvhull(h); + + % Find the local maxima of the difference H-h. + lmax = flocmax(H-h); + + % Find the histogram balance around each index. + for k = 0:n + E(k+1) = hbalance(h,k); + end + + % The threshold is the local maximum with highest balance. + E = E.*lmax; + [dummy ind] = max(E); + T = ind-1; +endfunction + +################################################################################ +## Auxiliary functions from HistThresh toolbox http://www.cs.tut.fi/~ant/histthresh/ +################################################################################ + ## partial sums from C. A. Glasbey, "An analysis of histogram-based thresholding ## algorithms," CVGIP: Graphical Models and Image Processing, vol. 55, pp. 532-537, 1993. function x = partial_sumA (y, j) @@ -203,3 +614,113 @@ ind = 0:j; x = ind.^3*y(1:j+1)'; endfunction + +## Test if a histogram is bimodal. +function b = bimodtest(y) + len = length(y); + b = false; + modes = 0; + + % Count the number of modes of the histogram in a loop. If the number + % exceeds 2, return with boolean return value false. + for k = 2:len-1 + if y(k-1) < y(k) && y(k+1) < y(k) + modes = modes+1; + if modes > 2 + return + end + end + end + + % The number of modes could be less than two here + if modes == 2 + b = true; + end +endfunction + +## Find the local maxima of a vector using a three point neighborhood. +function y = flocmax(x) +% y binary vector with maxima of x marked as ones + + len = length(x); + y = zeros(1,len); + + for k = 2:len-1 + [dummy,ind] = max(x(k-1:k+1)); + if ind == 2 + y(k) = 1; + end + end +endfunction + +## Calculate the balance measure of the histogram around a histogram index. +function E = hbalance(y,ind) +% y histogram +% ind index about which balance is calculated +% +% Out: +% E balance measure +% +% References: +% +% A. Rosenfeld and P. De La Torre, "Histogram concavity analysis as an aid +% in threhold selection," IEEE Transactions on Systems, Man, and +% Cybernetics, vol. 13, pp. 231-235, 1983. +% +% P. K. Sahoo, S. Soltani, and A. K. C. Wong, "A survey of thresholding +% techniques," Computer Vision, Graphics, and Image Processing, vol. 41, +% pp. 233-260, 1988. + + n = length(y)-1; + E = partial_sumA(y,ind)*(partial_sumA(y,n)-partial_sumA(y,ind)); +endfunction + +## Find the convex hull of a histogram. +function H = hconvhull(h) + % In: + % h histogram + % + % Out: + % H convex hull of histogram + % + % References: + % + % A. Rosenfeld and P. De La Torre, "Histogram concavity analysis as an aid + % in threhold selection," IEEE Transactions on Systems, Man, and + % Cybernetics, vol. 13, pp. 231-235, 1983. + + len = length(h); + K(1) = 1; + k = 1; + + % The vector K gives the locations of the vertices of the convex hull. + while K(k)~=len + + theta = zeros(1,len-K(k)); + for i = K(k)+1:len + x = i-K(k); + y = h(i)-h(K(k)); + theta(i-K(k)) = atan2(y,x); + end + + maximum = max(theta); + maxloc = find(theta==maximum); + k = k+1; + K(k) = maxloc(end)+K(k-1); + + end + + % Form the convex hull. + H = zeros(1,len); + for i = 2:length(K) + H(K(i-1):K(i)) = h(K(i-1))+(h(K(i))-h(K(i-1)))/(K(i)-K(i-1))*(0:K(i)-K(i-1)); + end +endfunction + +## Entroy function. Note that the function returns the negative of entropy. +function x = negativeE(y,j) + ## used by the maxentropy method only + y = y(1:j+1); + y = y(y~=0); + x = sum(y.*log10(y)); +endfunction