Statistics
| Revision:

root / trunk / libraries / libRaster / src / org / gvsig / raster / datastruct / Histogram.java @ 12383

History | View | Annotate | Download (11.7 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.datastruct;
20

    
21

    
22

    
23
/**
24
 * Representa un histograma.
25
 * @version 27/03/2007
26
 * @author Nacho Brodin (nachobrodin@gmail.com)
27
 *
28
 */
29
public class Histogram {
30
        /**
31
         * Variable que representa el histograma. La primera dimensi?n es el n?mero de 
32
         * bandas y la segunda un array de clases. En el caso b?sico de un RGB una clase tendr? el
33
         * valor m?nimo igual al m?ximo.
34
         */
35
        private HistogramClass[][] histogram = null;
36
        private int nClasses = 0;
37
        
38
        private long[][] table = null;
39
        private static String[] types = {"normal", "accumulated", "logaritmic"};
40
        private double min = Double.MAX_VALUE;
41
        private double max = Double.NEGATIVE_INFINITY;
42
        
43
        /**
44
         * Constructor
45
         */
46
        public Histogram(int nBands, int nClasses, double min, double max) {
47
                table = new long[nBands][nClasses];
48
                for (int i=0; i < table.length; i++)
49
                        for (int j = 0; j < table[0].length; j++)
50
                                table[i][j] = 0;
51
                this.min = min;
52
                this.max = max;
53
                this.nClasses = nClasses;
54
        }
55
        
56
        /**
57
         * Asigna la tabla
58
         * @param t
59
         */
60
        public void setTable(long[][] t) {
61
                table = t;
62
        }
63
                
64
        /**
65
         * Obtiene el histograma sin modificar
66
         * @return array bidimensional donde el primer elemento es el valor del pixel
67
         * o rango y el segundo el n?mero de elementos que aparecen.
68
         */
69
        public HistogramClass[][] getHistogram() {
70
                if (nClasses <= 0)
71
                        return null;
72
                
73
                histogram = new HistogramClass[table.length][nClasses];
74
                
75
                for (int i = 0; i < table.length; i++) {
76
                        for (int j = 0; j < nClasses; j++) {
77
                                HistogramClass hc = new HistogramClass(        min + ((j * (max - min)) / nClasses), 
78
                                                                                                                min + (((j + 1) * (max - min)) / nClasses));
79
                                hc.setValue(table[i][j]);
80
                                histogram[i][j] = hc;
81
                        }
82
                }
83
                return histogram;
84
        }
85
        
86
        /**
87
         * Obtiene el n?mero de bandas del histograma 
88
         * @return entero que representa el n?mero de bandas 
89
         */
90
        public int getNumBands() {
91
                if (table != null)
92
                        return table.length;
93
                return 0;
94
        }
95
        
96
        /**
97
         * Obtiene la longitud (n?mero de valores) de una banda determinada
98
         * @param band Banda o obtener la longitud
99
         * @return entero con la longitud de la banda
100
         * rangos de valores y DataclassList.
101
         */
102
        public int getBandLenght(int band) {
103
                if (table != null)
104
                        return table[band].length;
105
                return 0;
106
        }
107
        
108
        /**
109
         * Obtiene el n?mero de valores o clases del histograma
110
         * @return entero que representa el n?mero de valores o clases del histograma
111
         */
112
        public int getNumValues() {
113
                return nClasses;
114
        }
115
        
116
        /**
117
         * Asigna un histograma
118
         * @param hist histograma asignado
119
         */
120
        public void setHistogram(HistogramClass[][] hist){
121
                histogram = hist;
122
        }
123
                
124
        /**
125
         * Asigna un valor para una posici?n del histograma
126
         * @param band Valor del pixel o clase a asignar
127
         * @param px Valor del pixel
128
         * @param value Valor a asignar
129
         */
130
        public void setHistogramValue(int band, double px, long value) {
131
                int pos = (int) ((nClasses * (px - min))/(max-min));
132
                if (pos < 0) pos = 0;
133
                if (pos >= nClasses) pos = nClasses - 1;
134
                table[band][pos] = value;
135
        }
136
        
137
        /**
138
         * Asigna un valor para una posici?n del histograma segun la posicion en las
139
         * clases
140
         * @param band Valor del pixel o clase a asignar
141
         * @param pos Posicion dentro de la clase. Ejemplo 0..63
142
         * @param value Valor a asignar
143
         */
144
        public void setHistogramValueByPos(int band, int pos, long value) {
145
                if (pos < 0) pos = 0;
146
                if (pos >= nClasses) pos = nClasses - 1;
147
                table[band][pos] = value;
148
        }
149

    
150
        /**
151
         * Obtiene un valor del histograma
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 getHistogramValue(int band, double px) {
157
                if (histogram == null) getHistogram();
158
                for (int i = 0; i < histogram[band].length; i++) {
159
                        if (((HistogramClass)histogram[band][i]).isIn(px))
160
                                return ((HistogramClass)histogram[band][i]).getValue();
161
                }                
162
                return 0;
163
        }
164
        
165
        /**
166
         * Obtiene un valor del histograma segun la posicion dentro de las clases
167
         * @param band N?mero de banda del valor a recuperar
168
         * @param px Pixel o valor de la clase del valor a recuperar
169
         * @return valor
170
         */
171
        public double getHistogramValueByPos(int band, int pos) {
172
                if (pos < 0) pos = 0;
173
                if (pos >= nClasses) 
174
                        pos = nClasses - 1;
175
                return table[band][pos];
176
        }
177
        
178
        /**
179
         * Incrementa un valor de una posici?n del histograma
180
         * @param band N?mero de banda
181
         * @param px Pixel o valor de la clase
182
         */
183
        public void incrementPxValue(int band, double px) {
184
                int pos = (int) ((nClasses * (px - min)) / (max - min));
185
                if (pos < 0) 
186
                        pos = 0;
187
                if (pos >= nClasses) 
188
                        pos = nClasses - 1;
189
                table[band][pos]++;
190
        }
191
        
192
        /**
193
         * Devuelve el histograma acumulado
194
         * @return
195
         */
196
        public HistogramClass[][] getAccumulatedHistogram() {
197
                if (histogram != null) {
198
                        HistogramClass[][] hist = new HistogramClass[histogram.length][histogram[0].length];
199
                        for (int iBand = 0; iBand < hist.length; iBand++) {
200
                                hist[iBand][0] = new HistogramClass(histogram[iBand][0].getMin(), histogram[iBand][0].getMax());
201
                                hist[iBand][0].setValue(histogram[iBand][0].getValue());
202
                                for (int j = 1; j < hist[iBand].length; j++) {
203
                                        hist[iBand][j] = new HistogramClass(histogram[iBand][j].getMin(), histogram[iBand][j].getMax());
204
                                        hist[iBand][j].setValue(hist[iBand][j - 1].getValue() + histogram[iBand][j].getValue());
205
                                }
206
                        }
207
                        return hist;
208
                }
209
                return null;
210
        }
211
        
212
        /**
213
         * Devuelve el histograma logaritmico
214
         * @return
215
         */
216
        public HistogramClass[][] getLogaritmicHistogram() {
217
                if (histogram != null) {
218
                        HistogramClass[][] hist = new HistogramClass[histogram.length][histogram[0].length];
219
                        double minim = Double.MAX_VALUE;
220
                        for (int iBand = 0; iBand < histogram.length; iBand++) {
221
                                for (int j = 0; j < histogram[iBand].length; j++) {
222
                                        if (minim > histogram[iBand][j].getValue())
223
                                                minim = histogram[iBand][j].getValue();
224
                                }
225
                        }
226
                        for (int iBand = 0; iBand < histogram.length; iBand++) {
227
                                for (int j = 0; j < histogram[iBand].length; j++) {
228
                                        hist[iBand][j] = new HistogramClass(histogram[iBand][j].getMin(), histogram[iBand][j].getMax());
229
                                        hist[iBand][j].setValue(java.lang.Math.log(histogram[iBand][j].getValue() - minim + 1.0));
230
                                }
231
                        }
232
                        return hist;
233
                }
234
                return null;
235

    
236
        }
237
        
238
        /**
239
         * N?mero de tipos de histograma definidos en esta clase.
240
         * @return entero con el n?mero de tipos definidos.
241
         */
242
        public static int getHistogramTypesCount() {
243
                return types.length;
244
        }
245
        
246
        /**
247
         * Obtiene un tipo de histograma a partir de su posici?n en el array
248
         * @param pos posici?n en el array del tipo a obtener
249
         * @return Tipo
250
         */
251
        public static String getType(int pos) {
252
                return types[pos];
253
        }
254
        
255
        /**
256
         * Obtiene el histograma correspondiente al tipo pasado por par?metro. Los tipos
257
         * est?n definidos en esta misma clase de forma est?tica en la variable types.
258
         * @param type Tipo a devolver
259
         * @return Histograma
260
         */
261
        public HistogramClass[][] getHistogramByType(String type) {
262
                if(type.equals(types[0]))
263
                        return getHistogram();
264
                if(type.equals(types[1]))
265
                        return getAccumulatedHistogram();
266
                if(type.equals(types[2]))
267
                        return getLogaritmicHistogram();
268
                return null;
269
        }
270
        
271
  /**
272
   * Calculo de estad?sticas a partir de un histograma. El resultado de la funci?n es un array
273
   * bidimensional donde el primer ?ndice inndica la estadistica y el segundo el n?mero de banda.
274
   * 
275
   * <UL>
276
   * <LI>m?nimo</LI>
277
   * <LI>m?ximo</LI>
278
   * <LI>media</LI>
279
   * <LI>mediana</LI>
280
   * <LI>N?mero de pixels</LI>
281
   * </UL>
282
   * @param histogram
283
   * @param bandas solicitadas. Cada elemento del vector representa una banda. Si est? a true se calcula la 
284
   * estadistica para esa banda y si est? a false no se calcular?.
285
   * @return
286
   */
287
  public long[][] getBasicStats(boolean[] bands) {
288
          if (histogram == null)
289
                  return null;
290
          return getBasicStats(0, histogram[0].length - 1, bands);
291
  }
292

    
293
  /**
294
   * Calculo de estad?sticas a partir de un histograma. El resultado de la funci?n es un array
295
   * bidimensional donde el primer ?ndice inndica la estadistica y el segundo el n?mero de banda.
296
   * 
297
   * <UL>
298
   * <LI>m?nimo</LI>
299
   * <LI>m?ximo</LI>
300
   * <LI>media</LI>
301
   * <LI>mediana</LI>
302
   * <LI>N?mero de pixels</LI>
303
   * </UL>
304
   * @param histogram
305
   * @param beginPos Posici?n de inicio del histograma para contabilizar estadisticas
306
   * @param endPos Posici?n de fin del histograma para contabilizar estadisticas
307
   * @param bandas solicitadas. Cada elemento del vector representa una banda. Si est? a true se calcula la 
308
   * estadistica para esa banda y si est? a false no se calcular?.
309
   * @return
310
   */
311
  public long[][] getBasicStats(int beginPos2, int endPos2, boolean[] bands){
312
          if (histogram == null) getHistogram();
313
          
314
          // Preparar las posiciones para los rangos de los HistogramClass
315
          int beginPos = (int) ((nClasses * (beginPos2 - min)) / (max - min));
316
                if (beginPos < 0) beginPos = 0;
317
                if (beginPos >= nClasses) beginPos = nClasses - 1;
318
          int endPos = (int) ((nClasses * (endPos2 - min)) / (max - min));
319
                if (endPos < 0) endPos = 0;
320
                if (endPos >= nClasses) endPos = nClasses - 1;
321
          
322
          //Contamos el n?mero de bandas para las cuales se calcula la estad?stica
323
          int bandCount = 0;
324
          for (int iBand = 0; iBand < bands.length; iBand ++)
325
                  if (bands[iBand]) bandCount ++;
326
          
327
          int values = 5;
328
          long[][] res = new long[values][];
329
          
330
          long[] min = new long[bandCount];//M?nimo
331
          long[] max = new long[bandCount];//M?ximo
332
          for (int iBand = 0; iBand < bandCount; iBand ++) {
333
                  max[iBand] = beginPos;
334
                  min[iBand] = endPos;
335
          }
336
          long[] average = new long[bandCount]; //Valor de pixel medio (Media)
337
          long[] middle = new long[bandCount]; //Mediana
338
          long[] nPixelsBand = new long[bandCount];//N?mero de pixels por banda
339
                                              
340
          int showBandCounter = 0;  //Contador de bandas de las que hay calcular la estadistica
341
          for (int iBand = 0; iBand < histogram.length; iBand ++){
342
                  if(bands[iBand]){
343
                    int pixels = 0; //N?mero de valores por banda (entre 0 y 255)
344
                        for(int i = beginPos; i <= endPos; i ++){
345
                                
346
                                //Calculo del m?nimo
347
                                if(histogram[iBand][i].getValue() != 0 && i < min[showBandCounter])
348
                                        min[showBandCounter] = i;
349
                                
350
                                //Calculo del m?ximo                                                                                
351
                                if(histogram[iBand][i].getValue() != 0 && i > max[showBandCounter])
352
                                        max[showBandCounter] = i;
353
                                
354
                                //Calculo del n?mero de pixeles
355
                                nPixelsBand[showBandCounter] += (long)histogram[iBand][i].getValue();
356
                                
357
                                if(histogram[iBand][i].getValue() != 0)
358
                                        pixels ++;
359
                                
360
                                average[showBandCounter] += histogram[iBand][i].getValue() * i;
361
                        }
362
                        //Calculo de la media
363
                        try{
364
                                average[showBandCounter] /= nPixelsBand[showBandCounter];
365
                        }catch(ArithmeticException exc){
366
                                average[showBandCounter] = 0;
367
                        }
368
                        
369
                        //Calculo de mediana
370
                        long middlePos = nPixelsBand[showBandCounter] >> 1;
371
                        int aux = 0;
372
                        int i = beginPos;
373
                        for(i = beginPos; aux < middlePos; i++)
374
                                aux += histogram[iBand][i].getValue();
375
                        middle[showBandCounter] = i - 1;
376
                        
377
                        showBandCounter ++;
378
                  }
379
          }
380
   
381
          res[0] = min;
382
          res[1] = max;
383
          res[2] = average;
384
          res[3] = middle;
385
          res[4] = nPixelsBand;
386
          return res;
387
  }
388
}