All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ClassifierSAMStrategy.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib 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 Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/rp/ClassifierSAMStrategy.cpp
22 
23  \brief Maximum a posteriori probability strategy.
24 */
25 
26 // TerraLib
27 
28 #include "ClassifierSAMStrategy.h"
29 #include "Macros.h"
30 #include "../common/progress/TaskProgress.h"
31 
32 #include <cfloat>
33 #include <cmath>
34 
35 namespace
36 {
37  static te::rp::ClassifierSAMStrategyFactory classifierMAPStrategyFactoryInstance;
38 }
39 
40 //-----------------------------------------------------------------------------
41 
43 {
44  reset();
45 }
46 
48 {
49 }
50 
52 {
53  reset();
54 
55  m_trainSamplesPtr = rhs.m_trainSamplesPtr;
56  m_maxAngularDistances = rhs.m_maxAngularDistances;
57 
58  return *this;
59 }
60 
61 void te::rp::ClassifierSAMStrategy::Parameters::reset() throw(te::rp::Exception)
62 {
63  m_trainSamplesPtr.reset();
64  m_maxAngularDistances.clear();
65 }
66 
68 {
70 }
71 
72 //-----------------------------------------------------------------------------
73 
75 {
76  m_isInitialized = false;
77 }
78 
80 {
81 }
82 
84  te::rp::StrategyParameters const* const strategyParams) throw(te::rp::Exception)
85 {
86  m_isInitialized = false;
88  m_classesMeans.clear();
89  m_classesIndex2ID.clear();
90 
91  ClassifierSAMStrategy::Parameters const * const castParamsPtr =
92  dynamic_cast< ClassifierSAMStrategy::Parameters const * >( strategyParams );
93  TERP_TRUE_OR_RETURN_FALSE( castParamsPtr, "Invalid parameters" );
94 
95  // Checking the angluar distances
96 
97  TERP_TRUE_OR_RETURN_FALSE( castParamsPtr->m_maxAngularDistances.size() ==
98  castParamsPtr->m_trainSamplesPtr->size(),
99  "Mismatch between the classes number and the max angular distances" );
100 
101  for( unsigned int maxAngularDistancesIdx = 0 ; maxAngularDistancesIdx <
102  castParamsPtr->m_maxAngularDistances.size() ; ++ maxAngularDistancesIdx )
103  {
105  maxAngularDistancesIdx ] >= 0.0 ),
106  "Invalid max angular distance" );
107  }
108 
109  // Calculating m_classesMeans and m_classesIndex2ID
110 
112  "Invalid classes samples pointer" )
113  TERP_TRUE_OR_RETURN_FALSE( castParamsPtr->m_trainSamplesPtr->size() > 0,
114  "Invalid classes samples number" )
115  TERP_TRUE_OR_RETURN_FALSE( castParamsPtr->m_trainSamplesPtr->begin()->second.size() > 0,
116  "Invalid classe samples number" )
117  const unsigned int dimsNumber = (unsigned int)
118  castParamsPtr->m_trainSamplesPtr->begin()->second.operator[]( 0 ).size();
119  TERP_TRUE_OR_RETURN_FALSE( dimsNumber > 0,
120  "Invalid dimensions number" )
121 
122  {
123  ClassesSamplesT::const_iterator classesIt =
124  castParamsPtr->m_trainSamplesPtr->begin();
125  const ClassesSamplesT::const_iterator classesItE =
126  castParamsPtr->m_trainSamplesPtr->end();
127  unsigned int dimIdx = 0;
128  SamplesT::const_iterator samplesIt;
129  SamplesT::const_iterator samplesItE;
130 
131  while( classesIt != classesItE )
132  {
133  const ClassIDT& classID = classesIt->first;
134  TERP_TRUE_OR_RETURN_FALSE( classID > 0, "Invalid class ID" );
135 
136  const SamplesT& classSamples = classesIt->second;
137  TERP_TRUE_OR_RETURN_FALSE( classSamples.size() > 0,
138  "Invalid class samples number" );
139 
140  SampleT classMeans( dimsNumber );
141 
142  for( dimIdx = 0 ; dimIdx < dimsNumber ; ++dimIdx )
143  {
144  double& dimMean = classMeans[ dimIdx ];
145  dimMean = 0.0;
146 
147  samplesIt = classSamples.begin();
148  samplesItE = classSamples.end();
149 
150  while( samplesIt != samplesItE )
151  {
152  TERP_TRUE_OR_RETURN_FALSE( samplesIt->size() == dimsNumber,
153  "Sample size mismatch" )
154  dimMean += samplesIt->operator[]( dimIdx );
155 
156  ++samplesIt;
157  }
158 
159  dimMean /= (double)( classSamples.size() );
160  }
161 
162  m_classesMeans.push_back( classMeans );
163  m_classesIndex2ID.push_back( classID );
164 
165  ++classesIt;
166  }
167 
168  }
169 
170  // Finalizing
171 
172  m_initParams = (*castParamsPtr);
173 
174  m_isInitialized = true;
175 
176  return true;
177 }
178 
180  const std::vector<unsigned int>& inputRasterBands,
181  const std::vector<te::gm::Polygon*>&, te::rst::Raster& outputRaster,
182  const unsigned int outputRasterBand,
183  const bool enableProgressInterface) throw(te::rp::Exception)
184 {
186  "Classification strategy not initialized" );
187  TERP_TRUE_OR_RETURN_FALSE( inputRasterBands.size() > 0, "Invalid input bands" );
188  TERP_TRUE_OR_RETURN_FALSE( inputRasterBands.size() == m_classesMeans[ 0 ].size(),
189  "Invalid input bands" );
190  TERP_DEBUG_TRUE_OR_THROW( outputRasterBand < outputRaster.getNumberOfBands(),
191  "Invalid output band" );
192  TERP_DEBUG_TRUE_OR_THROW( inputRaster.getNumberOfColumns() ==
193  outputRaster.getNumberOfColumns(), "Rasters dims mismatch" );
194  TERP_DEBUG_TRUE_OR_THROW( inputRaster.getNumberOfRows() ==
195  outputRaster.getNumberOfRows(), "Rasters dims mismatch" );
196 
197  // progress
198 
199  std::auto_ptr< te::common::TaskProgress > progressPtr;
200  if( enableProgressInterface )
201  {
202  progressPtr.reset( new te::common::TaskProgress );
203  progressPtr->setTotalSteps( inputRaster.getNumberOfRows() );
204  progressPtr->setMessage( "Classifying" );
205  }
206 
207  // Classifying
208 
209  const unsigned int classesNumber = (unsigned int)m_classesMeans.size();
210  const unsigned int nRows = (unsigned int)inputRaster.getNumberOfRows();
211  const unsigned int nCols = (unsigned int)inputRaster.getNumberOfColumns();
212  const unsigned int nDims = (unsigned int)m_classesMeans[ 0 ].size();
213  unsigned int col = 0;
214  unsigned int dim = 0;
215  unsigned int classIdx = 0;
216  double angularTR = 0;
217  double angularTT = 0;
218  double angularRR = 0;
219  double angularDist = 0;
220  double readedValue = 0;
221  double minAngularDist = 0;
222  unsigned int minAngularDistClassIdx = 0;
223 
224  for( unsigned int row = 0 ; row < nRows ; ++row )
225  {
226  for( col = 0 ; col < nCols ; ++col )
227  {
228  // Looking the the closest class
229 
230  minAngularDist = DBL_MAX;
231  minAngularDistClassIdx = classesNumber;
232 
233  for( classIdx = 0 ; classIdx < classesNumber ; ++classIdx )
234  {
235  const SampleT& classMeans = m_classesMeans[ classIdx ];
236 
237  angularTR = 0;
238  angularTT = 0;
239  angularRR = 0;
240 
241  for( dim = 0 ; dim < nDims ; ++dim )
242  {
243  const double& meanValue = classMeans[ dim ];
244 
245  inputRaster.getValue( col, row, readedValue, inputRasterBands[ dim ] );
246 
247  angularTR += readedValue * meanValue;
248  angularRR += meanValue * meanValue;
249  angularTT += readedValue * readedValue;
250  }
251 
252  angularDist = angularTR / ( sqrt( angularTT ) *
253  sqrt( angularRR ) );
254 
255  if( std::abs( angularDist ) > 1.0 )
256  {
257  angularDist = DBL_MAX;
258  }
259  else
260  {
261  angularDist = acos( angularDist );
262  }
263 
264  if( ( angularDist < minAngularDist ) && ( angularDist <
265  m_initParams.m_maxAngularDistances[ classIdx ] ) )
266  {
267  minAngularDist = angularDist;
268  minAngularDistClassIdx = classIdx;
269  }
270  }
271 
272  if( minAngularDistClassIdx == classesNumber )
273  outputRaster.setValue( col, row, 0, 0 );
274  else
275  outputRaster.setValue( col, row, m_classesIndex2ID[ minAngularDistClassIdx ],
276  0 );
277  }
278 
279  if( enableProgressInterface )
280  {
281  progressPtr->pulse();
282  if( ! progressPtr->isActive() ) return false;
283  }
284  }
285 
286  return true;
287 }
288 
289 //-----------------------------------------------------------------------------
290 
292  : te::rp::ClassifierStrategyFactory("sam")
293 {
294 }
295 
297 {
298 }
299 
301 {
302  return new te::rp::ClassifierSAMStrategy();
303 }
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
Spectral Angle Mapper strategy factory.
ClassifierSAMStrategy::Parameters m_initParams
Initialization parameters.
te::rp::ClassifierStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
ClassesSamplesTPtr m_trainSamplesPtr
A shared pointer to a always-valid structure where trainning samples are stored.
std::vector< double > SampleT
Class sample type definition.
const Parameters & operator=(const Parameters &params)
#define TERP_TRUE_OR_RETURN_FALSE(value, message)
Checks if value is true. For false values a warning message will be logged and a return of context wi...
Definition: Macros.h:183
Raster classifier strategy factory base class.
AbstractParameters * clone() const
Create a clone copy of this instance.
bool m_isInitialized
Is this instance initialized?
An abstract class for raster data strucutures.
Definition: Raster.h:71
unsigned int ClassIDT
Class ID type definition (zero means invalid ID).
Raster strategy parameters base class.
bool initialize(StrategyParameters const *const strategyParams)
Initialize the classification strategy.
Spectral Angle Mapper classification strategy.
Abstract parameters base interface.
SamplesT m_classesMeans
Classes means.
std::vector< ClassIDT > m_classesIndex2ID
An class index ordered vector of classes IDs;.
Raster classifier strategy base class.
std::vector< SampleT > SamplesT
Class samples container type definition.
Spectral Angle Mapper classification strategy.
#define TERP_DEBUG_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:356
std::vector< double > m_maxAngularDistances
This is a vector of maximum acceptable angles (radians) between one pixel spectra and the reference s...
bool execute(const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, const std::vector< te::gm::Polygon * > &inputPolygons, te::rst::Raster &outputRaster, const unsigned int outputRasterBand, const bool enableProgressInterface)
Executes the classification strategy.