All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PCAFusion.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/PCAFusion.cpp
22  \brief Creation of skeleton imagems.
23 */
24 
25 #include "PCAFusion.h"
26 #include "Macros.h"
27 #include "Functions.h"
28 
29 #include "../raster/BandProperty.h"
30 #include "../raster/RasterFactory.h"
31 #include "../raster/Band.h"
32 #include "../raster/Grid.h"
33 #include "../geometry/Envelope.h"
34 #include "../common/progress/TaskProgress.h"
35 #include "../memory/ExpansibleRaster.h"
36 
37 #include <cmath>
38 #include <limits>
39 
40 namespace te
41 {
42  namespace rp
43  {
44 
46  {
47  reset();
48  }
49 
51  {
52  reset();
53  operator=( other );
54  }
55 
57  {
58  reset();
59  }
60 
61  void PCAFusion::InputParameters::reset() throw( te::rp::Exception )
62  {
63  m_lowResRasterPtr = 0;
64  m_lowResRasterBands.clear();
65  m_highResRasterPtr = 0;
66  m_highResRasterBand = 0;
67  m_enableProgress = false;
68  m_enableThreadedProcessing = true;
70  }
71 
73  const PCAFusion::InputParameters& params )
74  {
75  reset();
76 
77  m_lowResRasterPtr = params.m_lowResRasterPtr;
78  m_lowResRasterBands = params.m_lowResRasterBands;
79  m_highResRasterPtr = params.m_highResRasterPtr;
80  m_highResRasterBand = params.m_highResRasterBand;
81  m_enableProgress = params.m_enableProgress;
82  m_enableThreadedProcessing = params.m_enableThreadedProcessing;
83  m_interpMethod = params.m_interpMethod;
84 
85  return *this;
86  }
87 
89  {
90  return new InputParameters( *this );
91  }
92 
94  {
95  reset();
96  }
97 
99  {
100  reset();
101  operator=( other );
102  }
103 
105  {
106  reset();
107  }
108 
109  void PCAFusion::OutputParameters::reset() throw( te::rp::Exception )
110  {
111  m_rType.clear();
112  m_rInfo.clear();
113  m_outputRasterPtr.reset();
114  }
115 
117  const PCAFusion::OutputParameters& params )
118  {
119  reset();
120 
121  m_rType = params.m_rType;
122  m_rInfo = params.m_rInfo;
123 
124  return *this;
125  }
126 
128  {
129  return new OutputParameters( *this );
130  }
131 
133  {
134  reset();
135  }
136 
138  {
139  }
140 
142  throw( te::rp::Exception )
143  {
144  if( ! m_isInitialized ) return false;
145 
146  PCAFusion::OutputParameters* outParamsPtr = dynamic_cast<
147  PCAFusion::OutputParameters* >( &outputParams );
148  TERP_TRUE_OR_THROW( outParamsPtr, "Invalid paramters" );
149 
150  // progress
151 
152  std::auto_ptr< te::common::TaskProgress > progressPtr;
154  {
155  progressPtr.reset( new te::common::TaskProgress );
156 
157  progressPtr->setTotalSteps( 4 );
158 
159  progressPtr->setMessage( "Fusing images" );
160  }
161 
162  // Loading ressampled data
163 
164  std::auto_ptr< te::rst::Raster > ressampledRasterPtr;
165 
166  TERP_TRUE_OR_RETURN_FALSE( loadRessampledRaster( ressampledRasterPtr ),
167  "Ressampled raster data loading error" );
168 
169 // te::rp::Copy2DiskRaster( *ressampledRasterPtr, "ressampledRaster.tif" );
170 
172  {
173  progressPtr->pulse();
174  if( ! progressPtr->isActive() ) return false;
175  }
176 
177  // Compute PCA space raster
178 
179  std::auto_ptr< te::rst::Raster > pcaRasterPtr;
180  boost::numeric::ublas::matrix< double > pcaMatrix;
181 
182  {
183  te::rst::Grid* gridPtr = new te::rst::Grid( *ressampledRasterPtr->getGrid() );
184  std::vector< te::rst::BandProperty * > bandProperties;
185  std::vector< unsigned int > ressampledRasterBands;
186 
187  for( unsigned int bandIdx = 0 ; bandIdx <
188  ressampledRasterPtr->getNumberOfBands() ; ++bandIdx )
189  {
190  bandProperties.push_back( new te::rst::BandProperty(
191  *ressampledRasterPtr->getBand( bandIdx )->getProperty() ) );
192  bandProperties[ bandIdx ]->m_type = te::dt::DOUBLE_TYPE;
193 
194  ressampledRasterBands.push_back( bandIdx );
195  }
196 
197  try
198  {
199  pcaRasterPtr.reset( new te::mem::ExpansibleRaster( 20, gridPtr,
200  bandProperties ) );
201  }
202  catch( te::common::Exception& e )
203  {
205  }
206 
207  TERP_TRUE_OR_RETURN_FALSE( DirectPrincipalComponents( *ressampledRasterPtr, ressampledRasterBands,
208  pcaMatrix, *pcaRasterPtr, m_inputParameters.m_enableThreadedProcessing ? 0 : 1 ),
209  "Principal components generation error" );
210 
211 // te::rp::Copy2DiskRaster( *pcaRasterPtr, "pcaRaster.tif" );
212  }
213 
215  {
216  progressPtr->pulse();
217  if( ! progressPtr->isActive() ) return false;
218  }
219 
220  // Swapping the first PCA band by the high resolution raster
221 
223  "Band swap error" );
224 
225 // te::rp::Copy2DiskRaster( *pcaRasterPtr, "swappedpcaRaster.tif" );
226 
228  {
229  progressPtr->pulse();
230  if( ! progressPtr->isActive() ) return false;
231  }
232 
233  // Generating the output fused raster
234 
235  {
236  te::rst::Grid* gridPtr = new te::rst::Grid( *pcaRasterPtr->getGrid() );
237  std::vector< te::rst::BandProperty * > bandProperties;
238 
239  for( unsigned int bandIdx = 0 ; bandIdx <
240  pcaRasterPtr->getNumberOfBands() ; ++bandIdx )
241  {
242  bandProperties.push_back( new te::rst::BandProperty(
243  *pcaRasterPtr->getBand( bandIdx )->getProperty() ) );
244  bandProperties[ bandIdx ]->m_type =
245  ressampledRasterPtr->getBand( bandIdx )->getProperty()->m_type;
246  }
247 
248  outParamsPtr->m_outputRasterPtr.reset(
250  outParamsPtr->m_rType,
251  gridPtr,
252  bandProperties,
253  outParamsPtr->m_rInfo,
254  0,
255  0 ) );
256  TERP_TRUE_OR_RETURN_FALSE( outParamsPtr->m_outputRasterPtr.get(),
257  "Output raster creation error" );
258 
260  pcaMatrix, *outParamsPtr->m_outputRasterPtr,
262  "Inverse PCA error" );
263  }
264 
266  {
267  progressPtr->pulse();
268  if( ! progressPtr->isActive() ) return false;
269  }
270 
271  return true;
272  }
273 
274  void PCAFusion::reset() throw( te::rp::Exception )
275  {
277  m_isInitialized = false;
278  }
279 
281  throw( te::rp::Exception )
282  {
283  reset();
284 
285  PCAFusion::InputParameters const* inputParamsPtr = dynamic_cast<
286  PCAFusion::InputParameters const* >( &inputParams );
287  TERP_TRUE_OR_THROW( inputParamsPtr, "Invalid paramters pointer" );
288 
289  m_inputParameters = *inputParamsPtr;
290 
291  // Checking the m_lowResRasterPtr and m_lowResRasterBands
292 
294  "Invalid low Resolution Raster Pointer" )
295 
298  "Invalid raster" );
299 
300  for( unsigned int lowResRasterBandsIdx = 0 ; lowResRasterBandsIdx <
301  inputParamsPtr->m_lowResRasterBands.size() ; ++lowResRasterBandsIdx )
302  {
304  inputParamsPtr->m_lowResRasterBands[ lowResRasterBandsIdx ] <
306  "Invalid raster band" );
307  }
308 
309  // Checking the m_highResRasterPtr and m_highResRasterBand
310 
312  "Invalid high resolution Raster Pointer" )
313 
316  "Invalid raster" );
317 
321  "Invalid raster band" );
322 
323  m_isInitialized = true;
324 
325  return true;
326  }
327 
329  {
330  return m_isInitialized;
331  }
332 
333  bool PCAFusion::loadRessampledRaster( std::auto_ptr< te::rst::Raster >& ressampledRasterPtr ) const
334  {
335  // Creating the ressampled raster
336 
337  const unsigned int outNCols = m_inputParameters.m_highResRasterPtr->getNumberOfColumns();
338  const unsigned int outNRows = m_inputParameters.m_highResRasterPtr->getNumberOfRows();
339  unsigned int lowResRasterBandsIdx = 0;
340  unsigned int lowResRasterBandIdx = 0;
341 
342  te::rst::Grid* ressampledGrid = new te::rst::Grid( outNCols, outNRows,
345 
346  std::vector< te::rst::BandProperty * > ressampledBandProperties;
347 
348  for( lowResRasterBandsIdx = 0 ; lowResRasterBandsIdx <
349  m_inputParameters.m_lowResRasterBands.size() ; ++lowResRasterBandsIdx )
350  {
351  lowResRasterBandIdx = m_inputParameters.m_lowResRasterBands[ lowResRasterBandsIdx ];
352 
353  ressampledBandProperties.push_back( new te::rst::BandProperty(
354  *m_inputParameters.m_lowResRasterPtr->getBand( lowResRasterBandIdx )->getProperty() ) );
355  }
356 
357  try
358  {
359  ressampledRasterPtr.reset( new te::mem::ExpansibleRaster( 20, ressampledGrid,
360  ressampledBandProperties ) );
361  }
362  catch( te::common::Exception& e )
363  {
365  }
366 
367  const double colsRescaleFactor =
369  ((double)outNCols);
370  const double rowsRescaleFactor =
372  ((double)outNRows);
373  unsigned int outRow = 0;
374  unsigned int outCol = 0;
375  double inRow = 0;
376  double inCol = 0;
379  std::complex< double > value = 0;
380  te::rst::Raster& ressampledRaster = *ressampledRasterPtr;
381  double inNoDataValue = 0;
382  double outNoDataValue = 0;
383 
384  for( lowResRasterBandsIdx = 0 ; lowResRasterBandsIdx <
385  m_inputParameters.m_lowResRasterBands.size() ; ++lowResRasterBandsIdx )
386  {
387  lowResRasterBandIdx = m_inputParameters.m_lowResRasterBands[ lowResRasterBandsIdx ];
388  inNoDataValue = m_inputParameters.m_lowResRasterPtr->getBand( lowResRasterBandIdx )->getProperty()->m_noDataValue;
389  outNoDataValue = ressampledRaster.getBand( lowResRasterBandsIdx )->getProperty()->m_noDataValue;
390 
391  for( outRow = 0 ; outRow < outNRows ; ++outRow )
392  {
393  inRow = ((double)outRow) * rowsRescaleFactor;
394 
395  for( outCol = 0 ; outCol < outNCols ; ++outCol )
396  {
397  inCol = ((double)outCol) * colsRescaleFactor;
398 
399  interpol.getValue( inCol, inRow, value, lowResRasterBandIdx );
400 
401  if( value.real() == inNoDataValue )
402  {
403  ressampledRaster.setValue( outCol, outRow, outNoDataValue, lowResRasterBandsIdx );
404  }
405  else
406  {
407  ressampledRaster.setValue( outCol, outRow, value.real(), lowResRasterBandsIdx );
408  }
409  }
410  }
411  }
412 
413  return true;
414  }
415 
416  bool PCAFusion::swapBandByHighResRaster( te::rst::Raster& pcaRaster, const unsigned int pcaRasterBandIdx )
417  {
420 
421  assert( pcaRasterBandIdx < pcaRaster.getNumberOfBands() );
422  te::rst::Band& pcaBand = (*pcaRaster.getBand( pcaRasterBandIdx ));
424 
425  double pcaZeroMean = 0.0;
427  0 : 1, pcaZeroMean ) )
428  {
429  return false;
430  }
431 
432  double pcaZeroStdDev = 0.0;
434  0 : 1, &pcaZeroMean, pcaZeroStdDev ) )
435  {
436  return false;
437  }
438 
439  double hrMean = 0.0;
440  if( ! te::rp::GetMeanValue( hrBand, m_inputParameters.m_enableThreadedProcessing ? 0 : 1, hrMean ) )
441  {
442  return false;
443  }
444 
445  double hrStdDev = 0.0;
446  if( ! te::rp::GetStdDevValue( hrBand, m_inputParameters.m_enableThreadedProcessing ? 0 : 1, &hrMean, hrStdDev ) )
447  {
448  return false;
449  }
450 
451  const double gain = ( ( hrStdDev == 0.0 ) ? 0.0 : ( pcaZeroStdDev / hrStdDev ) );
452  const double offset = ( hrStdDev == 0.0 ) ? 0.0 : ( pcaZeroMean - ( hrMean * gain ) );
453  const double& pcaNoDataValue = pcaBand.getProperty()->m_noDataValue;
454  const double& hrNoDataValue = hrBand.getProperty()->m_noDataValue;
455  const unsigned int nRows = pcaRaster.getNumberOfRows();
456  const unsigned int nCols = pcaRaster.getNumberOfColumns();
457  unsigned int col = 0;
458  unsigned int row = 0;
459  double value = 0;
460  double pcaAllowedMin = 0;
461  double pcaAllowedMax = 0;
462  te::rp::GetDataTypeRange( pcaBand.getProperty()->getType(), pcaAllowedMin,
463  pcaAllowedMax );
464 
465  for( row = 0 ; row < nRows ; ++row )
466  {
467  for( col = 0 ; col < nCols ; ++col )
468  {
469  hrBand.getValue( col, row, value );
470  if( value == hrNoDataValue )
471  {
472  pcaBand.setValue( col, row, pcaNoDataValue );
473  }
474  else
475  {
476  value = ( value * gain ) + offset;
477  value = std::max( pcaAllowedMin, value );
478  value = std::min( pcaAllowedMax, value );
479 
480  pcaBand.setValue( col, row, value );
481  }
482  }
483  }
484 
485  return true;
486  }
487 
488  }
489 } // end namespace te
490 
bool m_enableProgress
Enable/Disable the progress interface (default:false).
Definition: PCAFusion.h:70
bool m_enableThreadedProcessing
If true, threaded processing will be performed (best with multi-core or multi-processor systems (defa...
Definition: PCAFusion.h:72
bool execute(AlgorithmOutputParameters &outputParams)
Executes the algorithm using the supplied parameters.
Definition: PCAFusion.cpp:141
virtual void setValue(unsigned int c, unsigned int r, const double value, std::size_t b=0)
Sets the attribute value in a band of a cell.
Definition: Raster.cpp:233
te::rst::Raster const * m_highResRasterPtr
Input high-resolution raster.
Definition: PCAFusion.h:66
AbstractParameters * clone() const
Create a clone copy of this instance.
Definition: PCAFusion.cpp:88
virtual void getValue(unsigned int c, unsigned int r, double &value) const =0
Returns the cell attribute value.
bool isInitialized() const
Returns true if the algorithm instance is initialized and ready for execution.
Definition: PCAFusion.cpp:328
bool swapBandByHighResRaster(te::rst::Raster &pcaRaster, const unsigned int pcaRasterBandIdx)
Swap the band values by the normalized high resolution raster data.
Definition: PCAFusion.cpp:416
A raster band description.
Definition: BandProperty.h:61
AbstractParameters * clone() const
Create a clone copy of this instance.
Definition: PCAFusion.cpp:127
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
Definition: PCAFusion.cpp:109
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
bool GetMeanValue(const te::rst::Band &band, const unsigned int maxThreads, double &meanValue)
Get the mean of band pixel values.
Definition: Functions.cpp:1106
virtual const char * what() const
It outputs the exception message.
Definition: Exception.cpp:58
bool m_isInitialized
Tells if this instance is initialized.
Definition: PCAFusion.h:142
It interpolates one pixel based on a selected algorithm. Methods currently available are Nearest Neig...
Definition: Interpolator.h:54
std::string m_rType
Output raster data source type (as described in te::raster::RasterFactory ).
Definition: PCAFusion.h:100
void TERPEXPORT GetDataTypeRange(const int dataType, double &min, double &max)
Returns the real data type range (all values that can be represented by the given data type)...
Definition: Functions.h:146
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
Raster Processing algorithm output parameters base interface.
PCAFusion output parameters.
Definition: PCAFusion.h:96
void getValue(const double &c, const double &r, std::complex< double > &v, const std::size_t &b)
Get the interpolated value at specific band.
Definition: Interpolator.h:96
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits::max().
Definition: BandProperty.h:136
te::rst::Raster const * m_lowResRasterPtr
Input low-resolution multi-band raster.
Definition: PCAFusion.h:62
const InputParameters & operator=(const InputParameters &params)
Definition: PCAFusion.cpp:72
te::rst::Interpolator::Method m_interpMethod
The raster interpolator method (default:NearestNeighbor).
Definition: PCAFusion.h:74
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
const Algorithm & operator=(const Algorithm &)
Definition: Algorithm.cpp:43
te::common::AccessPolicy getAccessPolicy() const
Returns the raster access policy.
Definition: Raster.cpp:89
std::auto_ptr< te::rst::Raster > m_outputRasterPtr
The generated output fused raster.
Definition: PCAFusion.h:104
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
An abstract class for raster data strucutures.
Definition: Raster.h:71
unsigned int getNumberOfRows() const
Returns the raster number of rows.
Definition: Raster.cpp:208
bool GetStdDevValue(const te::rst::Band &band, const unsigned int maxThreads, double const *const meanValuePtr, double &stdDevValue)
Get the standard deviation of band pixel values.
Definition: Functions.cpp:1231
void reset()
Clear all internal allocated objects and reset the algorithm to its initial state.
Definition: PCAFusion.cpp:274
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:370
bool initialize(const AlgorithmInputParameters &inputParams)
Initialize the algorithm instance making it ready for execution.
Definition: PCAFusion.cpp:280
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
Definition: PCAFusion.cpp:61
bool DirectPrincipalComponents(const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, boost::numeric::ublas::matrix< double > &pcaMatrix, te::rst::Raster &pcaRaster, const unsigned int maxThreads)
Generate all principal components from the given input raster.
Definition: Functions.cpp:1524
A raster band description.
Definition: Band.h:63
Grid * getGrid()
It returns the raster grid.
Definition: Raster.cpp:94
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
Abstract parameters base interface.
std::vector< unsigned int > m_lowResRasterBands
The low-resolution raster band indexes.
Definition: PCAFusion.h:64
int getSRID() const
Returns the raster spatial reference system identifier.
Definition: Raster.cpp:203
#define TERP_LOG_AND_RETURN_FALSE(message)
Logs a warning message will and return false.
Definition: Macros.h:236
std::map< std::string, std::string > m_rInfo
The necessary information to create the output rasters (as described in te::raster::RasterFactory).
Definition: PCAFusion.h:102
InputParameters m_inputParameters
Input execution parameters.
Definition: PCAFusion.h:140
bool loadRessampledRaster(std::auto_ptr< te::rst::Raster > &ressampledRasterPtr) const
Load resampled data from the input image.
Definition: PCAFusion.cpp:333
A raster (stored in memory and eventually swapped to disk) where it is possible to dynamically add li...
PCAFusion input parameters.
Definition: PCAFusion.h:58
static Raster * make()
It creates and returns an empty raster with default raster driver.
te::gm::Envelope * getExtent()
Returns the geographic extension of the grid.
Definition: Grid.cpp:275
bool InversePrincipalComponents(const te::rst::Raster &pcaRaster, const boost::numeric::ublas::matrix< double > &pcaMatrix, te::rst::Raster &outputRaster, const unsigned int maxThreads)
Regenerate the original raster from its principal components.
Definition: Functions.cpp:1612
Raster Processing algorithm input parameters base interface.
Near neighborhood interpolation method.
Definition: Interpolator.h:63
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
Creation of skeleton imagems.
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:149
unsigned int m_highResRasterBand
Band to process from the high-resolution raster.
Definition: PCAFusion.h:68
const OutputParameters & operator=(const OutputParameters &params)
Definition: PCAFusion.cpp:116