Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / util / Histogram.java @ 11185

History | View | Annotate | Download (11.3 KB)

1 10939 nacho
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2007 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 */
19
package org.gvsig.raster.util;
20
21 11113 nacho
22 10939 nacho
/**
23
 * Representa un histograma.
24
 * @version 27/03/2007
25
 * @author Nacho Brodin (nachobrodin@gmail.com)
26 11076 nacho
 *
27 10939 nacho
 */
28
public class Histogram {
29 11113 nacho
        private HistogramClass[][] histogram = null;
30
        private int nClasses = 0;
31
32 11185 bsanchez
        private long[][] table = null;
33 10939 nacho
        private static String[] types = {"normal", "accumulated", "logaritmic"};
34 11185 bsanchez
        private double min = Double.MAX_VALUE;
35
        private double max = Double.MIN_VALUE;
36 10939 nacho
37
        /**
38
         * Constructor
39
         */
40 11185 bsanchez
        public Histogram(int nBands, int nClasses, double min, double max) {
41
                table = new long[nBands][nClasses];
42
                for (int i=0; i < table.length; i++)
43
                        for (int j=0; j < table[0].length; j++)
44
                                table[i][j] = 0;
45
                this.min = min;
46
                this.max = max;
47 11113 nacho
                this.nClasses = nClasses;
48 10939 nacho
        }
49 11113 nacho
50 10939 nacho
        /**
51
         * Obtiene el histograma sin modificar
52
         * @return array bidimensional donde el primer elemento es el valor del pixel
53
         * o rango y el segundo el n?mero de elementos que aparecen.
54
         */
55 11113 nacho
        public HistogramClass[][] getHistogram() {
56 11185 bsanchez
                if (nClasses <= 0)
57 11113 nacho
                        return null;
58
59 11185 bsanchez
                histogram = new HistogramClass[table.length][nClasses];
60 11113 nacho
61 11185 bsanchez
                for (int i = 0; i < table.length; i++) {
62 11113 nacho
                        for (int j = 0; j < nClasses; j++) {
63 11185 bsanchez
                                HistogramClass hc = new HistogramClass(min + ((j*(max-min))/nClasses), min + (((j+1)*(max-min))/nClasses));
64
                                hc.setValue(table[i][j]);
65 11113 nacho
                                histogram[i][j] = hc;
66
                        }
67
                }
68 10939 nacho
                return histogram;
69
        }
70
71
        /**
72
         * Obtiene el n?mero de bandas del histograma
73
         * @return entero que representa el n?mero de bandas
74
         */
75
        public int getNumBands() {
76 11185 bsanchez
                if (table != null)
77
                        return table.length;
78 10939 nacho
                return 0;
79
        }
80
81
        /**
82
         * Obtiene la longitud (n?mero de valores) de una banda determinada
83
         * @param band Banda o obtener la longitud
84
         * @return entero con la longitud de la banda
85 11185 bsanchez
         * rangos de valores y DataclassList.
86 10939 nacho
         */
87
        public int getBandLenght(int band) {
88 11185 bsanchez
                if (table != null)
89
                        return table[band].length;
90 10939 nacho
                return 0;
91
        }
92
93
        /**
94
         * Obtiene el n?mero de valores o clases del histograma
95
         * @return entero que representa el n?mero de valores o clases del histograma
96
         */
97
        public int getNumValues() {
98 11113 nacho
                return nClasses;
99 10939 nacho
        }
100
101
        /**
102
         * Asigna un histograma
103
         * @param hist histograma asignado
104
         */
105 11113 nacho
        public void setHistogram(HistogramClass[][] hist){
106 10939 nacho
                histogram = hist;
107
        }
108
109
        /**
110 11113 nacho
         * Asigna un valor para una posici?n del histograma
111
         * @param band Valor del pixel o clase a asignar
112 10939 nacho
         * @param px Valor del pixel
113
         * @param value Valor a asignar
114
         */
115 11113 nacho
        public void setHistogramValue(int band, double px, long value) {
116 11185 bsanchez
                int pos = (int) ((nClasses * (px - min))/(max-min));
117
                if (pos < 0) pos = 0;
118
                if (pos >= nClasses) pos = nClasses - 1;
119
                table[band][pos] = value;
120 10939 nacho
        }
121
122
        /**
123 11185 bsanchez
         * Asigna un valor para una posici?n del histograma segun la posicion en las
124
         * clases
125
         * @param band Valor del pixel o clase a asignar
126
         * @param pos Posicion dentro de la clase. Ejemplo 0..63
127
         * @param value Valor a asignar
128
         */
129
        public void setHistogramValueByPos(int band, int pos, long value) {
130
                if (pos < 0) pos = 0;
131
                if (pos >= nClasses) pos = nClasses - 1;
132
                table[band][pos] = value;
133
        }
134
135
        /**
136 10939 nacho
         * Obtiene un valor del histograma
137
         * @param band N?mero de banda del valor a recuperar
138
         * @param px Pixel o valor de la clase del valor a recuperar
139
         * @return valor
140
         */
141 11185 bsanchez
        public double getHistogramValue(int band, double px) {
142
                if (histogram == null) getHistogram();
143 11113 nacho
                for (int i = 0; i < histogram[band].length; i++) {
144 11185 bsanchez
                        if (((HistogramClass)histogram[band][i]).isIn(px))
145
                                return ((HistogramClass)histogram[band][i]).getValue();
146 11113 nacho
                }
147
                return 0;
148 10939 nacho
        }
149
150 11185 bsanchez
        /**
151
         * Obtiene un valor del histograma segun la posicion dentro de las clases
152
         * @param band N?mero de banda del valor a recuperar
153
         * @param px Pixel o valor de la clase del valor a recuperar
154
         * @return valor
155
         */
156
        public double getHistogramValueByPos(int band, int pos) {
157
                if (pos < 0) pos = 0;
158
                if (pos >= nClasses) pos = nClasses - 1;
159
                return table[band][pos];
160
        }
161 11113 nacho
162 10939 nacho
        /**
163
         * Incrementa un valor de una posici?n del histograma
164
         * @param band N?mero de banda
165
         * @param px Pixel o valor de la clase
166
         */
167 11113 nacho
        public void incrementPxValue(int band, double px) {
168 11185 bsanchez
                int pos = (int) ((nClasses * (px - min))/(max-min));
169
                if (pos < 0) pos = 0;
170
                if (pos >= nClasses) pos = nClasses - 1;
171
                table[band][pos]++;
172 10939 nacho
        }
173
174
        /**
175
         * Devuelve el histograma acumulado
176
         * @return
177
         */
178 11113 nacho
        public HistogramClass[][] getAccumulatedHistogram() {
179 11185 bsanchez
                if (histogram != null) {
180
                        HistogramClass[][] hist = new HistogramClass[histogram.length][histogram[0].length];
181 10939 nacho
                        for (int iBand = 0; iBand < hist.length; iBand++) {
182 11185 bsanchez
                                hist[iBand][0] = new HistogramClass(histogram[iBand][0].getMin(), histogram[iBand][0].getMax());
183
                                hist[iBand][0].setValue(histogram[iBand][0].getValue());
184 11080 nacho
                                for (int j = 1; j < hist[iBand].length; j++) {
185 11185 bsanchez
                                        hist[iBand][j] = new HistogramClass(histogram[iBand][j].getMin(), histogram[iBand][j].getMax());
186
                                        hist[iBand][j].setValue(hist[iBand][j - 1].getValue() + histogram[iBand][j].getValue());
187 10939 nacho
                                }
188
                        }
189 11080 nacho
                        return hist;
190 10939 nacho
                }
191 11185 bsanchez
                return null;
192 10939 nacho
        }
193
194
        /**
195 11080 nacho
         * Devuelve el histograma logaritmico
196 10939 nacho
         * @return
197
         */
198 11113 nacho
        public HistogramClass[][] getLogaritmicHistogram() {
199 11185 bsanchez
                if (histogram != null) {
200
                        HistogramClass[][] hist = new HistogramClass[histogram.length][histogram[0].length];
201
                        double minim = Double.MAX_VALUE;
202 11080 nacho
                        for (int iBand = 0; iBand < histogram.length; iBand++) {
203 11185 bsanchez
                                for (int j = 0; j < histogram[iBand].length; j++) {
204
                                        if (minim > histogram[iBand][j].getValue())
205
                                                minim = histogram[iBand][j].getValue();
206
                                }
207 11080 nacho
                        }
208 11185 bsanchez
                        for (int iBand = 0; iBand < histogram.length; iBand++) {
209
                                for (int j = 0; j < histogram[iBand].length; j++) {
210
                                        hist[iBand][j] = new HistogramClass(histogram[iBand][j].getMin(), histogram[iBand][j].getMax());
211
                                        hist[iBand][j].setValue(java.lang.Math.log(histogram[iBand][j].getValue() - minim + 1.0));
212
                                }
213
                        }
214 11080 nacho
                        return hist;
215
                }
216 11185 bsanchez
                return null;
217
218 10939 nacho
        }
219
220
        /**
221
         * N?mero de tipos de histograma definidos en esta clase.
222
         * @return entero con el n?mero de tipos definidos.
223
         */
224 11080 nacho
        public static int getHistogramTypesCount() {
225 10939 nacho
                return types.length;
226
        }
227
228
        /**
229
         * Obtiene un tipo de histograma a partir de su posici?n en el array
230
         * @param pos posici?n en el array del tipo a obtener
231
         * @return Tipo
232
         */
233 11080 nacho
        public static String getType(int pos) {
234 10939 nacho
                return types[pos];
235
        }
236
237 10943 nacho
        /**
238
         * Obtiene el histograma correspondiente al tipo pasado por par?metro. Los tipos
239
         * est?n definidos en esta misma clase de forma est?tica en la variable types.
240
         * @param type Tipo a devolver
241
         * @return Histograma
242
         */
243 11113 nacho
        public HistogramClass[][] getHistogramByType(String type) {
244 10943 nacho
                if(type.equals(types[0]))
245
                        return getHistogram();
246
                if(type.equals(types[1]))
247
                        return getAccumulatedHistogram();
248
                if(type.equals(types[2]))
249
                        return getLogaritmicHistogram();
250
                return null;
251
        }
252 10973 nacho
253 11080 nacho
  /**
254
   * Calculo de estad?sticas a partir de un histograma. El resultado de la funci?n es un array
255
   * bidimensional donde el primer ?ndice inndica la estadistica y el segundo el n?mero de banda.
256
   *
257
   * <UL>
258
   * <LI>m?nimo</LI>
259
   * <LI>m?ximo</LI>
260
   * <LI>media</LI>
261
   * <LI>mediana</LI>
262
   * <LI>N?mero de pixels</LI>
263
   * </UL>
264
   * @param histogram
265
   * @param bandas solicitadas. Cada elemento del vector representa una banda. Si est? a true se calcula la
266
   * estadistica para esa banda y si est? a false no se calcular?.
267
   * @return
268
   */
269
  public long[][] getBasicStats(boolean[] bands) {
270 11185 bsanchez
          if (histogram == null)
271 11080 nacho
                  return null;
272
          return getBasicStats(0, histogram[0].length - 1, bands);
273
  }
274
275
  /**
276
   * Calculo de estad?sticas a partir de un histograma. El resultado de la funci?n es un array
277
   * bidimensional donde el primer ?ndice inndica la estadistica y el segundo el n?mero de banda.
278
   *
279
   * <UL>
280
   * <LI>m?nimo</LI>
281
   * <LI>m?ximo</LI>
282
   * <LI>media</LI>
283
   * <LI>mediana</LI>
284
   * <LI>N?mero de pixels</LI>
285
   * </UL>
286
   * @param histogram
287
   * @param beginPos Posici?n de inicio del histograma para contabilizar estadisticas
288
   * @param endPos Posici?n de fin del histograma para contabilizar estadisticas
289
   * @param bandas solicitadas. Cada elemento del vector representa una banda. Si est? a true se calcula la
290
   * estadistica para esa banda y si est? a false no se calcular?.
291
   * @return
292
   */
293 11185 bsanchez
  public long[][] getBasicStats(int beginPos2, int endPos2, boolean[] bands){
294
          if (histogram == null) getHistogram();
295 11080 nacho
296 11185 bsanchez
          // Preparar las posiciones para los rangos de los HistogramClass
297
          int beginPos = (int) ((nClasses * (beginPos2 - min)) / (max - min));
298
                if (beginPos < 0) beginPos = 0;
299
                if (beginPos >= nClasses) beginPos = nClasses - 1;
300
          int endPos = (int) ((nClasses * (endPos2 - min)) / (max - min));
301
                if (endPos < 0) endPos = 0;
302
                if (endPos >= nClasses) endPos = nClasses - 1;
303
304 11080 nacho
          //Contamos el n?mero de bandas para las cuales se calcula la estad?stica
305 11185 bsanchez
          int bandCount = 0;
306
          for (int iBand = 0; iBand < bands.length; iBand ++)
307
                  if (bands[iBand]) bandCount ++;
308 11080 nacho
309
          int values = 5;
310
          long[][] res = new long[values][];
311
312
          long[] min = new long[bandCount];//M?nimo
313
          long[] max = new long[bandCount];//M?ximo
314 11185 bsanchez
          for (int iBand = 0; iBand < bandCount; iBand ++) {
315 11080 nacho
                  max[iBand] = beginPos;
316
                  min[iBand] = endPos;
317
          }
318
          long[] average = new long[bandCount]; //Valor de pixel medio (Media)
319
          long[] middle = new long[bandCount]; //Mediana
320
          long[] nPixelsBand = new long[bandCount];//N?mero de pixels por banda
321
322
          int showBandCounter = 0;  //Contador de bandas de las que hay calcular la estadistica
323 11185 bsanchez
          for (int iBand = 0; iBand < histogram.length; iBand ++){
324 11080 nacho
                  if(bands[iBand]){
325
                    int pixels = 0; //N?mero de valores por banda (entre 0 y 255)
326
                        for(int i = beginPos; i <= endPos; i ++){
327 10973 nacho
328 11080 nacho
                                //Calculo del m?nimo
329 11185 bsanchez
                                if(histogram[iBand][i].getValue() != 0 && i < min[showBandCounter])
330 11080 nacho
                                        min[showBandCounter] = i;
331 10973 nacho
332 11080 nacho
                                //Calculo del m?ximo
333 11185 bsanchez
                                if(histogram[iBand][i].getValue() != 0 && i > max[showBandCounter])
334 11080 nacho
                                        max[showBandCounter] = i;
335
336
                                //Calculo del n?mero de pixeles
337 11185 bsanchez
                                nPixelsBand[showBandCounter] += (long)histogram[iBand][i].getValue();
338 11080 nacho
339 11185 bsanchez
                                if(histogram[iBand][i].getValue() != 0)
340 11080 nacho
                                        pixels ++;
341
342 11185 bsanchez
                                average[showBandCounter] += histogram[iBand][i].getValue() * i;
343 11080 nacho
                        }
344
                        //Calculo de la media
345
                        try{
346
                                average[showBandCounter] /= nPixelsBand[showBandCounter];
347
                        }catch(ArithmeticException exc){
348
                                average[showBandCounter] = 0;
349
                        }
350
351
                        //Calculo de mediana
352
                        long middlePos = nPixelsBand[showBandCounter] >> 1;
353
                        int aux = 0;
354
                        int i = beginPos;
355
                        for(i = beginPos; aux < middlePos; i++)
356 11185 bsanchez
                                aux += histogram[iBand][i].getValue();
357 11080 nacho
                        middle[showBandCounter] = i - 1;
358
359
                        showBandCounter ++;
360
                  }
361
          }
362
363
          res[0] = min;
364
          res[1] = max;
365
          res[2] = average;
366
          res[3] = middle;
367
          res[4] = nPixelsBand;
368 11185 bsanchez
          return res;
369 11080 nacho
  }
370
}