27 #include "../common/PlatformUtils.h" 41 #include <boost/math/special_functions/binomial.hpp> 42 #include <boost/random.hpp> 44 #define RANSACGETMAXINVALIDITERATIONS( assurance, dynamicMaxIterations ) \ 46 (RansacIntegerCounterT)1 \ 49 (RansacIntegerCounterT)( \ 50 ((RansacFloatCounterT)dynamicMaxIterations) \ 52 ((RansacFloatCounterT)assurance) \ 57 #define RANSACGETMAXITERATIONS( goodTPNumber, totalTPNumber, modelRequiredTPNumber, procsNumber, assurance ) \ 60 (RansacIntegerCounterT) \ 63 (RansacFloatCounterT)( 1.0 - ((RansacFloatCounterT)assurance) ) \ 67 ((RansacFloatCounterT)1.0) \ 71 ((RansacFloatCounterT)goodTPNumber ) \ 73 ((RansacFloatCounterT)totalTPNumber) \ 76 ((RansacFloatCounterT)modelRequiredTPNumber) \ 82 ((RansacIntegerCounterT)procsNumber) \ 85 #define RANSACSYNCTHREAD \ 88 if( bestTransfPtr->initialize( bestParams ) ) \ 91 ( paramsPtr->m_bestTransformationPtrPtr->get() == 0 ) \ 94 ( bestTiePoins.size() > \ 95 (*paramsPtr->m_bestTransformationPtrPtr)->getParameters().m_tiePoints.size() ) \ 98 ( bestTiePoins.size() == \ 99 (*paramsPtr->m_bestTransformationPtrPtr)->getParameters().m_tiePoints.size() ) \ 102 ( bestParamsConvexHullArea > (*paramsPtr->m_bestParamsConvexHullAreaPtr) ) \ 105 ( bestParamsConvexHullArea == (*paramsPtr->m_bestParamsConvexHullAreaPtr) ) \ 108 ( bestParamsMaxDMapErrorPtr < (*paramsPtr->m_bestParamsMaxDMapErrorPtr) ) \ 110 ( bestParamsMaxIMapErrorPtr < (*paramsPtr->m_bestParamsMaxIMapErrorPtr) ) \ 118 (*paramsPtr->m_bestTransformationPtrPtr).reset( \ 119 bestTransfPtr->clone() ); \ 120 (*paramsPtr->m_bestParamsMaxDMapErrorPtr) = bestParamsMaxDMapErrorPtr; \ 121 (*paramsPtr->m_bestParamsMaxIMapErrorPtr) = bestParamsMaxIMapErrorPtr; \ 122 (*paramsPtr->m_bestParamsConvexHullAreaPtr) = bestParamsConvexHullArea; \ 123 (*paramsPtr->m_bestTiePoinsPtr) = bestTiePoins; \ 126 if( dynamicMaxIterations < globalDynamicMaxIterations ) \ 127 globalDynamicMaxIterations = dynamicMaxIterations; \ 196 const double maxDirectMapError,
197 const double maxInverseMapError,
199 const double& assurance,
200 const bool enableMultiThread,
201 const std::vector<double>& tiePointsWeights,
202 std::vector< te::gm::GTParameters::TiePoint >& outTiePoints,
203 std::unique_ptr< GeometricTransformation >& outTransf
206 if(maxDirectMapError < 0)
209 if(maxInverseMapError < 0)
212 if((assurance <= 0.0) || (assurance > 1.0))
215 outTiePoints.clear();
220 std::map< double, GTParameters::TiePoint > tpsMap;
222 const unsigned int inputTPNmb = (
unsigned int)
224 double tiePointsWeightsSum = 0;
226 if( tiePointsWeights.size() > 0 )
228 if( tiePointsWeights.size() != inputParams.
m_tiePoints.size () )
233 unsigned int tpIdx = 0;
235 for( tpIdx = 0 ; tpIdx < inputTPNmb ; ++tpIdx )
237 if( tiePointsWeights[ tpIdx ] < 0.0 )
return false;
239 tiePointsWeightsSum += tiePointsWeights[ tpIdx ];
242 if( tiePointsWeightsSum <= 0.0 )
return false;
246 double newWSum = 0.0;
249 for( tpIdx = 0 ; tpIdx < inputTPNmb ; ++tpIdx )
251 newW = tiePointsWeights[ tpIdx ];
252 newW /= tiePointsWeightsSum;
256 tpsMap[ newWSum ] = inputParams.
m_tiePoints[ tpIdx ];
262 const double increment = 1.0 /
265 for(
unsigned int tpIdx = 0 ; tpIdx < inputTPNmb ; ++tpIdx )
275 std::unique_ptr< GeometricTransformation > bestTransformationPtr(
277 if( bestTransformationPtr.get() == nullptr )
return false;
280 boost::mutex syncMutex;
281 double bestParamsMaxDMapError = maxDirectMapError;
282 double bestParamsMaxIMapError = maxInverseMapError;
283 double bestParamsConvexHullArea = -1.0;
284 bool returnValue =
true;
285 bool keepRunningFlag =
true;
292 enableMultiThread ? procsNumber : 1
297 bestTransformationPtr->getMinRequiredTiePoints(),
299 bestTransformationPtr->getMinRequiredTiePoints(),
300 enableMultiThread ? procsNumber : 1,
305 baseThreadParams.m_inputGTParamsPtr = &inputParams;
306 baseThreadParams.m_maxDirectMapError = maxDirectMapError;
307 baseThreadParams.m_maxInverseMapError = maxInverseMapError;
308 baseThreadParams.m_assurance = assurance;
309 baseThreadParams.m_useDynamicIterationsNumber = ( maxIterations == 0 );
310 baseThreadParams.m_dynamicMaxIterationsPtr = &dynamicMaxIterations;
311 baseThreadParams.m_procsNumber = enableMultiThread ?
313 baseThreadParams.m_returnValuePtr = &returnValue;
314 baseThreadParams.m_mutexPtr = &syncMutex;
315 baseThreadParams.m_keepRunningFlagPtr = &keepRunningFlag;
316 baseThreadParams.m_tpsMapPtr = &tpsMap;
317 baseThreadParams.m_bestTransformationPtrPtr = &bestTransformationPtr;
318 baseThreadParams.m_bestParamsMaxDMapErrorPtr = &bestParamsMaxDMapError;
319 baseThreadParams.m_bestParamsMaxIMapErrorPtr = &bestParamsMaxIMapError;
320 baseThreadParams.m_bestParamsConvexHullAreaPtr = &bestParamsConvexHullArea;
321 baseThreadParams.m_bestTiePoinsPtr = &outTiePoints;
325 if( enableMultiThread )
327 std::vector< ApplyRansacThreadEntryThreadParams > threadsParameters;
328 threadsParameters.resize( procsNumber, baseThreadParams );
329 boost::thread_group threads;
331 for(
unsigned int threadIdx = 0 ; threadIdx < procsNumber ;
335 &threadsParameters[ threadIdx ] ) );
347 if( bestTransformationPtr.get() )
349 outTransf.reset( bestTransformationPtr.release() );
371 std::unique_ptr< te::gm::GeometricTransformation > bestTransfPtr(
373 if( bestTransfPtr.get() == nullptr )
381 const std::vector< te::gm::GTParameters::TiePoint > tiePoints =
383 std::map< double, GTParameters::TiePoint > tpsMap = *(paramsPtr->
m_tpsMapPtr);
387 boost::random::mt19937 generator( (boost::random::mt19937::result_type)time(
nullptr) );
400 boost::mutex& mutex = (*(paramsPtr->
m_mutexPtr));
404 const unsigned int reqTPsNmb = bestTransfPtr->getMinRequiredTiePoints();
405 const unsigned int inputTPNmb = (
unsigned int)tiePoints.size();
407 if( inputTPNmb < reqTPsNmb )
421 double bestParamsConvexHullArea = -1.0;
422 std::vector< te::gm::GTParameters::TiePoint > bestTiePoins;
426 boost::random::uniform_01< double > distribution;
429 std::vector< te::gm::GTParameters::TiePoint > consensusSetTiePoints;
430 consensusSetParams.
m_tiePoints.reserve( tiePoints.size() );
431 double consensusSetMaxDMapError = 0;
432 double consensusSetMaxIMapError = 0;
433 unsigned int consensusSetSize = 0;
434 double consensusSetConvexHullArea = 0.0;
435 std::vector< Coord2D > consensusSetPt1ConvexHullPoits;
437 double tiePointDMapErr = 0;
438 double tiePointIMapErr = 0;
440 std::map< double, GTParameters::TiePoint >::const_iterator tpsMapIt;
441 unsigned int inputTpIdx = 0;
444 std::vector< GTParameters::TiePoint* > selectedTpsPtrsVec;
445 selectedTpsPtrsVec.resize( reqTPsNmb,
nullptr );
446 unsigned int selectedTpsPtrsVecIdx = 0;
447 bool selectedTpsNotSelectedBefore =
false;
457 double randomValue = 0;
459 while( keepRunningFlag && ( currentIteration < dynamicMaxIterations ) &&
460 ( consecutiveInvalidIterations < dynamicMaxConsecutiveInvalidIterations ) )
466 consensusSetParams.
reset();;
467 selectedTpsCounter = 0;
469 while( selectedTpsCounter < reqTPsNmb )
471 randomValue = distribution( generator );
472 tpsMapIt = tpsMap.upper_bound( randomValue );
473 assert( tpsMapIt != tpsMap.end() );
477 selectedTpsNotSelectedBefore =
true;
479 for( selectedTpsPtrsVecIdx = 0 ; selectedTpsPtrsVecIdx <
480 selectedTpsCounter ; ++selectedTpsPtrsVecIdx )
482 if( selectedTpsPtrsVec[ selectedTpsPtrsVecIdx ] ==
483 &(tpsMapIt->second) )
485 selectedTpsNotSelectedBefore =
false;
490 if( selectedTpsNotSelectedBefore )
492 consensusSetParams.
m_tiePoints.push_back( tpsMapIt->second );
495 ++selectedTpsCounter;
501 if( bestTransfPtr->computeParameters( consensusSetParams ) )
506 consensusSetTiePoints.clear();
507 consensusSetMaxDMapError = 0;
508 consensusSetMaxIMapError = 0;
510 for( inputTpIdx = 0 ; inputTpIdx < inputTPNmb ; ++inputTpIdx )
514 tiePointDMapErr = bestTransfPtr->getDirectMappingError( curTP, consensusSetParams );
515 tiePointIMapErr = bestTransfPtr->getInverseMappingError( curTP, consensusSetParams );
517 if( ( tiePointDMapErr <= maxDirectMapError ) &&
518 ( tiePointIMapErr <= maxInverseMapError ) )
520 consensusSetTiePoints.push_back( curTP );
522 if( tiePointDMapErr > consensusSetMaxDMapError )
523 consensusSetMaxDMapError = tiePointDMapErr;
524 if( tiePointIMapErr > consensusSetMaxIMapError )
525 consensusSetMaxIMapError = tiePointIMapErr;
529 consensusSetSize = (
unsigned int)consensusSetTiePoints.size();
531 consensusSetTiePoints );
536 ( consensusSetSize >= reqTPsNmb )
539 ( consensusSetSize > bestTiePoins.size() )
542 ( consensusSetSize == bestTiePoins.size() )
545 ( consensusSetConvexHullArea > bestParamsConvexHullArea )
548 ( consensusSetConvexHullArea == bestParamsConvexHullArea )
551 ( bestParamsMaxDMapErrorPtr > consensusSetMaxDMapError )
553 ( bestParamsMaxIMapErrorPtr > consensusSetMaxIMapError )
561 bestParams = consensusSetParams;
562 bestParamsMaxDMapErrorPtr = consensusSetMaxDMapError;
563 bestParamsMaxIMapErrorPtr = consensusSetMaxIMapError;
564 bestParamsConvexHullArea = consensusSetConvexHullArea;
565 bestTiePoins = consensusSetTiePoints;
567 consecutiveInvalidIterations = 0;
571 ++consecutiveInvalidIterations;
576 ++consecutiveInvalidIterations;
581 if( useDynamicIterationsNumber && ( currentIteration != 0 ) )
583 if( bestTiePoins.size() == inputTPNmb )
587 keepRunningFlag =
false;
593 else if( ! bestTiePoins.empty() )
602 if( dynamicMaxIterationsEstimation < dynamicMaxIterations )
604 dynamicMaxIterations =
605 ( dynamicMaxIterations - ( ( dynamicMaxIterations - dynamicMaxIterationsEstimation ) / 2 ) );
607 dynamicMaxConsecutiveInvalidIterations =
611 if( globalDynamicMaxIterations < dynamicMaxIterations )
613 dynamicMaxIterations = globalDynamicMaxIterations;
615 dynamicMaxConsecutiveInvalidIterations =
624 ( threadSyncIteration >= threadSyncMaxIterations )
626 ( currentIteration >= dynamicMaxIterations )
628 ( consecutiveInvalidIterations >= dynamicMaxConsecutiveInvalidIterations )
631 threadSyncIteration = 0;
636 ++threadSyncIteration;
647 if( tiePoints.size() < 3 )
655 for(
unsigned int tiePointsIdx = 0 ; tiePointsIdx < tiePoints.size() ;
659 tiePoints[ tiePointsIdx ].first.y ) );
662 std::unique_ptr< te::gm::Geometry > convexHullPtr( points.
convexHull() );
664 if( dynamic_cast< te::gm::Surface* >( convexHullPtr.get() ) )
666 return dynamic_cast< te::gm::Surface*
>( convexHullPtr.get() )->getArea();
boost::mutex * m_mutexPtr
static double getPt1ConvexHullArea(const std::vector< GTParameters::TiePoint > &tiePoints)
Returns the tie-points convex hull area (GTParameters::TiePoint::first).
std::vector< TiePoint > m_tiePoints
Tie points.
GTFilter()
Default constructor.
double * m_bestParamsMaxDMapErrorPtr
unsigned long int RansacIntegerCounterT
RANSAC integer counter type.
std::unique_ptr< GeometricTransformation > * m_bestTransformationPtrPtr
~ApplyRansacThreadEntryThreadParams()
double m_maxDirectMapError
A point with x and y coordinate values.
std::map< double, GTParameters::TiePoint > const * m_tpsMapPtr
A map from accumulated probabilities (normalized between 0 and 1) to tie-points data.
RansacIntegerCounterT m_procsNumber
MultiPoint is a GeometryCollection whose elements are restricted to points.
std::pair< Coord2D, Coord2D > TiePoint
Tie point type definition.
TECOMMONEXPORT unsigned int GetPhysProcNumber()
Returns the number of physical processors.
std::vector< te::gm::GTParameters::TiePoint > * m_bestTiePoinsPtr
MultiPoint is a GeometryCollection whose elements are restricted to points.
#define RANSACGETMAXINVALIDITERATIONS(assurance, dynamicMaxIterations)
Parameters used by the GTFilter::applyRansacThreadEntry method.
A point with x and y coordinate values.
#define RANSACGETMAXITERATIONS(goodTPNumber, totalTPNumber, modelRequiredTPNumber, procsNumber, assurance)
2D Geometric transformation outliers remotion filter.
Surface is an abstract class that represents a 2-dimensional geometric objects.
bool m_useDynamicIterationsNumber
const ApplyRansacThreadEntryThreadParams & operator=(const ApplyRansacThreadEntryThreadParams &other)
static GeometricTransformation * make(const std::string &factoryKey)
It creates an object with the appropriated factory.
static void applyRansacThreadEntry(te::gm::GTFilter::ApplyRansacThreadEntryThreadParams *paramsPtr)
Surf locator thread entry.
GTParameters const * m_inputGTParamsPtr
double * m_bestParamsConvexHullAreaPtr
double m_maxInverseMapError
void add(Geometry *g)
It adds the geometry into the collection.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
ApplyRansacThreadEntryThreadParams()
2D Geometric transformation factory.
2D Geometric transformation parameters.
bool applyRansac(const std::string &transfName, const GTParameters &inputParams, const double maxDirectMapError, const double maxInverseMapError, const RansacIntegerCounterT &maxIterations, const double &assurance, const bool enableMultiThread, const std::vector< double > &tiePointsWeights, std::vector< te::gm::GTParameters::TiePoint > &outTiePoints, std::unique_ptr< GeometricTransformation > &outTransf)
Apply a RANSAC based outliers remotion strategy.
bool * m_keepRunningFlagPtr
double * m_bestParamsMaxIMapErrorPtr
RansacIntegerCounterT * m_dynamicMaxIterationsPtr
virtual Geometry * convexHull() const _NOEXCEPT_OP(false)
This method calculates the Convex Hull of a geometry.
Surface is an abstract class that represents a 2-dimensional geometric objects.
std::string const * m_transfNamePtr