27 #include "../common/MatrixUtils.h" 28 #include "../common/progress/TaskProgress.h" 29 #include "../geometry/Coord2D.h" 30 #include "../geometry/Envelope.h" 31 #include "../geometry/Point.h" 32 #include "../geometry/Polygon.h" 33 #include "../raster/Grid.h" 34 #include "../raster/PositionIterator.h" 35 #include "../raster/Utils.h" 36 #include "../raster/SynchronizedRaster.h" 37 #include "../memory/CachedRaster.h" 49 #include <boost/numeric/ublas/io.hpp> 50 #include <boost/numeric/ublas/lu.hpp> 51 #include <boost/numeric/ublas/matrix.hpp> 52 #include <boost/ptr_container/ptr_vector.hpp> 65 { 1.32, 2.71, 3.84, 6.64, 10.83, std::numeric_limits<double>::max()},
66 { 2.77, 4.61, 5.99, 9.21, 13.82, std::numeric_limits<double>::max()},
67 { 4.11, 6.25, 7.82, 11.35, 16.27, std::numeric_limits<double>::max()},
68 { 5.39, 7.78, 9.49, 13.28, 18.47, std::numeric_limits<double>::max()},
69 { 6.63, 9.24, 11.07, 15.09, 20.52, std::numeric_limits<double>::max()},
70 { 7.84, 10.65, 12.59, 16.81, 22.46, std::numeric_limits<double>::max()},
71 { 9.04, 12.02, 14.07, 18.48, 24.32, std::numeric_limits<double>::max()},
72 {10.22, 13.36, 15.51, 20.09, 26.13, std::numeric_limits<double>::max()},
73 {11.39, 14.68, 16.92, 21.67, 27.88, std::numeric_limits<double>::max()},
74 {12.55, 15.99, 18.31, 23.21, 29.59, std::numeric_limits<double>::max()}
119 m_covarianceMatrix(cm)
143 unsigned int nBands =
static_cast<unsigned int>(
m_meanVector.size());
145 boost::numeric::ublas::matrix<double> term1(1, nBands);
146 boost::numeric::ublas::matrix<double> term2(nBands, 1);
148 for (
unsigned int i = 0; i < nBands; i++)
152 term2(i, 0) = term1(0, i);
156 term1 = prod(term1, term2);
159 return std::numeric_limits<double>::max();
171 return std::numeric_limits< double >::max();
193 return std::numeric_limits< double >::max();
199 return std::numeric_limits< double >::max();
203 boost::numeric::ublas::prod(
209 boost::numeric::ublas::prod(
295 "Invalid distance type" );
306 if(acceptanceThreshold < 90.0)
308 else if(acceptanceThreshold < 95.0)
310 else if(acceptanceThreshold < 99.0)
312 else if(acceptanceThreshold < 99.9)
314 else if(acceptanceThreshold < 100.0)
331 std::unique_ptr< te::mem::CachedRaster > cachedRasterPtr;
336 inputRasterPtr = cachedRasterPtr.get();
342 boost::ptr_vector< te::gm::Polygon > reprojectedPolsHandler;
343 std::vector< te::gm::Polygon* > reprojectedPolsNPtrs;
348 const int rasterSRID = inputRasterPtr->getSRID();
349 std::unique_ptr< te::gm::Geometry > transformedGeomPtr;
351 std::unique_ptr< te::common::TaskProgress > taskPtr;
356 static_cast<int>(inputPolygonsPtrSize)));
359 for( std::size_t inputPolygonsPtrIdx = 0 ; inputPolygonsPtrIdx <
360 inputPolygonsPtrSize ; ++inputPolygonsPtrIdx )
364 transformedGeomPtr->transform( rasterSRID );
365 reprojectedPolsNPtrs.push_back( (
te::gm::Polygon*)transformedGeomPtr.get() );
366 reprojectedPolsHandler.push_back( (
te::gm::Polygon*)transformedGeomPtr.release() );
371 if( !taskPtr->isActive() )
return false;
375 inputPolygonsPtr = &reprojectedPolsNPtrs;
380 std::multimap< double, Pattern > regions;
383 std::mutex globalMutex;
384 std::mutex condVarMutex;
385 std::condition_variable condVar;
388 std::size_t nextInputPolIdx2Process = 0;
389 unsigned int runningThreadsCounter = 0;
390 bool continueProcessingFlag =
true;
409 const unsigned int maxSegThreads = runningThreadsCounter =
411 const std::size_t inputPolygonsSize = inputPolygonsPtr->size();
412 std::vector< std::shared_ptr< std::thread > > threadsPtrs;
413 std::shared_ptr< std::thread > threadPtr;
415 std::unique_ptr< te::common::TaskProgress > taskPtr;
420 (
int)inputPolygonsSize) );
425 for(
unsigned int threadIdx = 0 ; threadIdx < maxSegThreads ; ++threadIdx )
428 threadsPtrs.push_back( threadPtr );
435 std::unique_lock<std::mutex> condVarLocker( condVarMutex );
436 condVar.wait_for( condVarLocker, std::chrono::seconds( 1 ) );
437 condVarLocker.unlock();
441 std::unique_lock<std::mutex> globalLocker( globalMutex );
445 taskPtr->setCurrentStep( nextInputPolIdx2Process );
446 if( !taskPtr->isActive() )
448 continueProcessingFlag =
false;
453 if( (!continueProcessingFlag) || ( runningThreadsCounter == 0 ) )
461 for(
unsigned int threadIdx = 0 ; threadIdx < maxSegThreads ; ++threadIdx )
463 threadsPtrs[ threadIdx ]->join();
469 runningThreadsCounter = 1;
478 Pattern* firstZeroDeterminantClusterPtr = 0;
479 std::multimap< double, Pattern >::iterator regionsIt = regions.begin();
480 const std::multimap< double, Pattern >::iterator regionsItEnd = regions.end();
481 std::unique_ptr< te::common::TaskProgress > taskPtr;
489 while( regionsIt != regionsItEnd )
491 if( regionsIt->second.m_covarianceMatrixDet == 0 )
493 if( firstZeroDeterminantClusterPtr )
495 regionsIt->second.m_myCluster = firstZeroDeterminantClusterPtr;
499 firstZeroDeterminantClusterPtr = &( regionsIt->second );
500 regionsIt->second.
m_myCluster = &( regionsIt->second );
507 regionsIt->second.
m_myCluster = &( regionsIt->second );
513 if( ! taskPtr->isActive() )
return false;
526 double distance2 = 0;
527 std::multimap<double, Pattern >::reverse_iterator regionsRIt1;
528 std::multimap<double, Pattern >::reverse_iterator regionsRIt2;
529 std::multimap<double, Pattern >::reverse_iterator regionsRIt3;
530 const std::multimap<double, Pattern >::reverse_iterator regionsItRBegin = regions.rbegin();
531 const std::multimap<double, Pattern >::reverse_iterator regionsItREnd = regions.rend();
534 std::set<std::pair<unsigned int, unsigned int> > compared;
536 std::unique_ptr< te::common::TaskProgress > taskPtr;
540 TE_TR(
"ISOSeg algorithm - detecting clusters") ) );
553 for (regionsRIt1 = regionsItRBegin; regionsRIt1 != regionsItREnd; ++regionsRIt1)
557 for (regionsRIt2 = regionsRIt1; regionsRIt2 != regionsItREnd; ++regionsRIt2)
559 if (regionsRIt1->second.m_myCluster != regionsRIt2->second.m_myCluster)
561 if (compared.find(std::pair<unsigned int, unsigned int>(
562 regionsRIt1->second.m_myCluster->m_id,
563 regionsRIt2->second.m_myCluster->m_id)) == compared.end())
565 compared.insert(std::pair<unsigned int, unsigned int>(
566 regionsRIt1->second.m_myCluster->m_id,
567 regionsRIt2->second.m_myCluster->m_id));
568 compared.insert(std::pair<unsigned int, unsigned int>(
569 regionsRIt2->second.m_myCluster->m_id,
570 regionsRIt1->second.m_myCluster->m_id));
577 distance = regionsRIt1->second.m_myCluster->getMahalanobisDistance(
578 regionsRIt2->second.m_myCluster );
579 distance2 = regionsRIt2->second.m_myCluster->getMahalanobisDistance(
580 regionsRIt1->second.m_myCluster );
581 distance = (distance2 < distance? distance2: distance);
584 distance = regionsRIt1->second.m_myCluster->getBhattacharyyaDistance(
585 regionsRIt2->second.m_myCluster );
591 if (distance <= maxDistance)
596 oldid = regionsRIt2->second.m_myCluster->m_id;
598 for (regionsRIt3 = regionsRIt2; regionsRIt3 != regionsItREnd; ++regionsRIt3)
601 if (regionsRIt3->second.m_myCluster->m_id == oldid)
603 regionsRIt3->second.m_myCluster = regionsRIt1->second.m_myCluster;
615 if( ! taskPtr->isActive() )
return false;
622 unsigned int maxColorMapOutValue = 0;
623 std::map< int, unsigned int > clusterId2OutputValueMap;
626 std::multimap<double, Pattern >::iterator regionsIt;
627 const std::multimap<double, Pattern >::iterator regionsItEnd = regions.end();
628 unsigned int outputValue = 1;
630 for (regionsIt = regions.begin(); regionsIt != regionsItEnd; ++regionsIt)
632 if( clusterId2OutputValueMap.find( regionsIt->second.m_myCluster->m_id ) ==
633 clusterId2OutputValueMap.end() )
635 clusterId2OutputValueMap[ regionsIt->second.m_myCluster->m_id ] = outputValue;
640 maxColorMapOutValue = outputValue - 1;
646 std::vector< int >
dt;
649 std::vector< double > noDataValues;
650 noDataValues.push_back( (
double)( maxColorMapOutValue + 2 ) );
653 "Output raster creation error" );
656 "Output raster palette creation error" );
660 const double outNoDataValue =
m_outputRasterPtr->getBand( 0 )->getProperty()->m_noDataValue;
663 unsigned int col = 0;
666 for(
unsigned int row = 0 ; row < nRows ; ++row )
668 for( col = 0 ; col <
nCols ; ++
col )
670 outBand.
setValue( col, row, outNoDataValue );
678 const std::multimap<double, Pattern >::iterator regionsItEnd = regions.end();
679 double outputValue = 0;
681 std::unique_ptr< te::common::TaskProgress > taskPtr;
686 static_cast<int>(regions.size())));
689 for (std::multimap<double, Pattern >::iterator regionsIt = regions.begin();
690 regionsIt != regionsItEnd; ++regionsIt)
692 te::gm::Polygon* polygon = inputPolygonsPtr->operator[]( regionsIt->second.m_id );
693 outputValue = clusterId2OutputValueMap[regionsIt->second.m_myCluster->m_id ];
711 if( ! taskPtr->isActive() )
return false;
728 const std::size_t inputRasterBandsSize = inputRasterBands.size();
730 std::size_t inputRasterBandsIdx1 = 0;
731 std::size_t inputRasterBandsIdx2 = 0;
732 std::size_t currentPolIdx = 0;
734 unsigned int validPixelsCount = 0;
735 std::vector< double > pixelValues( inputRasterBandsSize );
736 bool isValidPixel =
false;
737 double covariance = 0;
738 double pixelValue1 = 0;
739 double pixelValue2 = 0;
741 std::pair<double, Pattern> auxPair;
742 auxPair.second.m_id = -1;
743 auxPair.second.m_myCluster = 0;
744 auxPair.second.m_area = 0;
745 auxPair.second.m_covarianceMatrixDet = 0;
746 auxPair.second.m_meanVector.resize( inputRasterBandsSize );
747 auxPair.second.m_covarianceMatrix.resize( inputRasterBandsSize, inputRasterBandsSize );
748 auxPair.second.m_covarianceInversion.resize( inputRasterBandsSize, inputRasterBandsSize );
750 std::vector< double > bandsNoDataValues( inputRasterBandsSize );
751 for( inputRasterBandsIdx1 = 0 ; inputRasterBandsIdx1 <
752 inputRasterBandsSize ; ++inputRasterBandsIdx1 )
754 bandsNoDataValues[ inputRasterBandsIdx1 ] =
758 std::unique_ptr< te::common::TaskProgress > taskPtr;
763 (
int)inputPolygonsSize) );
778 if( currentPolIdx >= inputPolygonsSize )
793 &inputRaster, currentPolPtr );
795 &inputRaster, currentPolPtr );
797 if ( polIt != polItEnd )
799 auxPair.second.m_id = currentPolIdx;
803 for( inputRasterBandsIdx1 = 0 ; inputRasterBandsIdx1 <
804 inputRasterBandsSize ; ++inputRasterBandsIdx1 )
806 auxPair.second.m_meanVector[ inputRasterBandsIdx1 ] = 0.0;
809 validPixelsCount = 0;
811 while ( polIt != polItEnd )
815 for( inputRasterBandsIdx1 = 0 ; inputRasterBandsIdx1 <
816 inputRasterBandsSize ; ++inputRasterBandsIdx1 )
819 pixelValues[ inputRasterBandsIdx1 ], inputRasterBands[
820 inputRasterBandsIdx1 ] );
823 ( inputRasterBandsIdx1 == 0 )
825 ( pixelValues[ 0 ] == bandsNoDataValues[ 0 ] )
828 isValidPixel =
false;
835 for( inputRasterBandsIdx1 = 0 ; inputRasterBandsIdx1 <
836 inputRasterBandsSize ; ++inputRasterBandsIdx1 )
838 auxPair.second.m_meanVector[ inputRasterBandsIdx1 ] +=
839 pixelValues[ inputRasterBandsIdx1 ];
848 if( validPixelsCount )
850 for( inputRasterBandsIdx1 = 0 ; inputRasterBandsIdx1 <
851 inputRasterBandsSize ; ++inputRasterBandsIdx1 )
853 auxPair.second.m_meanVector[ inputRasterBandsIdx1 ] /= (double)validPixelsCount;
859 auxPair.first = (double)validPixelsCount;
860 auxPair.second.m_area = auxPair.first;
864 if( validPixelsCount > 2 )
866 for( inputRasterBandsIdx1 = 0 ; inputRasterBandsIdx1 <
867 inputRasterBandsSize ; ++inputRasterBandsIdx1 )
869 for( inputRasterBandsIdx2 = 0 ; inputRasterBandsIdx2 <
870 inputRasterBandsSize ; ++inputRasterBandsIdx2 )
872 if( inputRasterBandsIdx1 <= inputRasterBandsIdx2 )
875 &inputRaster, currentPolPtr );
878 while ( polIt != polItEnd )
881 pixelValue1, inputRasterBands[ inputRasterBandsIdx1 ] );
883 pixelValue2, inputRasterBands[ inputRasterBandsIdx2 ] );
886 ( pixelValue1 != bandsNoDataValues[ inputRasterBandsIdx1 ] )
894 auxPair.second.m_meanVector[ inputRasterBandsIdx1 ]
900 auxPair.second.m_meanVector[ inputRasterBandsIdx2 ]
908 covariance /= (double)( validPixelsCount - 1 );
910 auxPair.second.m_covarianceMatrix( inputRasterBandsIdx1, inputRasterBandsIdx2 ) = covariance;
911 auxPair.second.m_covarianceMatrix( inputRasterBandsIdx2, inputRasterBandsIdx1 ) = covariance;
924 auxPair.second.m_covarianceMatrixDet = 0;
929 auxPair.second.m_covarianceMatrixDet = 0;
936 auxPair.second.m_covarianceMatrixDet = 0;
946 taskPtr->setCurrentStep( currentPolIdx );
948 if( !taskPtr->isActive() )
964 unsigned int size1 = matrix.size1();
965 unsigned int size2 = matrix.size2();
967 std::cout << std::endl <<
"size1=" << size1;
968 std::cout << std::endl <<
"size2=" << size2;
970 for (
unsigned int i = 0; i < size1; ++ i)
972 std::cout << std::endl <<
"|";
974 for (
unsigned int j = 0; j < size2; ++ j)
976 std::cout <<
" " << matrix (i, j);
982 std::cout << std::endl;
unsigned int m_getBhattacharyyaDistance_bandIdx
Raster ISOSeg Classifier strategy factory.
An adapter class to allow concurrent access to raster data by multiple threads.
double getMahalanobisDistance(Pattern const *const p) const
Returns the Mahalanobis distance between two patterns.
AbstractParameters * clone() const
Create a clone copy of this instance.
~ClassifierISOSegStrategyFactory()
bool m_enableRasterCache
Enable or disable the use a raster data cache.
double m_getBhattacharyyaDistance_covsMegeDet
Base exception class for plugin module.
boost::numeric::ublas::matrix< double > m_getBhattacharyyaDistance_distanceTerm1
bool createOutputRaster(const std::vector< int > &bandsDataTypes, const std::vector< double > &noDataValues)
Create the output raster using the EXPANSIBLE driver.
double getBhattacharyyaDistance(Pattern const *const p) const
Returns the Bhattacharyya distance between two patterns.
This class implements the strategy to iterate with spatial restriction, the iteration occurs inside a...
boost::numeric::ublas::matrix< double > m_covarianceInversion
The inversion of covariance matrix between bands.
std::size_t * m_nextInputPolIdx2ProcessPtr
Pointer to variable pointing the next polygon index to process.
This class can be used to inform the progress of a task.
double m_getBhattacharyyaDistance_distanceValue
std::mutex * m_condVarMutexPtr
Pointer to the condition variable mutex.
boost::numeric::ublas::matrix< double > m_getBhattacharyyaDistance_meansDif
unsigned int getRow() const
Returns the current row in iterator.
An access synchronizer to be used in SynchronizedRaster raster instances.
boost::numeric::ublas::matrix< double > m_getBhattacharyyaDistance_covsMege
std::vector< te::gm::Polygon * > const * m_inputPolygonsPtr
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits<double>::max().
#define TE_TR(message)
It marks a string in order to get translated.
bool m_isInitialized
True if this instance is initialized.
boost::numeric::ublas::matrix< double > m_getBhattacharyyaDistance_covsMegeInv
The parameters passed to the fill regions thread entry.
bool operator<(const Pattern &rhs) const
bool execute()
Executes the classification strategy.
bool m_enableProgress
Pointer to variable pointing the variable to enable or disable the thread internal progress interface...
ClassifierISOSegStrategyFactory()
std::vector< unsigned int > const * m_inputRasterBandsPtr
Pointer to the input raster bands do be processed.
const te::rst::Band * getBand(std::size_t i) const
Returns the raster i-th band.
std::vector< unsigned int > m_inputRasterBands
Input raster bands.
static const double classifierISOSegStrategyChiTable[10][6]
te::rst::RasterSynchronizer * m_inputRasterSyncPtr
Pointer to the input raster sync.
static void printMatrix(const boost::numeric::ublas::matrix< double > &matrix)
Print a matrix to std::out.
Raster classifier strategy factory base class.
ISOSeg strategy for OBIA classification. The algorithm orders regions by area (larger first)...
const Parameters & operator=(const Parameters ¶ms)
unsigned int unsigned int nCols
TECOMMONEXPORT unsigned int GetPhysProcNumber()
Returns the number of physical processors.
bool GetDeterminant(const boost::numeric::ublas::matrix< T > &inputMatrix, double &determinant)
Get the Matrix determinant value.
Bhattacharyya Distance Type.
static PolygonIterator end(const te::rst::Raster *r, const te::gm::Polygon *p)
Returns an iterator referring to after the end of the iterator.
An abstract class for raster data strucutures.
#define TERP_LOG_AND_THROW(message)
Logs a error message and throws.
BandProperty * getProperty()
Returns the band property.
static te::dt::TimeDuration dt(20, 30, 50, 11)
ClassifierISOSegStrategy()
bool m_enableMultiThread
Enable or disable the use multipe threads.
bool operator==(const Pattern &rhs) const
Return true if two clusters are equal.
A RAM cache adaptor to an external existent raster that must always be avaliable. ...
double getThreshold(const double acceptanceThreshold, const unsigned nBands) const
A raster band description.
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Mahalanobis Distance Type.
DistanceType m_distanceType
Distance type.
std::condition_variable * m_condVarPtr
Pointer to the condition variable.
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.
static PolygonIterator begin(const te::rst::Raster *r, const te::gm::Polygon *p, const IterationType iterationType)
Returns an iterator referring to the first value of the band.
virtual void setValue(unsigned int c, unsigned int r, const double value)=0
Sets the cell attribute value.
std::unique_ptr< te::rst::Raster > m_outputRasterPtr
A pointer to the output raster.
int m_id
The id of the region of the pattern.
te::rp::ClassifierStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
Abstract parameters base interface.
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
bool m_progressInterfaceEnabled
Progress interface status.
Describes a region or a cluster (group of regions with similar properties) to be used by ISOSeg metho...
~ClassifierISOSegStrategy()
bool * m_continueProcessingFlagPtr
Pointer to variable pointing the variable to allow the process to continue.
te::rst::Raster const * m_inputRasterPtr
A pointer to the input raster.
unsigned int * m_runningThreadsCounterPtr
Pointer to variable pointing the current number of running threads.
Classifier Strategy Parameters.
Raster classifier strategy base class.
std::multimap< double, Pattern > * m_outputRegionsPtr
Pointer to the output regions container.
bool initialize(ClassifierStrategyParameters const *const strategyParams)
Initialize the classification strategy.
bool GetInverseMatrix(const boost::numeric::ublas::matrix< T > &inputMatrix, boost::numeric::ublas::matrix< T > &outputMatrix)
Matrix inversion.
unsigned int m_getBhattacharyyaDistance_nBands
ClassifierISOSegStrategy::Parameters m_parameters
Internal execution parameters.
double m_area
The area of all regions inside a pattern.
std::vector< double > m_meanVector
The vector of mean values, 1 value per band;.
Pattern & operator=(const Pattern &rhs)
Raster Processing functions.
double m_acceptanceThreshold
The acceptance threshold (the closer to 100%, few clusters are created).
std::mutex * m_globalMutexPtr
Pointer to the mutex.
ISOSeg strategy for segmentation-based classification.
unsigned int getColumn() const
Returns the current column in iterator.
Pattern * m_myCluster
The associated cluster of this pattern (optional).
std::vector< te::gm::Polygon * > const * m_inputPolygonsPtr
Input polygons.
void reset()
Reset to initial state.
#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...
bool setOutputRasterPalette(const unsigned int size)
Create and set the output raster palette folowing the current internal settings.
static void fillRegionsThreadEntry(FillRegionsThreadEntryParams *paramsPtr)
Fill regions thread entry.
double m_covarianceMatrixDet
The covariance matrix determinant.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
boost::numeric::ublas::matrix< double > m_covarianceMatrix
The covariance matrix between bands.