changeset 637:6428784b5707

graythresh: fix bug when checking input for algorithms that take options, silent division by zero warnings with unwind_protect block, get subfunctions to return cell array
author carandraug
date Sun, 30 Sep 2012 23:57:04 +0000
parents beed82f40217
children 426e9e2fcfc9
files inst/graythresh.m
diffstat 1 files changed, 60 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/inst/graythresh.m
+++ b/inst/graythresh.m
@@ -120,8 +120,8 @@
 ## a new approach", Computer Vision, Graphics, and Image Processing, 29: 377-393}
 ##
 ## @item percentile
-## 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)
+## Assumes a specific fraction of pixels (set at @var{options}) to be background.
+## If no value is given, assumes 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}
 ##
@@ -152,7 +152,7 @@
   ## Input checking
   if (nargin < 1 || nargin > 3)
     print_usage();
-  elseif (nargin > 2 && !any (strcmpi (varargin{1}, {"percentile"})))
+  elseif (nargin > 2 && !any (strcmpi (algo, {"percentile"})))
     error ("graythresh: algorithm `%s' does not accept any options.", algo);
   else
     hist_in = false;
@@ -278,17 +278,25 @@
 function T = maxentropy(y)
   n = numel (y) - 1;
 
-  % 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
+  dz_warn = warning ("query", "divide-by-zero");
+  unwind_protect
+    warning ("off", "Octave:divide-by-zero");
+    % 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
+  unwind_protect_cleanup
+    ## restore broadcats warning status
+    warning (dz_warn.state, "Octave:divide-by-zero");
+  end_unwind_protect
 
   [minimum,ind] = min(vec);
   T{1} = ind-1;
 endfunction
 
 function [T] = intermodes (y)
+  ## checked with ImageJ and is slightly different but not by much
   n = numel (y) - 1;
 
   % Smooth the histogram by iterative three point mean filtering.
@@ -353,45 +361,51 @@
   end
 endfunction
 
-function [T] = minerror_iter (y, T)
+function [Tout] = minerror_iter (y, T)
   n = numel (y) - 1;
 
   Tprev = NaN;
 
-  while T ~= Tprev
+  dz_warn = warning ("query", "divide-by-zero");
+  unwind_protect
+    warning ("off", "Octave:divide-by-zero");
+    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;
 
-    % 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));
+      % 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
+      % 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.')
+        break
+      endif
+
+      % The updated threshold is the integer part of the solution of the
+      % quadratic equation.
+      Tprev = T;
+      T = floor((w1+sqrt(sqterm))/w0);
 
-    % The updated threshold is the integer part of the solution of the
-    % quadratic equation.
-    Tprev = T;
-    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{1} = Tprev;
-    end
-
-  end
+      % 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
+    endwhile
+  unwind_protect_cleanup
+    ## restore broadcats warning status
+    warning (dz_warn.state, "Octave:divide-by-zero");
+  end_unwind_protect
+  Tout{1} = T;
 endfunction
 #{
   ## this is an implementation of the original minerror algorithm but seems
@@ -424,12 +438,12 @@
   endfunction
 #}
 
-function T = maxlikelihood (y)
+function Tout = maxlikelihood (y)
   n = numel (y) - 1;
 
   % The initial estimate for the threshold is found with the MINIMUM
   % algorithm.
-  T = minimum (y);
+  T = minimum (y){1};
 
   % Calculate initial values for the statistics.
   mu = partial_sumB(y,T)/partial_sumA(y,T);
@@ -480,16 +494,16 @@
   % If the threshold would be imaginary, return with threshold set to zero.
   sqterm = w1^2-w0*w2;
   if sqterm < 0;
-    T = 0;
+    Tout{1} = 0;
     return
   end
 
   % The threshold is the integer part of the solution of the quadratic
   % equation.
-  T{1} = floor((w1+sqrt(sqterm))/w0);
+  Tout{1} = floor((w1+sqrt(sqterm))/w0);
 endfunction
 
-function T = intermeans (y, T)
+function Tout = intermeans (y, T)
   n = numel (y) - 1;
 
   Tprev = NaN;
@@ -503,7 +517,7 @@
     Tprev = T;
     T = floor((mu+nu)/2);
   end
-  T{1} = T;
+  Tout{1} = T;
 endfunction
 
 function T = concavity (h)