Statistics
| Revision:

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

History | View | Annotate | Download (11.3 KB)

1
/* 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

    
22
/**
23
 * Representa un histograma.
24
 * @version 27/03/2007
25
 * @author Nacho Brodin (nachobrodin@gmail.com)
26
 *
27
 */
28
public class Histogram {
29
        private HistogramClass[][] histogram = null;
30
        private int nClasses = 0;
31
        
32
        private long[][] table = null;
33
        private static String[] types = {"normal", "accumulated", "logaritmic"};
34
        private double min = Double.MAX_VALUE;
35
        private double max = Double.MIN_VALUE;
36
        
37
        /**
38
         * Constructor
39
         */
40
        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
                this.nClasses = nClasses;
48
        }
49
                
50
        /**
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
        public HistogramClass[][] getHistogram() {
56
                if (nClasses <= 0)
57
                        return null;
58
                
59
                histogram = new HistogramClass[table.length][nClasses];
60
                
61
                for (int i = 0; i < table.length; i++) {
62
                        for (int j = 0; j < nClasses; j++) {
63
                                HistogramClass hc = new HistogramClass(min + ((j*(max-min))/nClasses), min + (((j+1)*(max-min))/nClasses));
64
                                hc.setValue(table[i][j]);
65
                                histogram[i][j] = hc;
66
                        }
67
                }
68
                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
                if (table != null)
77
                        return table.length;
78
                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
         * rangos de valores y DataclassList.
86
         */
87
        public int getBandLenght(int band) {
88
                if (table != null)
89
                        return table[band].length;
90
                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
                return nClasses;
99
        }
100
        
101
        /**
102
         * Asigna un histograma
103
         * @param hist histograma asignado
104
         */
105
        public void setHistogram(HistogramClass[][] hist){
106
                histogram = hist;
107
        }
108
                
109
        /**
110
         * Asigna un valor para una posici?n del histograma
111
         * @param band Valor del pixel o clase a asignar
112
         * @param px Valor del pixel
113
         * @param value Valor a asignar
114
         */
115
        public void setHistogramValue(int band, double px, long value) {
116
                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
        }
121
        
122
        /**
123
         * 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
         * 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
        public double getHistogramValue(int band, double px) {
142
                if (histogram == null) getHistogram();
143
                for (int i = 0; i < histogram[band].length; i++) {
144
                        if (((HistogramClass)histogram[band][i]).isIn(px))
145
                                return ((HistogramClass)histogram[band][i]).getValue();
146
                }                
147
                return 0;
148
        }
149
        
150
        /**
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
        
162
        /**
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
        public void incrementPxValue(int band, double px) {
168
                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
        }
173
        
174
        /**
175
         * Devuelve el histograma acumulado
176
         * @return
177
         */
178
        public HistogramClass[][] getAccumulatedHistogram() {
179
                if (histogram != null) {
180
                        HistogramClass[][] hist = new HistogramClass[histogram.length][histogram[0].length];
181
                        for (int iBand = 0; iBand < hist.length; iBand++) {
182
                                hist[iBand][0] = new HistogramClass(histogram[iBand][0].getMin(), histogram[iBand][0].getMax());
183
                                hist[iBand][0].setValue(histogram[iBand][0].getValue());
184
                                for (int j = 1; j < hist[iBand].length; j++) {
185
                                        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
                                }
188
                        }
189
                        return hist;
190
                }
191
                return null;
192
        }
193
        
194
        /**
195
         * Devuelve el histograma logaritmico
196
         * @return
197
         */
198
        public HistogramClass[][] getLogaritmicHistogram() {
199
                if (histogram != null) {
200
                        HistogramClass[][] hist = new HistogramClass[histogram.length][histogram[0].length];
201
                        double minim = Double.MAX_VALUE;
202
                        for (int iBand = 0; iBand < histogram.length; iBand++) {
203
                                for (int j = 0; j < histogram[iBand].length; j++) {
204
                                        if (minim > histogram[iBand][j].getValue())
205
                                                minim = histogram[iBand][j].getValue();
206
                                }
207
                        }
208
                        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
                        return hist;
215
                }
216
                return null;
217

    
218
        }
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
        public static int getHistogramTypesCount() {
225
                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
        public static String getType(int pos) {
234
                return types[pos];
235
        }
236
        
237
        /**
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
        public HistogramClass[][] getHistogramByType(String type) {
244
                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
        
253
  /**
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
          if (histogram == null)
271
                  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
  public long[][] getBasicStats(int beginPos2, int endPos2, boolean[] bands){
294
          if (histogram == null) getHistogram();
295
          
296
          // 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
          //Contamos el n?mero de bandas para las cuales se calcula la estad?stica
305
          int bandCount = 0;
306
          for (int iBand = 0; iBand < bands.length; iBand ++)
307
                  if (bands[iBand]) bandCount ++;
308
          
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
          for (int iBand = 0; iBand < bandCount; iBand ++) {
315
                  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
          for (int iBand = 0; iBand < histogram.length; iBand ++){
324
                  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
                                
328
                                //Calculo del m?nimo
329
                                if(histogram[iBand][i].getValue() != 0 && i < min[showBandCounter])
330
                                        min[showBandCounter] = i;
331
                                
332
                                //Calculo del m?ximo                                                                                
333
                                if(histogram[iBand][i].getValue() != 0 && i > max[showBandCounter])
334
                                        max[showBandCounter] = i;
335
                                
336
                                //Calculo del n?mero de pixeles
337
                                nPixelsBand[showBandCounter] += (long)histogram[iBand][i].getValue();
338
                                
339
                                if(histogram[iBand][i].getValue() != 0)
340
                                        pixels ++;
341
                                
342
                                average[showBandCounter] += histogram[iBand][i].getValue() * i;
343
                        }
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
                                aux += histogram[iBand][i].getValue();
357
                        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
          return res;
369
  }
370
}