changeset 10754:4ca5fadf4f0c octave-forge

graythresh: return goodness of computed value. Prepare code for multiple algorithms. Avoid var names that shadow core functions.
author carandraug
date Sun, 02 Sep 2012 01:53:19 +0000
parents 382399423984
children 996fadda47e4
files main/image/NEWS main/image/inst/graythresh.m
diffstat 2 files changed, 123 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/main/image/NEWS	Sun Sep 02 00:51:46 2012 +0000
+++ b/main/image/NEWS	Sun Sep 02 01:53:19 2012 +0000
@@ -30,6 +30,9 @@
 
       imginfo
 
+ ** The function `graythresh' now returns a second value representing the
+    ``goodness'' of the computed threshold value.
+
  ** The following functions have been deprecated (see their help text
     for the recommended alternatives):
 
--- a/main/image/inst/graythresh.m	Sun Sep 02 00:51:46 2012 +0000
+++ b/main/image/inst/graythresh.m	Sun Sep 02 01:53:19 2012 +0000
@@ -1,4 +1,6 @@
 ## Copyright (C) 2005 Barre-Piquot
+## Copyright (C) 2007 Søren Hauberg
+## Copyright (C) 2012 Carnë Draug <carandraug+dev@gmail.com>
 ##
 ## This program is free software; you can redistribute it and/or modify it under
 ## the terms of the GNU General Public License as published by the Free Software
@@ -14,73 +16,133 @@
 ## this program; if not, see <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{level}=} graythresh (@var{I})
-## Compute global image threshold using Otsu's method.
+## @deftypefn {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img})
+## @deftypefnx {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img}, @var{algo})
+## Compute global image threshold.
+##
+## Given an image @var{img} finds the optimal threshold value @var{level} for
+## conversion to a binary image with @code{im2bw}. Color images are converted
+## to grayscale before @var{level} is computed.
+##
+## The optional argument @var{method} is the algorithm to be used (default's to
+## Otsu). The available algorithms are:
+##
+## @table @asis
+## @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.,
+## 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 Huang
+## Not yet implemented.
+##
+## @item ImageJ
+## Not yet implemented.
+##
+## @item intermodes
+## Not yet implemented.
+##
+## @item IsoData
+## Not yet implemented.
 ##
-## The output @var{level} is a global threshold (level) that can be used to convert
-## an intensity image to a binary image with @code{im2bw}.
-## @var{level} is a normalized intensity value that lies in the range [0, 1]. 
-## 
-## The function uses Otsu's method, which chooses the threshold to
-## minimize the intraclass variance of the black and white pixels. 
-## 
-## Color images are converted grayscale before @var{level} is computed.
+## @item Li
+## Not yet implemented.
+##
+## @item MaxEntropy
+## Not yet implemented.
+##
+## @item mean
+## Not yet implemented.
+##
+## @item MinError
+## Not yet implemented.
+##
+## @item minimum
+## Not yet implemented.
+##
+## @item moments
+## Not yet implemented.
+##
+## @item percentile
+## Not yet implemented.
+##
+## @item RenyiEntropy
+## Not yet implemented.
+##
+## @item Shanbhag
+## Not yet implemented.
+##
+## @item triangle
+## Not yet implemented.
+##
+## @item Yen
+## Not yet implemented.
+## @end table
+##
 ## @seealso{im2bw}
 ## @end deftypefn
 
-## Note:
-## This function is taken from
-## http://www.irit.fr/~Philippe.Joly/Teaching/M2IRR/IRR05/
-## I added texinfo documentation, error checking and sanitised the code.
-##    -- Søren Hauberg
+## Notes:
+##  * 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.
 
-function level = graythresh (I)
+function [level, goodness] = graythresh (img, algo = "otsu")
     ## Input checking
-    if (nargin != 1)
+    if (nargin < 1 || nargin > 2)
       print_usage();
+    elseif (!isgray (img) && !isrgb (img))
+      error ("graythresh: input must be an image");
     endif
-    if (!isgray(I) && !isrgb(I))
-      error("graythresh: input must be an image");
-    endif
-    
+
     ## If the image is RGB convert it to grayscale
-    if (isrgb(I))
-      I = rgb2gray(I);
+    if (isrgb(img))
+      img = rgb2gray (img);
     endif
 
-    ## Calculation of the normalized histogram
-    n = 256;
-    h = hist(I(:), 1:n);        
-    h = h/(length(I(:))+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);
-    end    
-         
-    ## 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;
-    max = 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 > max)
-            max = s;
-            level = i;
-        endif
-    endfor
-    
-    ## Normalisation of the threshold        
-    level /= n;
+    switch tolower (algo)
+      case {"otsu"}
+        ## Calculation of the normalized histogram
+        n = 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 > max)
+                goodness = s;
+                level    = i;
+            endif
+        endfor
+        
+        ## Normalisation of the threshold
+        level /= n;
+      otherwise
+        error ("graythresh: unknown method '%s'", algo);
+    endswitch
 endfunction