001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.pub.threshold;
011
012public abstract class Thresholder {
013        
014        // compute the sum of a histogram array
015        protected int sum(int[] h) {
016                int cnt = 0;
017                for (int i=0; i<h.length; i++) {
018                        cnt += h[i];
019                }
020                return cnt;
021        }
022        
023        protected int count(int[] h) {
024                return count(h,0,h.length-1);
025        }
026        
027        // compute the population of a histogram from index lo...hi
028        protected int count(int[] h, int lo, int hi) {
029                if (lo < 0) lo = 0;
030                if (hi >= h.length) hi = h.length-1;
031                int cnt = 0;
032                for (int i = lo; i <= hi; i++) {
033                        cnt += h[i];
034                }
035                return cnt;
036        }
037        
038        protected double mean(int[] h) {
039                return mean(h,0,h.length-1);
040        }
041        
042        protected double mean(int[] h, int lo, int hi) {
043                if (lo < 0) lo = 0;
044                if (hi >= h.length) hi = h.length-1;
045                long cnt = 0;
046                long sum = 0;
047                for (int i=lo; i<=hi; i++) {
048                        cnt = cnt + h[i];
049                        sum = sum + i * h[i];
050                }
051                if (cnt > 0)
052                        return ((double)sum) / cnt;
053                else 
054                        return 0;
055        }
056        
057        protected double sigma2(int[] h) {
058                return sigma2(h, 0, h.length-1);
059        }
060                        
061        // this is a slow version, only for testing:
062//      protected double sigma2(int[] h, int lo, int hi) {
063//              if (lo < 0) lo = 0;
064//              if (hi >= h.length) hi = h.length-1;
065//              double mu = mean(h,lo,hi);
066//              long cnt = 0;
067//              double sum = 0;
068//              for (int i=lo; i<=hi; i++) {
069//                      cnt = cnt + h[i];
070//                      sum = sum + (i - mu) * (i - mu) * h[i];
071//              }
072//              if (cnt > 0)
073//                      return ((double)sum) / cnt;
074//              else 
075//                      return 0;
076//      }
077        
078        // fast version
079        protected double sigma2(int[] h, int lo, int hi) {
080                if (lo < 0) lo = 0;
081                if (hi >= h.length) hi = h.length-1;
082                long A = 0;
083                long B = 0;
084                long N = 0;
085                for (int i=lo; i<=hi; i++) {
086                        int ni = h[i];
087                        A = A + i * ni;
088                        B = B + i * i * ni;
089                        N = N + ni;
090                }
091                if (N > 0)
092                        return ((double)B - (double)A*A / N) / N;
093                else 
094                        return 0;
095        }
096        
097        
098        // ---  utility methods -----------------------------
099        
100        // compute the median of a histogram 
101        protected int median(int[] h) {
102                int K = h.length;
103                int N = sum(h);
104                int m = N / 2;
105                int i = 0;
106                int sum = h[0];
107                while (sum <= m && i < K) {
108                        i++;
109                        sum += h[i];
110                }
111                return i;
112        }
113        
114        public double[] normalize(int[] h) {
115                int K = h.length;
116                int N = count(h);
117                double[] nh = new double[K];
118                for (int i=0; i<K; i++) {
119                        nh[i] = ((double) h[i]) / N;
120                }
121                return nh;
122        }
123        
124        public double[] normalize(double[] h) {
125                double[] nh = new double[h.length];
126                double hmax = max(h);
127                for (int i=0; i<h.length; i++) {
128                        nh[i] =  (double) h[i] / hmax;
129                }
130                return nh;
131        }
132        
133        public double max(double[] h) {
134                double hmax = Double.NEGATIVE_INFINITY;
135                for (int i=0; i<h.length; i++) {
136                        double n = h[i];
137                        if (n>hmax) hmax = n;
138                }
139                return hmax;
140        
141        }
142        
143}