ClassifierEDStrategy.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/ClassifierEDStrategy.cpp
22 
23  \brief Euclidean Distance Classifier strategy.
24 */
25 
26 // TerraLib
27 
28 #include "ClassifierEDStrategy.h"
29 #include "Macros.h"
30 #include "../raster/Band.h"
31 #include "../raster/BandProperty.h"
32 #include "../common/MatrixUtils.h"
33 
34 // STL
35 #include <memory>
36 
37 #include <cfloat>
38 
39 namespace
40 {
41  static te::rp::ClassifierEDStrategyFactory classifierEDStrategyFactoryInstance;
42 }
43 
44 //-----------------------------------------------------------------------------
45 
47 {
48  reset();
49 }
50 
52 
54 {
55  reset();
56 
58 
59  return *this;
60 }
61 
63 {
64  m_trainSamplesPtr.reset();
65 }
66 
68 {
69  return new te::rp::ClassifierEDStrategy::Parameters( *this );
70 }
71 
72 //-----------------------------------------------------------------------------
73 
75 {
76  m_isInitialized = false;
78 }
79 
81 
83  te::rp::ClassifierStrategyParameters const* const strategyParams) _NOEXCEPT_OP(false)
84 {
85  m_isInitialized = false;
87  m_classesIndex2ID.clear();
88  m_classesMeans.clear();
89 
90  ClassifierEDStrategy::Parameters const* const castParamsPtr =
91  dynamic_cast< ClassifierEDStrategy::Parameters const * >( strategyParams );
92  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( castParamsPtr, "Invalid parameters" );
93 
94  // Checking the input parameters
95 
97  "Invalid classes samples pointer" )
98  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( castParamsPtr->m_trainSamplesPtr->size() > 0,
99  "Invalid classes samples number" )
100  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( castParamsPtr->m_trainSamplesPtr->begin()->second.size() > 0,
101  "Invalid classes samples number" )
102 
103  m_initParams = (*castParamsPtr);
104 
105  // Calculating m_classesMeans and m_classesIndex2ID
106 
107  // Dimension number (bands number)
108  const unsigned int dimsNumber = static_cast<unsigned int>(castParamsPtr->m_trainSamplesPtr->begin()->second.operator[]( 0 ).size());
109 
110  {
111  Parameters::MClassesSamplesCT::const_iterator classesIt =
113  const Parameters::MClassesSamplesCT::const_iterator classesItE =
115 
117 
118  // Iterate class
119  while( classesIt != classesItE )
120  {
121  const Parameters::ClassIDT& classID = classesIt->first;
122 
123  const Parameters::ClassSamplesContainerT& classSamples = classesIt->second;
124  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( classSamples.size() > 0,
125  "Invalid class samples number" );
126 
127  Parameters::ClassSampleT classMeans( dimsNumber, 0.0 );
128 
129  unsigned int dimIdx = 0;
130 
131  m_highestTrainClassID = std::max( m_highestTrainClassID, classID );
132 
133  // Iterate bands
134  for( dimIdx = 0 ; dimIdx < dimsNumber ; ++dimIdx )
135  {
136  double& dimMean = classMeans[ dimIdx ];
137  dimMean = 0.0;
138 
139  Parameters::ClassSamplesContainerT::const_iterator samplesIt =
140  classSamples.begin();
141  const Parameters::ClassSamplesContainerT::const_iterator samplesItE =
142  classSamples.end();
143 
144  // Iterate samples
145  while( samplesIt != samplesItE )
146  {
147  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( samplesIt->size() == dimsNumber,
148  "Sample size mismatch" )
149  dimMean += samplesIt->operator[]( dimIdx );
150 
151  ++samplesIt;
152  }
153 
154  // sum / simple size
155  dimMean /= static_cast<double>( classSamples.size() );
156  }
157 
158  // Adding to container
159  m_classesMeans.push_back( classMeans );
160  m_classesIndex2ID.push_back( classID );
161 
162  ++classesIt;
163  }
164 
165  }
166 
167  // Finalizing
168 
169  m_isInitialized = true;
170 
171  return true;
172 }
173 
175 {
177  "Classification strategy not initialized" );
178  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( m_inputRasterBands.size() > 0, "Invalid input bands" );
180  "Invalid input bands" );
181 
182  // Creating the output raster
183 
184  std::vector< int > dt;
185  dt.push_back( te::dt::UINT32_TYPE );
186 
187  std::vector< double > noDataValues;
188  noDataValues.push_back( static_cast<double>( m_highestTrainClassID + 2 ) );
189 
191  "Output raster creation error" );
192 
194  "Output raster palette creation error" );
195 
196  // progress
197 
198  std::unique_ptr< te::common::TaskProgress > progressPtr;
200  {
201  progressPtr.reset( new te::common::TaskProgress );
202  progressPtr->setTotalSteps( static_cast<int>(m_inputRasterPtr->getNumberOfRows()) );
203  progressPtr->setMessage( "Classifying" );
204  }
205 
206  // Classifying
207 
208  const unsigned int classesNumber = static_cast<unsigned int>(m_classesMeans.size());
209  const unsigned int nRows = static_cast<unsigned int>(m_inputRasterPtr->getNumberOfRows());
210  const unsigned int nCols = static_cast<unsigned int>(m_inputRasterPtr->getNumberOfColumns());
211  const unsigned int nDims = static_cast<unsigned int>(m_inputRasterBands.size());
212  const double outNoDataValue = m_outputRasterPtr->getBand( 0 )->getProperty()->m_noDataValue;
213  const double inNoDataValue = m_inputRasterPtr->getBand( m_inputRasterBands[ 0 ] )->getProperty()->m_noDataValue;
214  unsigned int col = 0;
215  unsigned int dim = 0;
216  boost::numeric::ublas::matrix< double > sample( nDims, 1 );
217  unsigned int classIdx = 0;
218  double dist = 0;
219  double bestDist = 0;
220  unsigned int bestClass = 0;
221 
222 
223  for( unsigned int row = 0 ; row < nRows ; ++row )
224  {
225  for( col = 0 ; col < nCols ; ++col )
226  {
227  // Creating the sample
228 
229  for( dim = 0 ; dim < nDims ; ++dim )
230  {
231  m_inputRasterPtr->getValue( col, row, sample( dim, 0 ), m_inputRasterBands[ dim ] );
232  }
233 
234  if( sample( 0, 0 ) == inNoDataValue )
235  {
236  m_outputRasterPtr->setValue(col, row, outNoDataValue);
237  }
238  else
239  {
240  unsigned int refClass = bestClass;
241  bestDist = 0;
242 
243  for( unsigned int band = 0 ; band < nDims ; ++band )
244  // bestDist += (sample(band, 0) - m_classesMeans[refClass][band]) * (sample(band, 0) - m_classesMeans[refClass][band]) * 1/2;
245  bestDist += (sample(band, 0) - m_classesMeans[refClass][band]) * (sample(band, 0) - m_classesMeans[refClass][band]);
246 
247  for( classIdx = 0 ; classIdx < classesNumber ; ++classIdx )
248  {
249  const Parameters::ClassSampleT& classMeans = m_classesMeans[ classIdx ];
250 
251 
252  if( classIdx == refClass )
253  continue;
254 
255  dist = 0;
256 
257 
258  for( dim = 0 ; dim < nDims ; ++dim )
259  {
260  // dist += (sample(dim, 0) - classMeans[classIdx]) * (sample(dim, 0) - classMeans[classIdx]) * 1/2;
261  dist += (sample(dim, 0) - classMeans[classIdx]) * (sample(dim, 0) - classMeans[classIdx]);
262 
263  if(dist <= bestDist)
264  break;
265  }
266 
267 
268  // considerar a condição invertida, inverter atribuições internas
269  if( dist < bestDist )
270  {
271  bestDist = dist;
272  bestClass = classIdx;
273  }
274  }
275 
276  // double vClass = bestclass + 1;
277  m_outputRasterPtr->setValue( col, row, m_classesIndex2ID[ bestClass ] );
278  }
279  }
280 
282  {
283  progressPtr->pulse();
284  if( ! progressPtr->isActive() ) return false;
285  }
286  }
287 
288  return true;
289 }
290 
292  return 0;
293 }
294 //-----------------------------------------------------------------------------
295 
297  : te::rp::ClassifierStrategyFactory("ed")
298 {
299 }
300 
302 
304 {
305  return new te::rp::ClassifierEDStrategy();
306 }
unsigned int band
ClassifierEDStrategy::Parameters m_initParams
Initialization parameters.
te::rp::ClassifierStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
std::vector< std::vector< double > > m_classesMeans
Classes means;.
bool m_isInitialized
Is this instance initialized?
bool createOutputRaster(const std::vector< int > &bandsDataTypes, const std::vector< double > &noDataValues)
Create the output raster using the EXPANSIBLE driver.
AbstractParameters * clone() const
Create a clone copy of this instance.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
const Parameters & operator=(const Parameters &params)
#define _NOEXCEPT_OP(x)
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits<double>::max().
Definition: BandProperty.h:136
std::vector< unsigned int > m_inputRasterBands
Input raster bands.
MClassesSamplesCTPtr m_trainSamplesPtr
A shared pointer to a always-valid structure where trainning samples are stored.
Raster classifier strategy factory base class.
std::vector< Parameters::ClassIDT > m_classesIndex2ID
An class index ordered vector of classes IDs;.
unsigned int unsigned int nCols
bool execute() _NOEXCEPT_OP(false)
Executes the classification strategy.
Euclidean Distance Classifier strategy.
unsigned int getNumberOfRows() const
Returns the raster number of rows.
BandProperty * getProperty()
Returns the band property.
URI C++ Library.
Definition: Attributes.h:37
static te::dt::TimeDuration dt(20, 30, 50, 11)
Parameters::ClassIDT m_highestTrainClassID
The highest train class ID.
void reset() _NOEXCEPT_OP(false)
Clear all internal allocated resources and reset the parameters instance to its initial state...
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
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.
Abstract parameters base interface.
bool m_progressInterfaceEnabled
Progress interface status.
bool initialize(ClassifierStrategyParameters const *const strategyParams) _NOEXCEPT_OP(false)
Initialize the classification strategy.
te::rst::Raster const * m_inputRasterPtr
A pointer to the input raster.
Raster classifier strategy base class.
Euclidean Distance Classifier 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< ClassSampleT > ClassSamplesContainerT
Class samples container type definition.
unsigned int col
std::vector< double > ClassSampleT
Class sample type definition.
Euclidean Distance strategy factory.
unsigned int ClassIDT
Class ID type definition (zero means invalid ID).