All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MixtureModelLinearStrategy.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 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(TR_RP("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 }
AbstractParameters * clone() const
Create a clone copy of this instance.
bool initialize(StrategyParameters const *const strategyParams)
Initialize the segmentation strategy.
MixtureModelLinearStrategy::Parameters m_parameters
Internal execution parameters.
Raster strategy parameters base class.
Raster Processing functions.
te::rp::MixtureModelStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
Raster mixture model strategy base class.
double GetDigitalNumberBandMax(std::string bandName)
Returns the maximum digital number of a given sensor/band.
Definition: Functions.cpp:651
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
#define TR_RP(message)
It marks a string in order to get translated. This is a special mark used in the Raster Processing mo...
Definition: Config.h:58
#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
Abstract parameters base interface.
Raster linear strategy for mixture model classification.
Raster linear mixture model strategy factory.
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.
bool getInverseMatrix(const boost::numeric::ublas::matrix< T > &inputMatrix, boost::numeric::ublas::matrix< T > &outputMatrix)
Matrix inversion.
Definition: MatrixUtils.h:104
bool m_isInitialized
True if this instance is initialized.
An abstract class for raster data strucutures.
Definition: Raster.h:70
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
Raster Mixture model strategy factory base class.
const Parameters & operator=(const Parameters &params)