Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / gridAnalysis / supervisedClassificationB / SupervisedClassificationBAlgorithm.java @ 59

History | View | Annotate | Download (11.3 KB)

1
package es.unex.sextante.gridAnalysis.supervisedClassificationB;
2

    
3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.Iterator;
6
import java.util.Set;
7

    
8
import es.unex.sextante.additionalInfo.AdditionalInfoMultipleInput;
9
import es.unex.sextante.core.AnalysisExtent;
10
import es.unex.sextante.core.GeoAlgorithm;
11
import es.unex.sextante.core.Sextante;
12
import es.unex.sextante.dataObjects.IRasterLayer;
13
import es.unex.sextante.dataObjects.IRecord;
14
import es.unex.sextante.dataObjects.IRecordsetIterator;
15
import es.unex.sextante.dataObjects.ITable;
16
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
17
import es.unex.sextante.exceptions.RepeatedParameterNameException;
18
import es.unex.sextante.parameters.RasterLayerAndBand;
19

    
20
public class SupervisedClassificationBAlgorithm
21
         extends
22
            GeoAlgorithm {
23

    
24
   public static final String INPUT                 = "INPUT";
25
   public static final String METHOD                = "METHOD";
26
   public static final String CLASSIFICATION        = "CLASSIFICATION";
27
   public static final String CLASSES               = "CLASSES";
28
   public static final String TABLE                 = "TABLE";
29

    
30
   public static final int    METHOD_PARALELLPIPED  = 0;
31
   public static final int    METHOD_MIN_DISTANCE   = 1;
32
   public static final int    METHOD_MAX_LIKELIHOOD = 2;
33

    
34
   private IRasterLayer[]     m_Window;
35
   private IRasterLayer       m_Output;
36
   private ArrayList          m_Bands;
37
   private HashMap            m_Classes;
38
   private int[]              m_iBands;
39

    
40

    
41
   @Override
42
   public void defineCharacteristics() {
43

    
44
      final String sMethod[] = { Sextante.getText("Parallelepiped"), Sextante.getText("Minimum_distance"),
45
               Sextante.getText("Maximum_likelihood") };
46

    
47
      setName(Sextante.getText("Supervised_classification") + "(B)");
48
      setGroup(Sextante.getText("Raster_layer_analysis"));
49
      setUserCanDefineAnalysisExtent(true);
50

    
51
      try {
52
         m_Parameters.addMultipleInput(INPUT, Sextante.getText("Bands"), AdditionalInfoMultipleInput.DATA_TYPE_BAND, true);
53
         m_Parameters.addInputTable(TABLE, Sextante.getText("Classes"), true);
54
         m_Parameters.addSelection(METHOD, Sextante.getText("Method"), sMethod);
55
         addOutputRasterLayer(CLASSIFICATION, Sextante.getText("Classification"));
56
         //addOutputTable(CLASSES, Sextante.getText("Classes"));
57
      }
58
      catch (final RepeatedParameterNameException e) {
59
         Sextante.addErrorToLog(e);
60
      }
61

    
62
   }
63

    
64

    
65
   @Override
66
   public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
67

    
68
      int i;
69
      AnalysisExtent ge;
70

    
71
      final int iMethod = m_Parameters.getParameterValueAsInt(METHOD);
72
      m_Bands = m_Parameters.getParameterValueAsArrayList(INPUT);
73

    
74

    
75
      if (m_Bands.size() == 0) {
76
         return false;
77
      }
78

    
79
      m_Classes = new HashMap();
80

    
81
      getClassInformation();
82

    
83
      if (m_Task.isCanceled()) {
84
         return false;
85
      }
86

    
87
      m_Output = getNewRasterLayer(CLASSIFICATION, Sextante.getText("Classification"), IRasterLayer.RASTER_DATA_TYPE_SHORT);
88
      m_Output.setNoDataValue(-1);
89
      ge = m_Output.getWindowGridExtent();
90

    
91
      m_Window = new IRasterLayer[m_Bands.size()];
92
      m_iBands = new int[m_Bands.size()];
93
      for (i = 0; i < m_Window.length; i++) {
94
         final RasterLayerAndBand band = (RasterLayerAndBand) m_Bands.get(i);
95
         m_iBands[i] = band.getBand();
96
         m_Window[i] = band.getRasterLayer();
97
         m_Window[i].setWindowExtent(ge);
98
      }
99

    
100
      switch (iMethod) {
101
         case 0:
102
            doParalellpiped();
103
         case 1:
104
         default:
105
            doMinimumDistance();
106
         case 2:
107
            doMaximumLikelihood();
108
      }
109

    
110
      return !m_Task.isCanceled();
111

    
112
   }
113

    
114

    
115
   private void getClassInformation() throws GeoAlgorithmExecutionException {
116

    
117
      try {
118
         final ITable table = m_Parameters.getParameterValueAsTable(TABLE);
119
         m_Window = new IRasterLayer[m_Bands.size()];
120

    
121
         final IRecordsetIterator iter = table.iterator();
122
         while (iter.hasNext()) {
123
            final IRecord record = iter.next();
124
            final String sClassName = record.getValue(0).toString();
125
            final ArrayList stats = new ArrayList();
126
            for (int i = 0; i < m_Window.length; i++) {
127
               final String sFieldName = m_Window[i].getName() + "|" + Integer.toString(m_iBands[i] + 1);
128
               final MeanAndStdDev masd = new MeanAndStdDev();
129
               boolean bMatchFound = false;
130
               for (int j = 1; j < table.getFieldCount(); j += 2) {
131
                  if (table.getFieldName(j).equals(sFieldName)) {
132
                     masd.mean = Double.parseDouble(record.getValue(j).toString());
133
                     masd.stdDev = Double.parseDouble(record.getValue(j + 1).toString());
134
                     bMatchFound = true;
135
                  }
136
               }
137
               if (!bMatchFound) {
138
                  throw new GeoAlgorithmExecutionException(Sextante.getText("Error_reading_table"));
139
               }
140
               stats.add(masd);
141
            }
142
            m_Classes.put(sClassName, stats);
143
         }
144
      }
145
      catch (final Exception e) {
146
         throw new GeoAlgorithmExecutionException(Sextante.getText("Error_reading_table"));
147
      }
148

    
149

    
150
   }
151

    
152

    
153
   private void doParalellpiped() {
154

    
155
      int iNX, iNY;
156
      int x, y;
157
      int iMatchingClass = 0;
158
      int iClass, iGrid;
159
      final double dMean[][] = new double[m_Classes.size()][m_Window.length];
160
      final double dStdDev[][] = new double[m_Classes.size()][m_Window.length];
161
      double dValue;
162
      ArrayList stats;
163
      MeanAndStdDev substats;
164
      Set set;
165
      Iterator iter;
166

    
167
      iNX = m_Output.getWindowGridExtent().getNX();
168
      iNY = m_Output.getWindowGridExtent().getNY();
169

    
170
      set = m_Classes.keySet();
171
      iter = set.iterator();
172
      iClass = 0;
173
      while (iter.hasNext()) {
174
         stats = (ArrayList) m_Classes.get(iter.next());
175
         for (iGrid = 0; iGrid < m_Window.length; iGrid++) {
176
            substats = ((MeanAndStdDev) stats.get(iGrid));
177
            dMean[iClass][iGrid] = substats.mean;
178
            dStdDev[iClass][iGrid] = substats.stdDev;
179
         }
180
         iClass++;
181
      }
182

    
183
      for (y = 0; y < iNY; y++) {
184
         for (x = 0; x < iNX; x++) {
185
            for (iClass = 0; iClass < m_Classes.size(); iClass++) {
186
               iMatchingClass = iClass;
187
               for (iGrid = 0; iGrid < m_Window.length; iGrid++) {
188
                  dValue = m_Window[iGrid].getCellValueAsDouble(x, y);
189
                  if (!m_Window[iGrid].isNoDataValue(dValue)) {
190
                     if (Math.abs(m_Window[iGrid].getCellValueAsDouble(x, y) - dMean[iClass][iGrid]) > dStdDev[iClass][iGrid]) {
191
                        iMatchingClass = -1;
192
                        break;
193
                     }
194
                  }
195
                  else {
196
                     break;
197
                  }
198
               }
199
               if (iMatchingClass != -1) {
200
                  break;
201
               }
202
            }
203
            if (iMatchingClass != -1) {
204
               m_Output.setCellValue(x, y, iMatchingClass + 1);
205
            }
206
            else {
207
               m_Output.setNoData(x, y);
208
            }
209
         }
210
      }
211

    
212
   }
213

    
214

    
215
   private void doMinimumDistance() {
216

    
217
      int iNX, iNY;
218
      int x, y;
219
      int iClass, iGrid, iMin = 0;
220
      final double dMean[][] = new double[m_Classes.size()][m_Window.length];
221
      double dMin, d, e;
222
      double dValue;
223
      ArrayList stats;
224
      Set set;
225
      Iterator iter;
226

    
227
      iNX = m_Output.getWindowGridExtent().getNX();
228
      iNY = m_Output.getWindowGridExtent().getNY();
229

    
230
      set = m_Classes.keySet();
231
      iter = set.iterator();
232
      iClass = 0;
233
      while (iter.hasNext()) {
234
         stats = (ArrayList) m_Classes.get(iter.next());
235
         for (iGrid = 0; iGrid < m_Window.length; iGrid++) {
236
            dMean[iClass][iGrid] = ((MeanAndStdDev) stats.get(iGrid)).mean;
237
         }
238
         iClass++;
239
      }
240

    
241
      for (y = 0; y < iNY; y++) {
242
         for (x = 0; x < iNX; x++) {
243
            for (iClass = 0, dMin = -1.0; iClass < m_Classes.size(); iClass++) {
244
               for (iGrid = 0, d = 0.0; iGrid < m_Window.length; iGrid++) {
245
                  dValue = m_Window[iGrid].getCellValueAsDouble(x, y);
246
                  if (!m_Window[iGrid].isNoDataValue(dValue)) {
247
                     e = m_Window[iGrid].getCellValueAsDouble(x, y) - dMean[iClass][iGrid];
248
                     d += e * e;
249
                     if ((dMin < 0.0) || (dMin > d)) {
250
                        dMin = d;
251
                        iMin = iClass;
252
                     }
253
                  }
254
                  else {
255
                     dMin = -1;
256
                  }
257
               }
258
            }
259

    
260
            if (dMin >= 0.0) {
261
               m_Output.setCellValue(x, y, iMin + 1);
262
            }
263
            else {
264
               m_Output.setNoData(x, y);
265
            }
266
         }
267
      }
268

    
269
   }
270

    
271

    
272
   private void doMaximumLikelihood() {
273

    
274
      int iNX, iNY;
275
      int x, y;
276
      int iClass, iGrid, iMax = 0;
277
      final double dMean[][] = new double[m_Classes.size()][m_Window.length];
278
      final double dStdDev[][] = new double[m_Classes.size()][m_Window.length];
279
      final double dK[][] = new double[m_Classes.size()][m_Window.length];
280
      double dMax, d, e;
281
      double dValue;
282
      ArrayList stats;
283
      MeanAndStdDev substats;
284
      Set set;
285
      Iterator iter;
286

    
287
      iNX = m_Output.getWindowGridExtent().getNX();
288
      iNY = m_Output.getWindowGridExtent().getNY();
289

    
290
      set = m_Classes.keySet();
291
      iter = set.iterator();
292
      iClass = 0;
293
      while (iter.hasNext()) {
294
         stats = (ArrayList) m_Classes.get(iter.next());
295
         for (iGrid = 0; iGrid < m_Window.length; iGrid++) {
296
            substats = ((MeanAndStdDev) stats.get(iGrid));
297
            dMean[iClass][iGrid] = substats.mean;
298
            dStdDev[iClass][iGrid] = substats.stdDev;
299
            dK[iClass][iGrid] = 1.0 / (dStdDev[iClass][iGrid] * Math.sqrt(2.0 * Math.PI));
300
         }
301
         iClass++;
302
      }
303

    
304
      for (y = 0; y < iNY; y++) {
305
         for (x = 0; x < iNX; x++) {
306
            for (iClass = 0, dMax = 0.0; iClass < m_Classes.size(); iClass++) {
307
               for (iGrid = 0, d = 0.0; iGrid < m_Window.length; iGrid++) {
308
                  dValue = m_Window[iGrid].getCellValueAsDouble(x, y);
309
                  if (!m_Window[iGrid].isNoDataValue(dValue)) {
310
                     e = (m_Window[iGrid].getCellValueAsDouble(x, y) - dMean[iClass][iGrid]) / dStdDev[iClass][iGrid];
311
                     e = dK[iClass][iGrid] * Math.exp(-0.5 * e * e);
312
                     d += e * e;
313
                     if (dMax < d) {
314
                        dMax = d;
315
                        iMax = iClass;
316
                     }
317
                  }
318
                  else {
319
                     dMax = -1;
320
                  }
321
               }
322
            }
323

    
324
            if (dMax > 0.0) {
325
               m_Output.setCellValue(x, y, iMax + 1);
326
            }
327
            else {
328
               m_Output.setNoData(x, y);
329
            }
330
         }
331
      }
332

    
333
   }
334

    
335
   private class MeanAndStdDev {
336

    
337
      public double mean   = 0;
338
      public double stdDev = 0;
339

    
340
   }
341

    
342
}