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 | 59 | nbrodin | 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 | } |