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 #include "../raster/Band.h"
32 
33 #include <cfloat>
34 #include <cmath>
35 
36 namespace
37 {
38  static te::rp::ClassifierSAMStrategyFactory classifierMAPStrategyFactoryInstance;
39 }
40 
41 //-----------------------------------------------------------------------------
42 
44 {
45  reset();
46 }
47 
49 
51 {
52  reset();
53 
56 
57  return *this;
58 }
59 
61 {
62  m_trainSamplesPtr.reset();
63  m_maxAngularDistances.clear();
64 }
65 
67 {
69 }
70 
71 //-----------------------------------------------------------------------------
72 
74 {
75  m_isInitialized = false;
77 }
78 
80 
82  te::rp::ClassifierStrategyParameters const* const strategyParams) throw(te::rp::Exception)
83 {
84  m_isInitialized = false;
86  m_classesMeans.clear();
87  m_classesIndex2ID.clear();
88 
89  ClassifierSAMStrategy::Parameters const * const castParamsPtr =
90  dynamic_cast< ClassifierSAMStrategy::Parameters const * >( strategyParams );
91  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( castParamsPtr, "Invalid parameters" );
92 
93  // Checking the angluar distances
94 
96  castParamsPtr->m_trainSamplesPtr->size(),
97  "Mismatch between the classes number and the max angular distances" );
98 
99  for( unsigned int maxAngularDistancesIdx = 0 ; maxAngularDistancesIdx <
100  castParamsPtr->m_maxAngularDistances.size() ; ++ maxAngularDistancesIdx )
101  {
103  maxAngularDistancesIdx ] >= 0.0 ),
104  "Invalid max angular distance" );
105  }
106 
107  // Calculating m_classesMeans and m_classesIndex2ID
108 
110  "Invalid classes samples pointer" )
111  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( castParamsPtr->m_trainSamplesPtr->size() > 0,
112  "Invalid classes samples number" )
113  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( castParamsPtr->m_trainSamplesPtr->begin()->second.size() > 0,
114  "Invalid classe samples number" )
115  const unsigned int dimsNumber = (unsigned int)
116  castParamsPtr->m_trainSamplesPtr->begin()->second.operator[]( 0 ).size();
117  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( dimsNumber > 0,
118  "Invalid dimensions number" )
119 
120  {
121  ClassesSamplesT::const_iterator classesIt =
122  castParamsPtr->m_trainSamplesPtr->begin();
123  const ClassesSamplesT::const_iterator classesItE =
124  castParamsPtr->m_trainSamplesPtr->end();
125  unsigned int dimIdx = 0;
126  SamplesT::const_iterator samplesIt;
127  SamplesT::const_iterator samplesItE;
128 
130 
131  while( classesIt != classesItE )
132  {
133  const ClassIDT& classID = classesIt->first;
134  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( classID > 0, "Invalid class ID" );
135 
136  const SamplesT& classSamples = classesIt->second;
137  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( classSamples.size() > 0,
138  "Invalid class samples number" );
139 
140  m_highestTrainClassID = std::max( m_highestTrainClassID, classID );
141 
142  SampleT classMeans( dimsNumber );
143 
144  for( dimIdx = 0 ; dimIdx < dimsNumber ; ++dimIdx )
145  {
146  double& dimMean = classMeans[ dimIdx ];
147  dimMean = 0.0;
148 
149  samplesIt = classSamples.begin();
150  samplesItE = classSamples.end();
151 
152  while( samplesIt != samplesItE )
153  {
154  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( samplesIt->size() == dimsNumber,
155  "Sample size mismatch" )
156  dimMean += samplesIt->operator[]( dimIdx );
157 
158  ++samplesIt;
159  }
160 
161  dimMean /= (double)( classSamples.size() );
162  }
163 
164  m_classesMeans.push_back( classMeans );
165  m_classesIndex2ID.push_back( classID );
166 
167  ++classesIt;
168  }
169 
170  }
171 
172  // Finalizing
173 
174  m_initParams = (*castParamsPtr);
175 
176  m_isInitialized = true;
177 
178  return true;
179 }
180 
182 {
184  "Classification strategy not initialized" );
185  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( m_inputRasterBands.size() > 0, "Invalid input bands" );
187  "Invalid input bands" );
188 
189  // Globals
190 
191  const unsigned int classesNumber = (unsigned int)m_classesMeans.size();
192  const unsigned int nRows = (unsigned int)m_inputRasterPtr->getNumberOfRows();
193  const unsigned int nCols = (unsigned int)m_inputRasterPtr->getNumberOfColumns();
194  const unsigned int nDims = (unsigned int)m_classesMeans[ 0 ].size();
195 
196  // Creating the output raster
197 
198  {
199  std::vector< int > dt;
200  dt.push_back( te::dt::UINT32_TYPE );
201 
202  std::vector< double > noDataValues;
203  noDataValues.push_back( (double)( m_highestTrainClassID + 2 ) );
204 
206  "Output raster creation error" );
207 
209  "Output raster palette creation error" );
210  }
211 
212  // progress
213 
214  std::unique_ptr< te::common::TaskProgress > progressPtr;
216  {
217  progressPtr.reset( new te::common::TaskProgress );
218  progressPtr->setTotalSteps( m_inputRasterPtr->getNumberOfRows() );
219  progressPtr->setMessage( "Classifying" );
220  }
221 
222  // Classifying
223 
224  unsigned int col = 0;
225  unsigned int dim = 0;
226  unsigned int classIdx = 0;
227  double angularTR = 0;
228  double angularTT = 0;
229  double angularRR = 0;
230  double angularDist = 0;
231  double minAngularDist = 0;
232  unsigned int minAngularDistClassIdx = 0;
233  const double outNoDataValue = m_outputRasterPtr->getBand( 0 )->getProperty()->m_noDataValue;
234  const double inNoDataValue = m_inputRasterPtr->getBand( m_inputRasterBands[ 0 ] )->getProperty()->m_noDataValue;
235  std::vector< double > currentPixelValues( nDims );
236 
237  for( unsigned int row = 0 ; row < nRows ; ++row )
238  {
239  for( col = 0 ; col < nCols ; ++col )
240  {
241  // Is this a valid pixel ?
242 
243  for( dim = 0 ; dim < nDims ; ++dim )
244  {
245  m_inputRasterPtr->getValue( col, row, currentPixelValues[ dim ],
246  m_inputRasterBands[ dim ] );
247  }
248 
249  if( currentPixelValues[ 0 ] == inNoDataValue )
250  {
251  m_outputRasterPtr->setValue( col, row, outNoDataValue, 0 );
252  }
253  else
254  {
255  // Looking the the closest class
256 
257  minAngularDist = DBL_MAX;
258  minAngularDistClassIdx = classesNumber;
259 
260  for( classIdx = 0 ; classIdx < classesNumber ; ++classIdx )
261  {
262  const SampleT& classMeans = m_classesMeans[ classIdx ];
263 
264  angularTR = 0;
265  angularTT = 0;
266  angularRR = 0;
267 
268  for( dim = 0 ; dim < nDims ; ++dim )
269  {
270  const double& meanValue = classMeans[ dim ];
271 
272  const double& readedValue = currentPixelValues[ dim ];;
273 
274  angularTR += readedValue * meanValue;
275  angularRR += meanValue * meanValue;
276  angularTT += readedValue * readedValue;
277  }
278 
279  angularDist = angularTR / ( sqrt( angularTT ) *
280  sqrt( angularRR ) );
281 
282  if( std::abs( angularDist ) > 1.0 )
283  {
284  angularDist = DBL_MAX;
285  }
286  else
287  {
288  angularDist = acos( angularDist );
289  }
290 
291  if( ( angularDist < minAngularDist ) && ( angularDist <
292  m_initParams.m_maxAngularDistances[ classIdx ] ) )
293  {
294  minAngularDist = angularDist;
295  minAngularDistClassIdx = classIdx;
296  }
297  }
298 
299  if( minAngularDistClassIdx == classesNumber )
300  m_outputRasterPtr->setValue( col, row, 0, 0 );
301  else
302  m_outputRasterPtr->setValue( col, row, m_classesIndex2ID[ minAngularDistClassIdx ],
303  0 );
304  }
305  }
306 
308  {
309  progressPtr->pulse();
310  if( ! progressPtr->isActive() ) return false;
311  }
312  }
313 
314  return true;
315 }
316 
317 //-----------------------------------------------------------------------------
318 
320  : te::rp::ClassifierStrategyFactory("sam")
321 {
322 }
323 
325 
327 {
328  return new te::rp::ClassifierSAMStrategy();
329 }
bool execute()
Executes the classification strategy.
Base exception class for plugin module.
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
bool createOutputRaster(const std::vector< int > &bandsDataTypes, const std::vector< double > &noDataValues)
Create the output raster using the EXPANSIBLE driver.
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...
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits<double>::max().
Definition: BandProperty.h:136
ClassesSamplesTPtr m_trainSamplesPtr
A shared pointer to a always-valid structure where trainning samples are stored.
std::vector< double > SampleT
Class sample type definition.
std::vector< unsigned int > m_inputRasterBands
Input raster bands.
const Parameters & operator=(const Parameters &params)
Raster classifier strategy factory base class.
AbstractParameters * clone() const
Create a clone copy of this instance.
unsigned int unsigned int nCols
bool m_isInitialized
Is this instance initialized?
unsigned int getNumberOfRows() const
Returns the raster number of rows.
unsigned int ClassIDT
Class ID type definition (zero means invalid ID).
BandProperty * getProperty()
Returns the band property.
URI C++ Library.
Definition: Attributes.h:37
static te::dt::TimeDuration dt(20, 30, 50, 11)
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
Spectral Angle Mapper classification strategy.
virtual void getValue(unsigned int c, unsigned int r, double &value, std::size_t b=0) const
Returns the attribute value of a band of a cell.
std::unique_ptr< te::rst::Raster > m_outputRasterPtr
A pointer to the output raster.
bool initialize(ClassifierStrategyParameters const *const strategyParams)
Initialize the classification strategy.
Abstract parameters base interface.
SamplesT m_classesMeans
Classes means.
bool m_progressInterfaceEnabled
Progress interface status.
te::rst::Raster const * m_inputRasterPtr
A pointer to the input raster.
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_INSTANCE_TRUE_OR_RETURN_FALSE(value, message)
Checks if value is true. For false values a warning message will be logged, the current instance erro...
Definition: Macros.h:200
bool setOutputRasterPalette(const unsigned int size)
Create and set the output raster palette folowing the current internal settings.
std::vector< double > m_maxAngularDistances
This is a vector of maximum acceptable angles (radians) between one pixel spectra and the reference s...
unsigned int col