changeset 855:f903e3963f9f

graythresh: large performance increase by avoiding repeated calculations. * graythresh.m: many calls to the partial_sumX() with exactly the same inputs were being done inside for loops which makes the algorithms extremely slow. Avoid this by calculating their values before the loop where appropriate, or once at the start of each iteration.
author Carnë Draug <carandraug@octave.org>
date Fri, 03 Jan 2014 06:36:56 +0000
parents 34045e6b58cc
children 4c060d12db5f
files inst/graythresh.m
diffstat 1 files changed, 45 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/inst/graythresh.m
+++ b/inst/graythresh.m
@@ -267,17 +267,21 @@
   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.
+    ## The threshold is chosen such that the following expression is minimized.
+    sumY = sum (y);
+    negY = negativeE (y, n);
     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));
+      sumA = partial_sumA (y, j);
+      negE = negativeE (y, j);
+      sum_diff = sumY - sumA;
+      vec(j+1) = negE/sumA - log10 (sumA) + (negY-negE)/(sum_diff) - log10 (sum_diff);
     end
   unwind_protect_cleanup
     ## restore broadcats warning status
     warning (dz_warn.state, "Octave:divide-by-zero");
   end_unwind_protect
 
-  [minimum,ind] = min(vec);
+  [~,ind] = min (vec);
   T{1} = ind-1;
 endfunction
 
@@ -354,14 +358,22 @@
   dz_warn = warning ("query", "divide-by-zero");
   unwind_protect
     warning ("off", "Octave:divide-by-zero");
+    sumA = partial_sumA (y, n);
+    sumB = partial_sumB (y, n);
+    sumC = partial_sumC (y, n);
     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;
+      sumAT = partial_sumA (y, T);
+      sumBT = partial_sumB (y, T);
+      sumCT = partial_sumC (y, T);
+      sumAdiff = sumA - sumAT;
+
+      mu = sumBT/sumAT;
+      nu = (sumB-sumBT)/(sumAdiff);
+      p = sumAT/sumA;
+      q = (sumAdiff) / sumA;
+      sigma2 = sumCT/sumAT-mu^2;
+      tau2 = (sumC-sumCT) / (sumAdiff) - nu^2;
 
       % The terms of the quadratic equation to be solved.
       w0 = 1/sigma2-1/tau2;
@@ -430,13 +442,21 @@
   ## initial estimate for the threshold is found with the minimum algorithm
   T = minimum (y){1};
 
+  sumY = sum (y);
+
+  sumB  = partial_sumB (y, n);
+  sumC  = partial_sumC (y, n);
+
+  sumAT = partial_sumA (y, T);
+  sumBT = partial_sumB (y, T);
+  sumCT = partial_sumC (y, T);
   ## 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     = sumBT / sumAT;
+  nu     = (sumB - sumBT) / (sumY - sumAT);
+  p      = sumAT / sumY;
+  q      = (sumY - sumAT) / sumY;
+  sigma2 = sumCT / sumAT - mu^2;
+  tau2   = (sumC - sumCT) / (sumY - sumAT) - nu^2;
 
   ## Return if sigma2 or tau2 are zero, to avoid division by zero
   if (sigma2 == 0 || tau2 == 0)
@@ -466,8 +486,8 @@
 
     mu      = ind.*phi*y'/F;
     nu      = ind.*gamma*y'/G;
-    p       = F / partial_sumA (y,n);
-    q       = G / partial_sumA (y,n);
+    p       = F / sumY;
+    q       = G / sumY;
     sigma2  = ind.^2.*phi*y'/F - mu^2;
     tau2    = ind.^2.*gamma*y'/G - nu^2;
 
@@ -499,9 +519,14 @@
   % 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.
+  sumY = sum (y);
+  sumB = partial_sumB (y, n);
   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));
+    sumAT = partial_sumA (y, T);
+    sumBT = partial_sumB (y, T);
+
+    mu = sumBT/sumAT;
+    nu = (sumB-sumBT)/(sumY-sumAT);
     Tprev = T;
     T = floor((mu+nu)/2);
   end