Mercurial > forge
changeset 10958:bf349bbc893d octave-forge
graythresh: add moments algorithm
author | carandraug |
---|---|
date | Wed, 26 Sep 2012 15:20:44 +0000 |
parents | 0280f329eb72 |
children | 7b5c664a5f38 |
files | main/image/NEWS main/image/inst/graythresh.m |
diffstat | 2 files changed, 108 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/main/image/NEWS Wed Sep 26 14:37:59 2012 +0000 +++ b/main/image/NEWS Wed Sep 26 15:20:44 2012 +0000 @@ -35,6 +35,15 @@ ** The function `graythresh' now returns a second value representing the ``goodness'' of the computed threshold value. + ** Alternative algorithms for automatic threshold have been implemented in + `graythresh' (thanks to Antti Niemistö for releasing HistThresh toolbox + http://www.cs.tut.fi/~ant/histthresh/ from where many were ported, under a + GPL license. Currently, the following algorithms have been implemented + (see graythresh for notes and references): + + moments + otsu + ** The following functions have been deprecated (see their help text for the recommended alternatives):
--- a/main/image/inst/graythresh.m Wed Sep 26 14:37:59 2012 +0000 +++ b/main/image/inst/graythresh.m Wed Sep 26 15:20:44 2012 +0000 @@ -1,3 +1,4 @@ +## Copyright (C) 2004 Antti Niemistö <antti.niemisto@tut.fi> ## Copyright (C) 2005 Barre-Piquot ## Copyright (C) 2007 Søren Hauberg ## Copyright (C) 2012 Carnë Draug <carandraug+dev@gmail.com> @@ -64,7 +65,9 @@ ## Not yet implemented. ## ## @item moments -## Not yet implemented. +## 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} ## ## @item percentile ## Not yet implemented. @@ -89,8 +92,9 @@ ## * 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/ -function [level, goodness] = graythresh (img, algo = "otsu") +function [level, good] = graythresh (img, algo = "otsu") ## Input checking if (nargin < 1 || nargin > 2) print_usage(); @@ -104,45 +108,98 @@ endif switch tolower (algo) - case {"otsu"} - ## Calculation of the normalized histogram - n = double (intmax (class (img))) + 1; - h = hist (img(:), 1:n); - h = h / (length (img(:)) + 1); - - ## Calculation of the cumulated histogram and the mean values - w = cumsum (h); - mu = zeros (n, 1); - mu(1) = h(1); - for i = 2:n - mu(i) = mu(i-1) + i * h(i); - endfor - - ## Initialisation of the values used for the threshold calculation - level = find (h > 0, 1); - w0 = w(level); - w1 = 1 - w0; - mu0 = mu(level) / w0; - mu1 = (mu(end) - mu(level)) / w1; - goodness = w0 * w1 * (mu1 - mu0) * (mu1 - mu0); - - ## For each step of the histogram, calculation of the threshold - ## and storing of the maximum - for i = find (h > 0) - w0 = w(i); - w1 = 1 - w0; - mu0 = mu(i) / w0; - mu1 = (mu(end) - mu(i)) / w1; - s = w0 * w1 * (mu1 - mu0) * (mu1 - mu0); - if (s > goodness) - goodness = s; - level = i; - endif - endfor - - ## Normalisation of the threshold - level /= n; - otherwise - error ("graythresh: unknown method '%s'", algo); + case {"otsu"}, [level, good] = otsu (img); + case {"moments"}, [level] = moments (img); + otherwise, error ("graythresh: unknown method '%s'", algo); endswitch endfunction + +function [level, good] = otsu (img) + ## Calculation of the normalized histogram + n = double (intmax (class (img))) + 1; + h = hist (img(:), 1:n); + h = h / (length (img(:)) + 1); + + ## Calculation of the cumulated histogram and the mean values + w = cumsum (h); + mu = zeros (n, 1); + mu(1) = h(1); + for i = 2:n + + mu(i) = mu(i-1) + i * h(i); + endfor + + ## Initialisation of the values used for the threshold calculation + level = find (h > 0, 1); + w0 = w(level); + w1 = 1 - w0; + mu0 = mu(level) / w0; + mu1 = (mu(end) - mu(level)) / w1; + good = w0 * w1 * (mu1 - mu0) * (mu1 - mu0); + + ## For each step of the histogram, calculation of the threshold + ## and storing of the maximum + for i = find (h > 0) + w0 = w(i); + w1 = 1 - w0; + mu0 = mu(i) / w0; + mu1 = (mu(end) - mu(i)) / w1; + s = w0 * w1 * (mu1 - mu0) * (mu1 - mu0); + if (s > good) + good = s; + level = i; + endif + endfor + + ## Normalisation of the threshold + level /= n; +endfunction + +function level = moments (I, n) + + if nargin == 1 + n = 255; + end + + I = double(I); + + % Calculate the histogram. + y = hist (I(:), 0:n); + + % The threshold is chosen such that A(y,t)/A(y,n) is closest to x0. + Avec = zeros (1, n+1); + + for t = 0:n + Avec(t+1) = partial_sumA (y, t) / partial_sumA (y, n); + end + + % The following finds x0. + x2 = (partial_sumB(y,n)*partial_sumC(y,n) - partial_sumA(y,n)*partial_sumD(y,n)) / (partial_sumA(y,n)*partial_sumC(y,n) - partial_sumB(y,n)^2); + x1 = (partial_sumB(y,n)*partial_sumD(y,n) - partial_sumC(y,n)^2) / (partial_sumA (y,n)*partial_sumC(y,n) - partial_sumB(y,n)^2); + x0 = .5 - (partial_sumB(y,n)/partial_sumA(y,n) + x2/2) / sqrt (x2^2 - 4*x1); + + % And finally the threshold. + [minimum, ind] = min (abs (Avec-x0)); + level = ind-1; + + ## Normalisation of the threshold + level /= n; +endfunction + +## 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) + x = sum (y(1:j+1)); +endfunction +function x = partial_sumB (y, j) + ind = 0:j; + x = ind*y(1:j+1)'; +endfunction +function x = partial_sumC (y, j) + ind = 0:j; + x = ind.^2*y(1:j+1)'; +endfunction +function x = partial_sumD (y, j) + ind = 0:j; + x = ind.^3*y(1:j+1)'; +endfunction