PCAFusion.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/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;
69  m_interpMethod = te::rst::NearestNeighbor;
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 
208  ressampledRasterBands, pcaMatrix, *pcaRasterPtr, ressampledRasterBands,
210  "Principal components generation error" );
211 
212 // te::rp::Copy2DiskRaster( *pcaRasterPtr, "pcaRaster.tif" );
213  }
214 
216  {
217  progressPtr->pulse();
218  if( ! progressPtr->isActive() ) return false;
219  }
220 
221  // Swapping the first PCA band by the high resolution raster
222 
224  "Band swap error" );
225 
226 // te::rp::Copy2DiskRaster( *pcaRasterPtr, "swappedpcaRaster.tif" );
227 
229  {
230  progressPtr->pulse();
231  if( ! progressPtr->isActive() ) return false;
232  }
233 
234  // Generating the output fused raster
235 
236  {
238 
239  std::vector< te::rst::BandProperty * > bandProperties;
240  std::vector< unsigned int > outputRasterBands;
241 
242  for( unsigned int bandIdx = 0 ; bandIdx <
243  pcaRasterPtr->getNumberOfBands() ; ++bandIdx )
244  {
245  bandProperties.push_back( new te::rst::BandProperty(
246  *pcaRasterPtr->getBand( bandIdx )->getProperty() ) );
247  bandProperties[ bandIdx ]->m_type =
248  ressampledRasterPtr->getBand( bandIdx )->getProperty()->m_type;
249 
250  outputRasterBands.push_back( bandIdx );
251  }
252 
253  outParamsPtr->m_outputRasterPtr.reset(
255  outParamsPtr->m_rType,
256  gridPtr,
257  bandProperties,
258  outParamsPtr->m_rInfo,
259  0,
260  0 ) );
261  TERP_TRUE_OR_RETURN_FALSE( outParamsPtr->m_outputRasterPtr.get(),
262  "Output raster creation error" );
263 
265  pcaMatrix, *outParamsPtr->m_outputRasterPtr, outputRasterBands,
267  "Inverse PCA error" );
268  }
269 
271  {
272  progressPtr->pulse();
273  if( ! progressPtr->isActive() ) return false;
274  }
275 
276  return true;
277  }
278 
279  void PCAFusion::reset() throw( te::rp::Exception )
280  {
282  m_isInitialized = false;
283  }
284 
286  throw( te::rp::Exception )
287  {
288  reset();
289 
290  PCAFusion::InputParameters const* inputParamsPtr = dynamic_cast<
291  PCAFusion::InputParameters const* >( &inputParams );
292  TERP_TRUE_OR_THROW( inputParamsPtr, "Invalid paramters pointer" );
293 
294  m_inputParameters = *inputParamsPtr;
295 
296  // Checking the m_lowResRasterPtr and m_lowResRasterBands
297 
299  "Invalid low Resolution Raster Pointer" )
300 
303  "Invalid raster" );
304 
305  for( unsigned int lowResRasterBandsIdx = 0 ; lowResRasterBandsIdx <
306  inputParamsPtr->m_lowResRasterBands.size() ; ++lowResRasterBandsIdx )
307  {
309  inputParamsPtr->m_lowResRasterBands[ lowResRasterBandsIdx ] <
311  "Invalid raster band" );
312  }
313 
314  // Checking the m_highResRasterPtr and m_highResRasterBand
315 
317  "Invalid high resolution Raster Pointer" )
318 
321  "Invalid raster" );
322 
326  "Invalid raster band" );
327 
328  m_isInitialized = true;
329 
330  return true;
331  }
332 
334  {
335  return m_isInitialized;
336  }
337 
338  bool PCAFusion::loadRessampledRaster( std::auto_ptr< te::rst::Raster >& ressampledRasterPtr ) const
339  {
340  // Creating the ressampled raster
341 
342  const unsigned int outNCols = m_inputParameters.m_highResRasterPtr->getNumberOfColumns();
343  const unsigned int outNRows = m_inputParameters.m_highResRasterPtr->getNumberOfRows();
344  unsigned int lowResRasterBandsIdx = 0;
345  unsigned int lowResRasterBandIdx = 0;
346 
347  te::rst::Grid* ressampledGrid = new te::rst::Grid( outNCols, outNRows,
350 
351  std::vector< te::rst::BandProperty * > ressampledBandProperties;
352 
353  for( lowResRasterBandsIdx = 0 ; lowResRasterBandsIdx <
354  m_inputParameters.m_lowResRasterBands.size() ; ++lowResRasterBandsIdx )
355  {
356  lowResRasterBandIdx = m_inputParameters.m_lowResRasterBands[ lowResRasterBandsIdx ];
357 
358  ressampledBandProperties.push_back( new te::rst::BandProperty(
359  *m_inputParameters.m_lowResRasterPtr->getBand( lowResRasterBandIdx )->getProperty() ) );
360  ressampledBandProperties[ lowResRasterBandsIdx ]->m_blkw = outNCols;
361  ressampledBandProperties[ lowResRasterBandsIdx ]->m_blkh = 1;
362  ressampledBandProperties[ lowResRasterBandsIdx ]->m_nblocksx = 1;
363  ressampledBandProperties[ lowResRasterBandsIdx ]->m_nblocksy = outNRows;
364  }
365 
366  try
367  {
368  ressampledRasterPtr.reset( new te::mem::ExpansibleRaster( 20, ressampledGrid,
369  ressampledBandProperties ) );
370  }
371  catch( te::common::Exception& e )
372  {
374  }
375 
376  const double colsRescaleFactor =
378  ((double)outNCols);
379  const double rowsRescaleFactor =
381  ((double)outNRows);
382  unsigned int outRow = 0;
383  unsigned int outCol = 0;
384  double inRow = 0;
385  double inCol = 0;
388  std::complex< double > value = 0;
389  te::rst::Raster& ressampledRaster = *ressampledRasterPtr;
390  double inNoDataValue = 0;
391  double outNoDataValue = 0;
392 
393  for( lowResRasterBandsIdx = 0 ; lowResRasterBandsIdx <
394  m_inputParameters.m_lowResRasterBands.size() ; ++lowResRasterBandsIdx )
395  {
396  lowResRasterBandIdx = m_inputParameters.m_lowResRasterBands[ lowResRasterBandsIdx ];
397  inNoDataValue = m_inputParameters.m_lowResRasterPtr->getBand( lowResRasterBandIdx )->getProperty()->m_noDataValue;
398  outNoDataValue = ressampledRaster.getBand( lowResRasterBandsIdx )->getProperty()->m_noDataValue;
399 
400  for( outRow = 0 ; outRow < outNRows ; ++outRow )
401  {
402  inRow = ((double)outRow) * rowsRescaleFactor;
403 
404  for( outCol = 0 ; outCol < outNCols ; ++outCol )
405  {
406  inCol = ((double)outCol) * colsRescaleFactor;
407 
408  interpol.getValue( inCol, inRow, value, lowResRasterBandIdx );
409 
410  if( value.real() == inNoDataValue )
411  {
412  ressampledRaster.setValue( outCol, outRow, outNoDataValue, lowResRasterBandsIdx );
413  }
414  else
415  {
416  ressampledRaster.setValue( outCol, outRow, value.real(), lowResRasterBandsIdx );
417  }
418  }
419  }
420  }
421 
422  return true;
423  }
424 
425  bool PCAFusion::swapBandByHighResRaster( te::rst::Raster& pcaRaster, const unsigned int pcaRasterBandIdx )
426  {
429 
430  assert( pcaRasterBandIdx < pcaRaster.getNumberOfBands() );
431  te::rst::Band& pcaBand = (*pcaRaster.getBand( pcaRasterBandIdx ));
433 
434  double pcaZeroMean = 0.0;
436  0 : 1, pcaZeroMean ) )
437  {
438  return false;
439  }
440 
441  double pcaZeroStdDev = 0.0;
443  0 : 1, &pcaZeroMean, pcaZeroStdDev ) )
444  {
445  return false;
446  }
447 
448  double hrMean = 0.0;
449  if( ! te::rp::GetMeanValue( hrBand, m_inputParameters.m_enableThreadedProcessing ? 0 : 1, hrMean ) )
450  {
451  return false;
452  }
453 
454  double hrStdDev = 0.0;
455  if( ! te::rp::GetStdDevValue( hrBand, m_inputParameters.m_enableThreadedProcessing ? 0 : 1, &hrMean, hrStdDev ) )
456  {
457  return false;
458  }
459 
460  const double gain = ( ( hrStdDev == 0.0 ) ? 0.0 : ( pcaZeroStdDev / hrStdDev ) );
461  const double& pcaNoDataValue = pcaBand.getProperty()->m_noDataValue;
462  const double& hrNoDataValue = hrBand.getProperty()->m_noDataValue;
463  const unsigned int nRows = pcaRaster.getNumberOfRows();
464  const unsigned int nCols = pcaRaster.getNumberOfColumns();
465  unsigned int col = 0;
466  unsigned int row = 0;
467  double value = 0;
468  double pcaAllowedMin = 0;
469  double pcaAllowedMax = 0;
470  te::rp::GetDataTypeRange( pcaBand.getProperty()->getType(), pcaAllowedMin,
471  pcaAllowedMax );
472 
473  for( row = 0 ; row < nRows ; ++row )
474  {
475  for( col = 0 ; col < nCols ; ++col )
476  {
477  hrBand.getValue( col, row, value );
478  if( value == hrNoDataValue )
479  {
480  pcaBand.setValue( col, row, pcaNoDataValue );
481  }
482  else
483  {
484  value = ( ( value - hrMean ) * gain ) + pcaZeroMean;
485  value = std::max( pcaAllowedMin, value );
486  value = std::min( pcaAllowedMax, value );
487 
488  pcaBand.setValue( col, row, value );
489  }
490  }
491  }
492 
493  return true;
494  }
495 
496  }
497 } // end namespace te
498 
bool GetMeanValue(const te::rst::Band &band, const unsigned int maxThreads, double &meanValue)
Get the mean of band pixel values.
Definition: Functions.cpp:1086
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
Near neighborhood interpolation method.
Definition: Enums.h:95
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:333
bool swapBandByHighResRaster(te::rst::Raster &pcaRaster, const unsigned int pcaRasterBandIdx)
Swap the band values by the normalized high resolution raster data.
Definition: PCAFusion.cpp:425
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.
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:55
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:180
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:92
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits::max().
Definition: BandProperty.h:136
bool DirectPrincipalComponents(const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, boost::numeric::ublas::matrix< double > &pcaMatrix, te::rst::Raster &pcaRaster, const std::vector< unsigned int > &pcaRasterBands, const unsigned int maxThreads)
Generate all principal components from the given input raster.
Definition: Functions.cpp:1504
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
void reset()
Clear all internal allocated objects and reset the algorithm to its initial state.
Definition: PCAFusion.cpp:279
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:437
URI C++ Library.
bool initialize(const AlgorithmInputParameters &inputParams)
Initialize the algorithm instance making it ready for execution.
Definition: PCAFusion.cpp:285
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
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:338
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 std::vector< unsigned int > &outputRasterBands, const unsigned int maxThreads)
Regenerate the original raster from its principal components.
Definition: Functions.cpp:1594
Raster Processing algorithm input parameters base interface.
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
Creation of skeleton imagems.
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:1211
#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