root / trunk / libraries / libRaster / src / org / gvsig / raster / util / Histogram.java @ 11219
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 | 11219 | bsanchez | private double max = Double.NEGATIVE_INFINITY; |
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 | } |