All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
MixtureModelLinearStrategy.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/MixtureModelLinearStrategy.cpp
22 
23  \brief Raster linear strategy for mixture model classification.
24 */
25 
26 // TerraLib
27 #include "../common/MatrixUtils.h"
28 #include "../common/progress/TaskProgress.h"
29 #include "../raster/Grid.h"
30 #include "../raster/Utils.h"
31 #include "Functions.h"
32 #include "Macros.h"
34 #include "Functions.h"
35 
36 // Boost
37 #include <boost/numeric/ublas/io.hpp>
38 #include <boost/numeric/ublas/matrix.hpp>
39 
40 namespace
41 {
42  static te::rp::MixtureModelLinearStrategyFactory mixtureModelLinearStrategyFactoryInstance;
43 }
44 
46 {
47  reset();
48 }
49 
51 {
52 }
53 
55 {
56  reset();
57 
58  return *this;
59 }
60 
62 {
63 }
64 
66 {
68 }
69 
71 {
72  m_isInitialized = false;
73 }
74 
76 {
77 }
78 
79 bool te::rp::MixtureModelLinearStrategy::initialize(te::rp::StrategyParameters const* const strategyParams) throw(te::rp::Exception)
80 {
81  m_isInitialized = false;
82 
83  te::rp::MixtureModelLinearStrategy::Parameters const* paramsPtr = dynamic_cast<te::rp::MixtureModelLinearStrategy::Parameters const*>(strategyParams);
84 
85  if(!paramsPtr)
86  return false;
87 
88  m_parameters = *(paramsPtr);
89 
90  m_isInitialized = true;
91 
92  return true;
93 }
94 
95 bool te::rp::MixtureModelLinearStrategy::execute(const te::rst::Raster& inputRaster, const std::vector<unsigned int>& inputRasterBands,
96  const std::vector<std::string>& inputSensorBands, const std::map<std::string, std::vector<double> >& components,
97  te::rst::Raster& outputRaster, const bool enableProgressInterface) throw(te::rp::Exception)
98 {
99  TERP_TRUE_OR_RETURN_FALSE(m_isInitialized, "Instance not initialized")
100 
101  const unsigned int nComponents = components.size();
102  const unsigned int nBands = inputRasterBands.size();
103 
104  boost::numeric::ublas::matrix<double> transposeA = boost::numeric::ublas::matrix<double>(nComponents + 1, nBands + 1);
105  boost::numeric::ublas::matrix<double> matrixA (transposeA.size2(), transposeA.size1());
106 
107 // by definition, A * X = R, we have A, so that X = inv(A' * A) * A' * R
108 // A is the set of known reflectances for each component
109 // R is the reflectances of a specific pixel
110 // X is the proportion of each component
111 
112  std::vector<double> Qmax;
113  for (unsigned i = 0; i < inputSensorBands.size(); i++)
114  Qmax.push_back(GetDigitalNumberBandMax(inputSensorBands[i]));
115 
116 // retrieve the transposed A matrix, normalizing values using band/sensor info
117  unsigned row = 0;
118  for (unsigned j = 0; j < nBands; j++)
119  transposeA(row, j) = 1.0;
120  transposeA(row, nBands) = 0.0;
121  std::map<std::string, std::vector<double> >::const_iterator it;
122  for (row = 1, it = components.begin(); it != components.end(); row++, it++)
123  {
124  for (unsigned j = 0; j < nBands; j++)
125  transposeA(row, j) = it->second[j] / Qmax[j];
126  transposeA(row, nBands) = 1.0;
127  }
128 
129 // calculate the matrixA from the transpose of A
130  matrixA = boost::numeric::ublas::trans(transposeA);
131 
132 // calculate the product A' * A
133  boost::numeric::ublas::matrix<double> productAtA = boost::numeric::ublas::matrix<double>(transposeA.size1(), matrixA.size2());
134  productAtA = boost::numeric::ublas::prod(transposeA, matrixA);
135 
136 // calculate the inverse of A' * A
137  boost::numeric::ublas::matrix<double> invertAtA = boost::numeric::ublas::matrix<double>(productAtA.size1(), productAtA.size2());
138  te::common::GetInverseMatrix(productAtA, invertAtA);
139 
140  boost::numeric::ublas::matrix<double> matrixR = boost::numeric::ublas::matrix<double>(matrixA.size1(), 1);
141  boost::numeric::ublas::matrix<double> productAtR = boost::numeric::ublas::matrix<double>(transposeA.size1(), matrixR.size2());
142  boost::numeric::ublas::matrix<double> matrixX = boost::numeric::ublas::matrix<double>(invertAtA.size1(), productAtR.size2());
143  boost::numeric::ublas::matrix<double> productAX = boost::numeric::ublas::matrix<double>(matrixA.size1(), matrixX.size2());
144  boost::numeric::ublas::matrix<double> matrixE = boost::numeric::ublas::matrix<double>(matrixR.size1(), matrixR.size2());
145 
146  te::common::TaskProgress task(TE_TR("Linear Mixture Model"), te::common::TaskProgress::UNDEFINED, inputRaster.getNumberOfRows());
147  double value;
148  for (unsigned r = 0; r < inputRaster.getNumberOfRows(); r++)
149  {
150  for (unsigned c = 0; c < inputRaster.getNumberOfColumns(); c++)
151  {
152 // read input values
153  for (unsigned b = 0; b < nBands; b++)
154  {
155  inputRaster.getValue(c, r, value, inputRasterBands[b]);
156  matrixR(b, 0) = value / Qmax[b];
157  }
158  matrixR(nBands, 0) = 0.0;
159 // calculate the product A' * R
160  productAtR = boost::numeric::ublas::prod(transposeA, matrixR);
161 // compute matrix X
162  matrixX = boost::numeric::ublas::prod(invertAtA, productAtR);
163 // write output fractions
164  for (unsigned b = 0; b < nComponents; b++)
165  outputRaster.setValue(c, r, matrixX(b + 1, 0), b);
166 
167 // compute error matrix
168  if (nComponents < outputRaster.getNumberOfBands())
169  {
170  productAX = boost::numeric::ublas::prod(matrixA, matrixX);
171  matrixE = matrixR - productAX;
172 
173 // write output errors
174  for (unsigned b = nComponents, e = 0; b < outputRaster.getNumberOfBands(); b++, e++)
175  outputRaster.setValue(c, r, matrixE(e, 0), b);
176  }
177  }
178  task.pulse();
179  }
180 
181  return true;
182 }
183 
185  : te::rp::MixtureModelStrategyFactory("linear")
186 {
187 }
188 
190 {
191 }
192 
194 {
196 }
double GetDigitalNumberBandMax(std::string bandName)
Returns the maximum digital number of a given sensor/band.
Definition: Functions.cpp:696
Raster Mixture model strategy factory base class.
te::rp::MixtureModelStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
Raster linear mixture model strategy factory.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
bool execute(const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, const std::vector< std::string > &inputSensorBands, const std::map< std::string, std::vector< double > > &components, te::rst::Raster &outputRaster, const bool enableProgressInterface)
Executes the segmentation strategy.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
Raster Processing functions.
#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 mixture model strategy base class.
An abstract class for raster data strucutures.
Definition: Raster.h:71
Raster strategy parameters base class.
Raster linear strategy for mixture model classification.
AbstractParameters * clone() const
Create a clone copy of this instance.
Abstract parameters base interface.
bool initialize(StrategyParameters const *const strategyParams)
Initialize the segmentation strategy.
MixtureModelLinearStrategy::Parameters m_parameters
Internal execution parameters.
bool GetInverseMatrix(const boost::numeric::ublas::matrix< T > &inputMatrix, boost::numeric::ublas::matrix< T > &outputMatrix)
Matrix inversion.
Definition: MatrixUtils.h:104
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
const Parameters & operator=(const Parameters &params)
bool m_isInitialized
True if this instance is initialized.