TiePointsLocatorSURFStrategy.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/TiePointsLocatorSURFStrategy.cpp
22  \brief Tie-Pointsr locator SURF strategy.
23 */
24 
26 #include "Macros.h"
27 #include "../common/progress/TaskProgress.h"
28 #include "../sam/rtree.h"
29 
30 #include <memory>
31 
32 #include <boost/shared_array.hpp>
33 
34 namespace
35 {
37  TiePointsLocatorSURFStrategyFactoryInstance;
38 }
39 
40 namespace te
41 {
42  namespace rp
43  {
45  {
46  reset();
47  }
48 
51  {
52  reset();
53  operator=( other );
54  }
55 
57  {
58  reset();
59  }
60 
62  throw( te::rp::Exception )
63  {
67  }
68 
72  {
73  reset();
74 
78 
79  return *this;
80  }
81 
84  {
85  return new Parameters( *this );
86  }
87 
88  /* ------------------------------------------------------------------------*/
89 
91  {
92  reset();
93  }
94 
96  {
97  reset();
98  }
99 
101  const double subSampleOptimizationRescaleFactor,
102  const TiePointsLocatorStrategyParameters& inputSpecParams,
103  std::unique_ptr< TiePointsLocatorStrategyParameters >& subSampledSpecParamsPtr ) const
104  {
105  Parameters const* inputSpecParamsPtr = dynamic_cast< Parameters const* >( &inputSpecParams );
106  TERP_TRUE_OR_THROW( inputSpecParamsPtr, "Invalid specific parameters" );
107 
108  subSampledSpecParamsPtr.reset( (te::rp::TiePointsLocatorStrategyParameters*)inputSpecParams.clone() );
109 
110  Parameters* subSampledSpecParamsNakedPtr = dynamic_cast< Parameters* >( subSampledSpecParamsPtr.get() );
111  TERP_TRUE_OR_THROW( subSampledSpecParamsNakedPtr, "Invalid specific parameters" );
112 
113  subSampledSpecParamsNakedPtr->m_surfScalesNumber =
114  3
115  +
116  (unsigned int)
117  (
118  ((double)( inputSpecParamsPtr->m_surfScalesNumber - 3 ))
119  *
120  subSampleOptimizationRescaleFactor
121  );
122  subSampledSpecParamsNakedPtr->m_surfOctavesNumber =
123  1
124  +
125  (unsigned int)
126  (
127  ((double)( inputSpecParamsPtr->m_surfOctavesNumber - 1 ))
128  *
129  subSampleOptimizationRescaleFactor
130  );
131  }
132 
134  std::unique_ptr< TiePointsLocatorStrategyParameters >& defaultSpecParamsPtr ) const
135  {
136  defaultSpecParamsPtr.reset( new Parameters() );
137  }
138 
140  const te::rp::TiePointsLocatorInputParameters& inputParameters )
141  {
142  m_inputParameters = inputParameters;
143 
145  == 1, "Invalid number of raster 1 bands" );
147  == 1, "Invalid number of raster 2 bands" );
148 
149  Parameters const* specParsPtr = dynamic_cast< Parameters const* >(
150  inputParameters.getSpecStrategyParams() );
151  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( specParsPtr, "Invalid specific parameters" );
152 
153  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( specParsPtr->m_surfScalesNumber > 2,
154  "Invalid m_surfScalesNumber" );
155 
156  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( specParsPtr->m_surfOctavesNumber > 0,
157  "Invalid m_surfOctavesNumber" );
158 
159  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( ( specParsPtr->m_surfMaxNormEuclideanDist >= 0 ) &&
160  ( specParsPtr->m_surfMaxNormEuclideanDist <= 1.0 ),
161  "Invalid m_surfMaxNormEuclideanDist" );
162 
163  m_isInitialized = true;
164 
165  // Defining the number of tie points
166 
168  {
170  }
171 
172  return true;
173  }
174 
176  {
178 
179  m_isInitialized = false;
181  }
182 
184  te::gm::GeometricTransformation const * const raster1ToRaster2TransfPtr,
185  const double raster1ToRaster2TransfDMapError,
186  MatchedInterestPointsSetT& matchedInterestPoints )
187  {
188  matchedInterestPoints.clear();
189 
190  if( !m_isInitialized )
191  {
192  return false;
193  }
194 
195  /* Calculating the rescale factors
196  factor = rescaled_orignal_image / original_image */
197 
198  double raster1XRescFact = 1.0;
199  double raster1YRescFact = 1.0;
200  double raster2XRescFact = 1.0;
201  double raster2YRescFact = 1.0;
202 
204  {
205  /* The image 1 has poor resolution - bigger pixel resolution values -
206  and image 2 needs to be rescaled down */
207 
208  raster2XRescFact = 1.0 / m_inputParameters.m_pixelSizeXRelation;
209  }
210  else if( m_inputParameters.m_pixelSizeXRelation < 1.0 )
211  {
212  /* The image 2 has poor resolution - bigger pixel resolution values
213  and image 1 needs to be rescaled down */
214 
215  raster1XRescFact = m_inputParameters.m_pixelSizeXRelation;
216  }
217 
219  {
220  /* The image 1 has poor resolution - bigger pixel resolution values -
221  and image 2 needs to be rescaled down */
222 
223  raster2YRescFact = 1.0 / m_inputParameters.m_pixelSizeYRelation;
224  }
225  else if( m_inputParameters.m_pixelSizeYRelation < 1.0 )
226  {
227  /* The image 2 has poor resolution - bigger pixel resolution values
228  and image 1 needs to be rescaled down */
229 
230  raster1YRescFact = m_inputParameters.m_pixelSizeYRelation;
231  }
232 
237 
238  // Defining the maximum number of interest points
239 
240  unsigned int maxInterestPoints1 = m_inputParameters.m_maxTiePoints;
241  unsigned int maxInterestPoints2 = m_inputParameters.m_maxTiePoints;
242 
243  {
244  const double width1 = ((double)m_inputParameters.m_raster1TargetAreaWidth)
245  * raster1XRescFact;
246  const double height1 = ((double)m_inputParameters.m_raster1TargetAreaHeight)
247  * raster1YRescFact;
248 
249  const double width2 = ((double)m_inputParameters.m_raster2TargetAreaWidth)
250  * raster2XRescFact;
251  const double height2 = ((double)m_inputParameters.m_raster2TargetAreaHeight)
252  * raster2YRescFact;
253 
254  const double area1 = width1 * height1;
255  const double area2 = width2 * height2;
256 
257  if( area1 > area2 )
258  {
259  maxInterestPoints1 = (unsigned int)( ((double)maxInterestPoints1)*( area1 / area2 ) );
260  }
261  else
262  {
263  maxInterestPoints2 = (unsigned int)( ((double)maxInterestPoints2)*( area2 / area1 ) );
264  }
265  }
266 
267  // progress
268 
269  std::unique_ptr< te::common::TaskProgress > progressPtr;
271  {
272  progressPtr.reset( new te::common::TaskProgress );
273  progressPtr->setTotalSteps( 10 );
274  progressPtr->setMessage( "Locating tie points" );
275  progressPtr->pulse();
276  if( ! progressPtr->isActive() ) return false;
277  }
278 
279  // Locating interest points and features from raster 1
280 
281  InterestPointsSetT raster1InterestPoints;
282  FloatsMatrix raster1Features;
283  {
284  // Loading image data
285 
286  std::vector< boost::shared_ptr< FloatsMatrix > > rasterData;
287  UCharsMatrix maskRasterData;
288  double achievedRescaleFactorX = 0;
289  double achievedRescaleFactorY = 0;
290 
291  if( !loadRasterData(
295  0,
300  raster1XRescFact,
301  raster1YRescFact,
303  20,
304  rasterData,
305  maskRasterData,
306  achievedRescaleFactorX,
307  achievedRescaleFactorY ) )
308  {
309  return false;
310  }
311 
312  raster1XRescFact = achievedRescaleFactorX;
313  raster1YRescFact = achievedRescaleFactorY;
314 
315 // printMatrix( *(rasterData[ 0 ]) );
316 // createTifFromMatrix( *(rasterData[ 0 ]), InterestPointsSetT(), "loadedRaster1");
317 
319  {
320  progressPtr->pulse();
321  if( ! progressPtr->isActive() ) return false;
322  }
323 
324  // Creating the integral image
325 
326  FloatsMatrix integralRaster;
327 
329  integralRaster ), "Integral image creation error" );
330 
331  rasterData.clear();
332 
334  {
335  progressPtr->pulse();
336  if( ! progressPtr->isActive() ) return false;
337  }
338 
339 // printMatrix( integralRaster );
340 // createTifFromMatrix( integralRaster, InterestPointsSetT(), "integralRaster1" );
341 
342  // locating interest points
343 
345  maxInterestPoints1,
346  integralRaster,
347  maskRasterData.getLinesNumber() ? (&maskRasterData) : nullptr,
348  raster1InterestPoints ),
349  "Error locating raster 1 interest points" );
350 
351 // createTifFromMatrix( *(rasterData[ 0 ]), raster1InterestPoints, "surfInterestPoints1");
352 
354  {
355  progressPtr->pulse();
356  if( ! progressPtr->isActive() ) return false;
357  }
358 
359 
360  InterestPointsSetT validInterestPoints;
361 
363  integralRaster, validInterestPoints, raster1Features ),
364  "Error generating raster features" );
365 
366  // Bring interest points to full raster indexed coords reference
367 
368  raster1InterestPoints.clear();
369 
370  {
371  InterestPointsSetT::iterator itB = validInterestPoints.begin();
372  const InterestPointsSetT::iterator itE = validInterestPoints.end();
373  InterestPointT auxIP;
374 
375  while( itB != itE )
376  {
377  auxIP = *itB;
378  auxIP.m_x = static_cast<unsigned int>((auxIP.m_x / raster1XRescFact) +
380  auxIP.m_y = static_cast<unsigned int>((auxIP.m_y / raster1YRescFact) +
382 
383  raster1InterestPoints.insert( auxIP );
384 
385  ++itB;
386  }
387  }
388 
390  {
391  progressPtr->pulse();
392  if( ! progressPtr->isActive() ) return false;
393  }
394 
395  }
396 
397  // Locating interest points and features from raster 2
398 
399  InterestPointsSetT raster2InterestPoints;
400  FloatsMatrix raster2Features;
401  {
402  // Loading image data
403 
404  std::vector< boost::shared_ptr< FloatsMatrix > > rasterData;
405  UCharsMatrix maskRasterData;
406  double achievedRescaleFactorX = 0;
407  double achievedRescaleFactorY = 0;
408 
409  if( !loadRasterData(
413  0,
418  raster2XRescFact,
419  raster2YRescFact,
421  20,
422  rasterData,
423  maskRasterData,
424  achievedRescaleFactorX,
425  achievedRescaleFactorY ) )
426  {
427  return false;
428  }
429 
430  raster2XRescFact = achievedRescaleFactorX;
431  raster2YRescFact = achievedRescaleFactorY;
432 
433 // printMatrix( *(rasterData[ 0 ]) );
434 // createTifFromMatrix( *(rasterData[ 0 ]), InterestPointsSetT(), "loadedRaster2");
435 
437  {
438  progressPtr->pulse();
439  if( ! progressPtr->isActive() ) return false;
440  }
441 
442  // Creating the integral image
443 
444  FloatsMatrix integralRaster;
445 
447  integralRaster ), "Integral image creation error" );
448 
450  {
451  progressPtr->pulse();
452  if( ! progressPtr->isActive() ) return false;
453  }
454 
455  rasterData.clear();
456 
457 // printMatrix( integralRaster );
458 // createTifFromMatrix( integralRaster, InterestPointsSetT(), "integralRaster2" );
459 
460  // locating interest points
461 
463  maxInterestPoints2,
464  integralRaster,
465  maskRasterData.getLinesNumber() ? (&maskRasterData) : nullptr,
466  raster2InterestPoints ),
467  "Error locating raster interest points" );
468 
469 // createTifFromMatrix( *(rasterData[ 0 ]), raster2InterestPoints, "surfInterestPoints2");
470 
472  {
473  progressPtr->pulse();
474  if( ! progressPtr->isActive() ) return false;
475  }
476 
477  InterestPointsSetT validInterestPoints;
478 
480  integralRaster, validInterestPoints, raster2Features ),
481  "Error generating raster features" );
482 
483  // Bring interest points to full raster indexed coords reference
484 
485  raster2InterestPoints.clear();
486 
487  {
488  InterestPointsSetT::iterator itB = validInterestPoints.begin();
489  const InterestPointsSetT::iterator itE = validInterestPoints.end();
490  InterestPointT auxIP;
491 
492  while( itB != itE )
493  {
494  auxIP = *itB;
495  auxIP.m_x = static_cast<unsigned int>((auxIP.m_x / raster2XRescFact) +
497  auxIP.m_y = static_cast<unsigned int>((auxIP.m_y / raster2YRescFact) +
499 
500  raster2InterestPoints.insert( auxIP );
501 
502  ++itB;
503  }
504  }
505 
507  {
508  progressPtr->pulse();
509  if( ! progressPtr->isActive() ) return false;
510  }
511  }
512 
513 // printMatrix( raster1Features );
514 // printMatrix( raster2Features );
515 
516  // Matching features
517 
518  MatchedInterestPointsSetT internalMatchedInterestPoints;
519 
521  raster1Features,
522  raster2Features,
523  raster1InterestPoints,
524  raster2InterestPoints,
525  raster1ToRaster2TransfPtr,
526  raster1ToRaster2TransfDMapError,
527  internalMatchedInterestPoints ),
528  "Error matching features" );
529 
531  {
532  progressPtr->pulse();
533  if( ! progressPtr->isActive() ) return false;
534  }
535 
536  // Removing the repeated matched points (those present in more than one scale)
537  // keeping the higher MatchedInterestPointsT::m_feature value
538 
539  {
540  MatchedInterestPointsSetT::iterator it1 = internalMatchedInterestPoints.begin();
541  MatchedInterestPointsSetT::iterator it2;
542  MatchedInterestPointsSetT::iterator eraseIt;
543 
544  while( it1 != internalMatchedInterestPoints.end() )
545  {
546  it2 = it1;
547  ++it2;
548  eraseIt = internalMatchedInterestPoints.end();
549 
550  while( it2 != internalMatchedInterestPoints.end() )
551  {
552  if(
553  ( it1->m_point1.m_x == it2->m_point1.m_x )
554  &&
555  ( it1->m_point1.m_y == it2->m_point1.m_y )
556  &&
557  ( it1->m_point2.m_x == it2->m_point2.m_x )
558  &&
559  ( it1->m_point2.m_y == it2->m_point2.m_y )
560  )
561  {
562  if( it1->m_feature < it2->m_feature )
563  {
564  eraseIt = it1;
565  }
566  else if( it1->m_feature > it2->m_feature )
567  {
568  eraseIt = it2;
569  }
570 
571  break;
572  }
573  else
574  {
575  ++it2;
576  }
577  }
578 
579  if( eraseIt == it1 )
580  {
581  ++it1;
582  internalMatchedInterestPoints.erase( eraseIt );
583  }
584  else if( eraseIt != internalMatchedInterestPoints.end() )
585  {
586  internalMatchedInterestPoints.erase( eraseIt );
587  ++it1;
588  }
589  else
590  {
591  ++it1;
592  }
593  }
594  }
595 
596  // Removing the worse mathed points to fitting the required amount of matched points
597 
598  while( internalMatchedInterestPoints.size() > m_inputParameters.m_maxTiePoints )
599  {
600  internalMatchedInterestPoints.erase( internalMatchedInterestPoints.begin() );
601  }
602 
603  // Generating the output matched interest points
604 
605  {
606  MatchedInterestPointsT auxMatchedPoints;
607  MatchedInterestPointsSetT::const_iterator itB = internalMatchedInterestPoints.begin();
608  const MatchedInterestPointsSetT::const_iterator itE = internalMatchedInterestPoints.end();
609 
610  float minFeature1P1 = FLT_MAX;
611  float maxFeature1P1 = (-1.0) * FLT_MAX;
612  float minFeature1P2 = FLT_MAX;
613  float maxFeature1P2 = (-1.0) * FLT_MAX;
614  float minDist = FLT_MAX;
615  float maxDist = (-1.0 ) *FLT_MAX;
616 
617  while( itB != itE )
618  {
619  if( minFeature1P1 > itB->m_point1.m_feature1 )
620  minFeature1P1 = itB->m_point1.m_feature1;
621  if( maxFeature1P1 < itB->m_point1.m_feature1 )
622  maxFeature1P1 = itB->m_point1.m_feature1;
623 
624  if( minFeature1P2 > itB->m_point2.m_feature1 )
625  minFeature1P2 = itB->m_point2.m_feature1;
626  if( maxFeature1P2 < itB->m_point2.m_feature1 )
627  maxFeature1P2 = itB->m_point2.m_feature1;
628 
629  if( minDist > itB->m_feature )
630  minDist = itB->m_feature;
631  if( maxDist < itB->m_feature )
632  maxDist = itB->m_feature;
633 
634  ++itB;
635  }
636 
637  float feature1P1Range = maxFeature1P1 - minFeature1P1;
638  float feature1P2Range = maxFeature1P2 - minFeature1P2;
639  float distRange = maxDist - minDist;
640 
641  if( ( feature1P1Range == 0.0 ) || ( feature1P2Range == 0.0 ) ||
642  ( distRange == 0.0 ) )
643  {
644  itB = internalMatchedInterestPoints.begin();
645 
646  while( itB != itE )
647  {
648  auxMatchedPoints = *itB;
649  auxMatchedPoints.m_feature = 1.0;
650 
651  matchedInterestPoints.insert( auxMatchedPoints );
652 
653  ++itB;
654  }
655  }
656  else
657  {
658  itB = internalMatchedInterestPoints.begin();
659 
660  while( itB != itE )
661  {
662  auxMatchedPoints = *itB;
663  auxMatchedPoints.m_feature =
664  (
665  (
666  ( maxDist - auxMatchedPoints.m_feature )
667  /
668  distRange
669  )
670  +
671  (
672  ( auxMatchedPoints.m_point1.m_feature1 - minFeature1P1 )
673  /
674  feature1P1Range
675  )
676  +
677  (
678  ( auxMatchedPoints.m_point2.m_feature1 - minFeature1P2 )
679  /
680  feature1P2Range
681  )
682  )
683  /
684  static_cast<float>(3.0);
685 
686  matchedInterestPoints.insert( auxMatchedPoints );
687 
688  ++itB;
689  }
690  }
691  }
692 
693  return true;
694  }
695 
697  {
698  TERP_TRUE_OR_THROW( m_isInitialized, "Not initialized instance" );
699 
700  unsigned int returnValue = 0;
701 
702  const unsigned int maxRastersArea = (unsigned int)
703  std::max(
704  (
706  *
708  *
710  *
712  )
713  ,
714  (
716  *
718  *
720  *
722  )
723  );
724 
725  const unsigned int filterWindowSize = ( getSurfOctaveBaseFilterSize( 0 ) +
728 
729  returnValue = maxRastersArea /
730  ( filterWindowSize * filterWindowSize );
731 
732  // This is because the features and matching matrix bare eing allocated in RAM
733 
734  const double totalPhysMem = (double)te::common::GetTotalPhysicalMemory();
735  const double usedVMem = (double)te::common::GetUsedVirtualMemory();
736  const double totalVMem = (double)te::common::GetTotalVirtualMemory();
737  const double freeVMem = 0.4 * std::min( totalPhysMem, ( totalVMem - usedVMem ) );
738 
739  const double featureElementsNumber = 65 * 65;
740 
741  double maxFeaturesMemory =
742  std::max(
743  0.0
744  ,
745  (
746  (-2.0) * featureElementsNumber
747  +
748  std::sqrt(
749  ( 4.0 * featureElementsNumber * featureElementsNumber )
750  +
751  ( 4.0 * freeVMem / ((double)sizeof( float ) ) )
752  )
753  )
754  );
755  maxFeaturesMemory =
756  std::max(
757  maxFeaturesMemory
758  ,
759  (
760  (-2.0) * featureElementsNumber
761  -
762  std::sqrt(
763  ( 4.0 * featureElementsNumber * featureElementsNumber )
764  +
765  ( 4.0 * freeVMem / ((double)sizeof( float ) ) )
766  )
767  )
768  );
769 
770  returnValue = std::min( returnValue, (unsigned int)maxFeaturesMemory );
771 
772  return returnValue;
773  }
774 
776  FloatsMatrix& outputData )
777  {
778  TERP_TRUE_OR_RETURN_FALSE( outputData.reset( inputData.getLinesNumber(),
779  inputData.getColumnsNumber() ), "Cannot allocate image matrix" );
780 
781  const unsigned int nLines = inputData.getLinesNumber();
782  const unsigned int nCols = inputData.getColumnsNumber();
783 
784  unsigned int outCol = 0;
785  float currSum = 0;
786 
787  for( unsigned int outLine = 0 ; outLine < nLines ; ++outLine )
788  for( outCol = 0; outCol < nCols ; ++outCol )
789  {
790  currSum = inputData[ outLine ][ outCol ];
791 
792  if( outLine )
793  currSum += outputData[ outLine - 1 ][ outCol ];
794  if( outCol )
795  currSum += outputData[ outLine ][ outCol - 1 ];
796  if( outLine && outCol )
797  currSum -= outputData[ outLine - 1 ][ outCol - 1 ];
798 
799  outputData[ outLine ][ outCol ] = currSum;
800  }
801 
802  return true;
803  }
804 
806  const unsigned int maxInterestPoints,
807  const FloatsMatrix& integralRasterData,
808  UCharsMatrix const* maskRasterDataPtr,
809  InterestPointsSetT& interestPoints ) const
810  {
811  interestPoints.clear();
812 
813  const unsigned int minIntegralRasterWidthHeigh = getSurfFilterSize(
816  if( ( integralRasterData.getColumnsNumber() < minIntegralRasterWidthHeigh )
817  || ( integralRasterData.getLinesNumber() < minIntegralRasterWidthHeigh ) )
818  {
819  return true;
820  }
821 
822  // finding interest points
823 
824  bool returnValue = true;
825  boost::mutex rastaDataAccessMutex;
826  boost::mutex interestPointsAccessMutex;
827  unsigned int nextRasterLinesBlockToProcess = 0;
828  std::vector< InterestPointsSetT > interestPointsSubSectors(
831 
832  SurfLocatorThreadParams threadParams;
833  threadParams.m_returnValuePtr = &returnValue;
834  threadParams.m_rastaDataAccessMutexPtr = &rastaDataAccessMutex;
835  threadParams.m_interestPointsAccessMutexPtr = &interestPointsAccessMutex;
837  &nextRasterLinesBlockToProcess;
838  threadParams.m_integralRasterDataPtr = &integralRasterData;
839  threadParams.m_maskRasterDataPtr = maskRasterDataPtr;
842  threadParams.m_interestPointsSubSectorsPtr = &interestPointsSubSectors;
843  threadParams.m_maxInterestPointsBySubSector = maxInterestPoints /
847 
849  {
851 
852  boost::thread_group threads;
853 
854  for( unsigned int threadIdx = 0 ; threadIdx < threadParams.m_processingBlocksNumber ;
855  ++threadIdx )
856  {
857  threads.add_thread( new boost::thread(
859  &threadParams ) );
860  }
861 
862  threads.join_all();
863  }
864  else
865  {
866  threadParams.m_processingBlocksNumber = 1;
867 
868  locateSurfInterestPointsThreadEntry( &threadParams );
869  }
870 
871  // transfering sector maximas to output
872 
873  const unsigned int interestPointsSubSectorsSize = static_cast<unsigned int>(interestPointsSubSectors.size());
874 
875  for( unsigned int interestPointsSubSectorsIdx = 0 ; interestPointsSubSectorsIdx <
876  interestPointsSubSectorsSize ; ++interestPointsSubSectorsIdx )
877  {
878  interestPoints.insert(
879  interestPointsSubSectors[ interestPointsSubSectorsIdx ].begin(),
880  interestPointsSubSectors[ interestPointsSubSectorsIdx ].end() );
881  }
882 
883  return returnValue;
884  }
885 
886 
887 
889  {
890  assert( paramsPtr );
891  assert( paramsPtr->m_returnValuePtr );
892  assert( paramsPtr->m_integralRasterDataPtr );
893  assert( paramsPtr->m_interestPointsSubSectorsPtr );
894  assert( paramsPtr->m_rastaDataAccessMutexPtr );
895  assert( paramsPtr->m_interestPointsAccessMutexPtr );
896  assert( paramsPtr->m_processingBlocksNumber > 0 );
897  assert( paramsPtr->m_nextRasterLinesBlockToProcessValuePtr );
898  assert( paramsPtr->m_scalesNumber > 2 );
899  assert( paramsPtr->m_octavesNumber > 0 );
900 
901  // Globals
902 
903  paramsPtr->m_rastaDataAccessMutexPtr->lock();
904 
905  const unsigned int maxGausFilterWidth = getSurfFilterSize(
906  paramsPtr->m_octavesNumber - 1, paramsPtr->m_scalesNumber - 1 );
907  const unsigned int maxGausFilterRadius = maxGausFilterWidth / 2;
908  const unsigned int rasterBuffersLinesNumber = maxGausFilterWidth;
909  const unsigned int lastRasterBuffersLineIdx = rasterBuffersLinesNumber - 1;
910  const unsigned int tiePointsSubSectorsSplitFactor = paramsPtr->m_tiePointsSubSectorsSplitFactor;
911  const unsigned int rowsBySubSector = (unsigned int)std::ceil(
912  ((double)paramsPtr->m_integralRasterDataPtr->getLinesNumber())
913  /
914  ((double)tiePointsSubSectorsSplitFactor) );
915  const unsigned int colsBySubSector = (unsigned int)std::ceil(
916  ((double)paramsPtr->m_integralRasterDataPtr->getColumnsNumber())
917  /
918  ((double)tiePointsSubSectorsSplitFactor) );
919  const unsigned int maxInterestPointsBySubSector = paramsPtr->m_maxInterestPointsBySubSector;
920  const unsigned int maxInterestPointsByScaleSubSector = maxInterestPointsBySubSector
921  / ( paramsPtr->m_octavesNumber * ( paramsPtr->m_scalesNumber - 2 ) );
922  const unsigned int rasterLines = paramsPtr->m_integralRasterDataPtr->getLinesNumber();
923  const unsigned int buffersCols = paramsPtr->m_integralRasterDataPtr->getColumnsNumber();
924  const unsigned int rasterBufferLineSizeBytes = sizeof( float ) *
925  buffersCols;
926  const unsigned int maskRasterBufferLineSizeBytes = sizeof( UCharsMatrix::ElementTypeT ) *
927  buffersCols;
928  const unsigned int processingBlocksNumber = paramsPtr->m_processingBlocksNumber;
929  const unsigned int maxLinesPerProcessingBlock = (unsigned int)
930  std::ceil(
931  ((double)rasterLines)
932  /
933  ((double)processingBlocksNumber)
934  );
935  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
936 
937  // Allocating the internal raster data buffer
938  // and the mask raster buffer
939 
940  FloatsMatrix rasterBufferDataHandler;
941  boost::scoped_array< float* > rasterBufferHandler( new float*[ rasterBuffersLinesNumber ] );
942  {
943  if( ! rasterBufferDataHandler.reset( rasterBuffersLinesNumber, buffersCols,
945  {
946  paramsPtr->m_rastaDataAccessMutexPtr->lock();
947  *(paramsPtr->m_returnValuePtr) = false;
948  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
949  return;
950  }
951 
952  for( unsigned int rasterBufferDataHandlerLine = 0 ; rasterBufferDataHandlerLine <
953  rasterBuffersLinesNumber ; ++rasterBufferDataHandlerLine )
954  {
955  rasterBufferHandler[ rasterBufferDataHandlerLine ] = rasterBufferDataHandler[
956  rasterBufferDataHandlerLine ];
957  }
958  }
959  float** rasterBufferPtr = rasterBufferHandler.get();
960 
961  // Allocating the mask raster buffer
962 
963  UCharsMatrix maskRasterBufferDataHandler;
964 
965  boost::scoped_array< unsigned char* > maskRasterBufferHandler( new unsigned char*[ rasterBuffersLinesNumber ] );
966 
967  unsigned char** maskRasterBufferPtr = nullptr;
968 
969  if( paramsPtr->m_maskRasterDataPtr )
970  {
971  if( ! maskRasterBufferDataHandler.reset( rasterBuffersLinesNumber, buffersCols,
973  {
974  paramsPtr->m_rastaDataAccessMutexPtr->lock();
975  *(paramsPtr->m_returnValuePtr) = false;
976  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
977  return;
978  }
979 
980  for( unsigned int maskRasterBufferDataHandlerLine = 0 ; maskRasterBufferDataHandlerLine <
981  rasterBuffersLinesNumber ; ++maskRasterBufferDataHandlerLine )
982  {
983  maskRasterBufferHandler[ maskRasterBufferDataHandlerLine ] = maskRasterBufferDataHandler[
984  maskRasterBufferDataHandlerLine ];
985  }
986 
987  maskRasterBufferPtr = maskRasterBufferHandler.get();
988  }
989 
990  // Allocating the internal octaves buffers
991 
992  FloatsMatrix octavesBufferDataHandler;
993  std::vector< std::vector< boost::shared_array< float* > > >
994  octavesBufferHandlers;
995  {
996  const unsigned int octavesBufferDataHandlerLines =
997  3 * paramsPtr->m_octavesNumber * paramsPtr->m_scalesNumber;
998  if( ! octavesBufferDataHandler.reset( octavesBufferDataHandlerLines ,
999  buffersCols,
1001  {
1002  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1003  *(paramsPtr->m_returnValuePtr) = false;
1004  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1005  return;
1006  }
1007  unsigned int octavesBufferDataHandlerLine = 0;
1008  unsigned int octavesBufferDataHandlerCol = 0;
1009  float* octavesBufferDataHandlerLinePtr = nullptr;
1010  for( octavesBufferDataHandlerLine = 0; octavesBufferDataHandlerLine <
1011  octavesBufferDataHandlerLines ; ++octavesBufferDataHandlerLine )
1012  {
1013  octavesBufferDataHandlerLinePtr = octavesBufferDataHandler[
1014  octavesBufferDataHandlerLine ];
1015 
1016  for( octavesBufferDataHandlerCol = 0; octavesBufferDataHandlerCol <
1017  buffersCols ; ++octavesBufferDataHandlerCol )
1018  {
1019  octavesBufferDataHandlerLinePtr[ octavesBufferDataHandlerCol ] = 0.0;
1020  }
1021  }
1022 
1023  octavesBufferDataHandlerLine = 0;
1024  unsigned int scaleIdx = 0 ;
1025  unsigned int octaveIdx = 0 ;
1026  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
1027  {
1028  octavesBufferHandlers.push_back( std::vector< boost::shared_array< float* > >() );
1029  std::vector< boost::shared_array< float* > >&
1030  currOctaveBuffersHandler = octavesBufferHandlers[ octaveIdx ];
1031 
1032  for( scaleIdx = 0 ; scaleIdx < paramsPtr->m_scalesNumber ; ++scaleIdx )
1033  {
1034  currOctaveBuffersHandler.push_back( boost::shared_array< float* >(
1035  new float*[ 3 ] ) );
1036  boost::shared_array< float* >& currOctavesBuffer =
1037  currOctaveBuffersHandler[ scaleIdx ];
1038  for( unsigned int bufferLine = 0 ; bufferLine < 3 ; ++bufferLine )
1039  {
1040  assert( octavesBufferDataHandlerLine <
1041  octavesBufferDataHandler.getLinesNumber() );
1042 
1043  currOctavesBuffer[ bufferLine ] = octavesBufferDataHandler[
1044  octavesBufferDataHandlerLine ];
1045 
1046  ++octavesBufferDataHandlerLine;
1047  }
1048  }
1049  }
1050  }
1051 
1052  // Allocating the laplacian sign buffers
1053 
1054  UCharsMatrix laplacianSignBufferDataHandler;
1055  std::vector< std::vector< boost::shared_array< unsigned char* > > >
1056  laplacianSignBufferHandlers;
1057  {
1058  const unsigned int laplacianSignBufferDataHandlerLines =
1059  3 * paramsPtr->m_octavesNumber * paramsPtr->m_scalesNumber;
1060  if( ! laplacianSignBufferDataHandler.reset( laplacianSignBufferDataHandlerLines ,
1061  buffersCols,
1063  {
1064  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1065  *(paramsPtr->m_returnValuePtr) = false;
1066  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1067  return;
1068  }
1069  unsigned int laplacianSignBufferDataHandlerLine = 0;
1070  unsigned int laplacianSignBufferDataHandlerCol = 0;
1071  unsigned char* laplacianSignBufferDataHandlerLinePtr = nullptr;
1072  for( laplacianSignBufferDataHandlerLine = 0; laplacianSignBufferDataHandlerLine <
1073  laplacianSignBufferDataHandlerLines ; ++laplacianSignBufferDataHandlerLine )
1074  {
1075  laplacianSignBufferDataHandlerLinePtr = laplacianSignBufferDataHandler[
1076  laplacianSignBufferDataHandlerLine ];
1077 
1078  for( laplacianSignBufferDataHandlerCol = 0; laplacianSignBufferDataHandlerCol <
1079  buffersCols ; ++laplacianSignBufferDataHandlerCol )
1080  {
1081  laplacianSignBufferDataHandlerLinePtr[ laplacianSignBufferDataHandlerCol ] =
1082  255;
1083  }
1084  }
1085 
1086  laplacianSignBufferDataHandlerLine = 0;
1087  unsigned int scaleIdx = 0 ;
1088  unsigned int octaveIdx = 0 ;
1089  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
1090  {
1091  laplacianSignBufferHandlers.push_back( std::vector< boost::shared_array< unsigned char* > >() );
1092  std::vector< boost::shared_array< unsigned char* > >&
1093  currlaplacianSignBuffersHandler = laplacianSignBufferHandlers[ octaveIdx ];
1094 
1095  for( scaleIdx = 0 ; scaleIdx < paramsPtr->m_scalesNumber ; ++scaleIdx )
1096  {
1097  currlaplacianSignBuffersHandler.push_back( boost::shared_array< unsigned char* >(
1098  new unsigned char*[ 3 ] ) );
1099  boost::shared_array< unsigned char* >& currlaplacianSignBuffer =
1100  currlaplacianSignBuffersHandler[ scaleIdx ];
1101  for( unsigned int bufferLine = 0 ; bufferLine < 3 ; ++bufferLine )
1102  {
1103  assert( laplacianSignBufferDataHandlerLine <
1104  laplacianSignBufferDataHandler.getLinesNumber() );
1105 
1106  currlaplacianSignBuffer[ bufferLine ] = laplacianSignBufferDataHandler[
1107  laplacianSignBufferDataHandlerLine ];
1108 
1109  ++laplacianSignBufferDataHandlerLine;
1110  }
1111  }
1112  }
1113  }
1114 
1115  // Locating interest points on each scale/octave
1116 
1117  const unsigned maxGausResponseFilterCenterBufferColBound = buffersCols -
1118  maxGausFilterRadius;
1119  const unsigned maxMaximaDetectionCenterBufferColBound = buffersCols -
1120  maxGausFilterRadius - 1;
1121 
1122  unsigned int scaleIdx = 0 ;
1123  unsigned int octaveIdx = 0 ;
1124  unsigned int subSectorIndex = 0;
1125  unsigned int scaleGlobalIndex = 0;
1126 
1127  std::vector< std::vector< InterestPointsSetT > > interestPointsSubSectors;
1128  {
1129  std::vector< InterestPointsSetT > dummyIPointsContainer(
1131  paramsPtr->m_tiePointsSubSectorsSplitFactor );
1132  interestPointsSubSectors.resize( paramsPtr->m_octavesNumber *
1133  paramsPtr->m_scalesNumber, dummyIPointsContainer );
1134  }
1135 
1136  for( unsigned int rasterLinesBlockIdx = 0; rasterLinesBlockIdx <
1137  processingBlocksNumber ; ++rasterLinesBlockIdx )
1138  {
1139  // the maxima points found inside the current raster block
1140  // for each combination of octaves and scales
1141  std::vector< InterestPointsSetT > blockMaximas( paramsPtr->m_scalesNumber *
1142  paramsPtr->m_octavesNumber, InterestPointsSetT() );
1143 
1144  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1145 
1146  if( rasterLinesBlockIdx == ( *(paramsPtr->m_nextRasterLinesBlockToProcessValuePtr ) ) )
1147  {
1148  ++( *(paramsPtr->m_nextRasterLinesBlockToProcessValuePtr ) );
1149 
1150  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1151 
1152  // globals
1153 
1154  const unsigned int rasterLinesStart =
1155  (unsigned int)
1156  std::max(
1157  0
1158  ,
1159  (
1160  ((int)(rasterLinesBlockIdx * maxLinesPerProcessingBlock ))
1161  -
1162  ((int)maxGausFilterRadius)
1163  -
1164  1
1165  )
1166  );
1167  const unsigned int rasterLinesEndBound =
1168  std::min(
1169  rasterLines
1170  ,
1171  (
1172  ( ( rasterLinesBlockIdx + 1 ) * maxLinesPerProcessingBlock )
1173  +
1174  maxGausFilterRadius
1175  +
1176  1
1177  )
1178  );
1179  const unsigned int firstRasterLineToGenerateResponse =
1180  rasterLinesStart + maxGausFilterWidth - 1;
1181  const unsigned int firstRasterLineToLookForMaximas =
1182  rasterLinesStart + maxGausFilterWidth + 1;
1183  unsigned int filterWidth = 0;
1184  unsigned int filterLobeWidth = 0;
1185  unsigned int filterLobeRadius = 0;
1186  unsigned int filterCenterBufCol = 0 ;
1187  float dXX = 0;
1188  float dYY = 0;
1189  float dXY = 0;
1190  InterestPointT auxInterestPoint;
1191  float** currScaleBufferPtr = nullptr;
1192  unsigned char** currLaplacianSignBufferPtr = nullptr;
1193  unsigned int lastScaleIdx = 0;
1194  unsigned int nextScaleIdx = 0;
1195  unsigned int prevResponseBufferColIdx = 0;
1196  unsigned int nextResponseBufferColIdx = 0;
1197  float windowCenterPixelValue = 0.0;
1198  float neighborMaximaDif_0_1 = 0.0;
1199  float neighborMaximaDif_0_2 = 0.0;
1200  float neighborMaximaDif_0_3 = 0.0;
1201  float neighborMaximaDif_0_4 = 0.0;
1202  float neighborMaximaDif_0_5 = 0.0;
1203  float neighborMaximaDif_0_6 = 0.0;
1204  float neighborMaximaDif_0_7 = 0.0;
1205  float neighborMaximaDif_0_8 = 0.0;
1206  float neighborMaximaDif_1_1 = 0.0;
1207  float neighborMaximaDif_1_2 = 0.0;
1208  float neighborMaximaDif_1_3 = 0.0;
1209  float neighborMaximaDif_1_4 = 0.0;
1210  float neighborMaximaDif_1_5 = 0.0;
1211  float neighborMaximaDif_1_6 = 0.0;
1212  float neighborMaximaDif_1_7 = 0.0;
1213  float neighborMaximaDif_1_8 = 0.0;
1214  float neighborMaximaDif_1_9 = 0.0;
1215  float neighborMaximaDif_2_1 = 0.0;
1216  float neighborMaximaDif_2_2 = 0.0;
1217  float neighborMaximaDif_2_3 = 0.0;
1218  float neighborMaximaDif_2_4 = 0.0;
1219  float neighborMaximaDif_2_5 = 0.0;
1220  float neighborMaximaDif_2_6 = 0.0;
1221  float neighborMaximaDif_2_7 = 0.0;
1222  float neighborMaximaDif_2_8 = 0.0;
1223  float neighborMaximaDif_2_9 = 0.0;
1224 
1225  // Processing each raster line from the current block
1226 
1227  for( unsigned int rasterLine = rasterLinesStart; rasterLine < rasterLinesEndBound ;
1228  ++rasterLine )
1229  {
1230  // read a new raster line into the last raster buffer line
1231  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1232  //std::cout << std::endl << "rasterLine"; std::cout << rasterLine << std::endl;
1233  //printBuffer( rasterBufferPtr, buffersLines, buffersCols );
1234  roolUpBuffer( rasterBufferPtr, rasterBuffersLinesNumber );
1235 // printBuffer( rasterBufferPtr, buffersLines, buffersCols );
1236  memcpy( rasterBufferPtr[ lastRasterBuffersLineIdx ],
1237  paramsPtr->m_integralRasterDataPtr->operator[]( rasterLine ),
1238  rasterBufferLineSizeBytes );
1239 // printBuffer( rasterBufferPtr, buffersLines, buffersCols );
1240  // read a new mask raster line into the last mask raster buffer line
1241  if( paramsPtr->m_maskRasterDataPtr )
1242  {
1243  roolUpBuffer( maskRasterBufferPtr, rasterBuffersLinesNumber );
1244  memcpy( maskRasterBufferPtr[ lastRasterBuffersLineIdx ],
1245  paramsPtr->m_maskRasterDataPtr->operator[]( rasterLine ),
1246  maskRasterBufferLineSizeBytes );
1247  }
1248  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1249 
1250  // generating the response maps for each octave/scale
1251 
1252  if( rasterLine >= firstRasterLineToGenerateResponse )
1253  {
1254  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
1255  {
1256  for( scaleIdx = 0 ; scaleIdx < paramsPtr->m_scalesNumber ;
1257  ++scaleIdx )
1258  {
1259  assert( octavesBufferHandlers.size() > octaveIdx );
1260  assert( octavesBufferHandlers[ octaveIdx].size() > scaleIdx );
1261  currScaleBufferPtr = octavesBufferHandlers[ octaveIdx][ scaleIdx ].get();
1262  assert( currScaleBufferPtr );
1263 
1264  assert( laplacianSignBufferHandlers.size() > octaveIdx );
1265  assert( laplacianSignBufferHandlers[ octaveIdx].size() > scaleIdx );
1266  currLaplacianSignBufferPtr = laplacianSignBufferHandlers[ octaveIdx][ scaleIdx ].get();
1267  assert( currLaplacianSignBufferPtr );
1268 
1269  // Roll up buffers
1270 
1271  roolUpBuffer( currScaleBufferPtr, 3 );
1272  roolUpBuffer( currLaplacianSignBufferPtr, 3 );
1273 
1274  // applying the filter kernels for the current scale
1275 
1276  filterWidth = getSurfFilterSize( octaveIdx, scaleIdx );
1277  assert( filterWidth <= maxGausFilterWidth );
1278 
1279  filterLobeWidth = filterWidth / 3;
1280  filterLobeRadius = filterLobeWidth / 2;
1281 
1282  for( filterCenterBufCol = maxGausFilterRadius ;
1283  filterCenterBufCol < maxGausResponseFilterCenterBufferColBound ;
1284  ++filterCenterBufCol )
1285  {
1286  dYY = getSurfDyyDerivative( rasterBufferPtr, filterCenterBufCol,
1287  maxGausFilterRadius, filterLobeWidth, filterLobeRadius);
1288  dYY /= (float)( filterWidth * filterWidth );
1289 
1290  dXX = getSurfDxxDerivative( rasterBufferPtr, filterCenterBufCol,
1291  maxGausFilterRadius, filterLobeWidth, filterLobeRadius);
1292  dXX /= (float)( filterWidth * filterWidth );
1293 
1294  dXY = getSurfDxyDerivative( rasterBufferPtr, filterCenterBufCol,
1295  maxGausFilterRadius, filterLobeWidth );
1296  dXY /= (float)( filterWidth * filterWidth );
1297 
1298  currScaleBufferPtr[ 2 ][ filterCenterBufCol ] =
1299  ( dXX * dYY ) - ( 0.81f * dXY * dXY );
1300  currLaplacianSignBufferPtr[ 2 ][ filterCenterBufCol ] =
1301  ( ( dXX + dYY ) >= 0.0 ) ? 1 : 0;
1302  }
1303  }
1304  }
1305  }
1306 
1307  // Finding local maximas over all scales using 3 x 3 x 3 window
1308  // at the lowest scale
1309 
1310  if( rasterLine >= firstRasterLineToLookForMaximas )
1311  {
1312 // printBuffer( octavesBufferHandlers[ 0 ][ 0 ].get(), buffersLines, buffersCols );
1313 // printBuffer( octavesBufferHandlers[ 0 ][ 1 ].get(), buffersLines, buffersCols );
1314 // printBuffer( octavesBufferHandlers[ 0 ][ 2 ].get(), buffersLines, buffersCols );
1315 // return;
1316 
1317  for( unsigned int windCenterCol = maxGausFilterRadius + 1;
1318  windCenterCol < maxMaximaDetectionCenterBufferColBound ; ++windCenterCol )
1319  {
1320  prevResponseBufferColIdx = windCenterCol - 1;
1321  nextResponseBufferColIdx = windCenterCol + 1;
1322  auxInterestPoint.m_feature1 = (-1.0) * FLT_MAX;
1323 
1324  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
1325  {
1326  std::vector< boost::shared_array< float* > >&
1327  currOctaveBuffersHandler = octavesBufferHandlers[ octaveIdx ];
1328 
1329  for( scaleIdx = 1 ; scaleIdx < ( paramsPtr->m_scalesNumber - 1 );
1330  ++scaleIdx )
1331  {
1332  windowCenterPixelValue = currOctaveBuffersHandler[
1333  scaleIdx ][ 1 ][ windCenterCol ];
1334  lastScaleIdx = scaleIdx - 1;
1335  nextScaleIdx = scaleIdx + 1;
1336 
1337  neighborMaximaDif_0_1 = windowCenterPixelValue - currOctaveBuffersHandler[
1338  scaleIdx ][ 0 ][ prevResponseBufferColIdx ];
1339  neighborMaximaDif_0_2 = windowCenterPixelValue - currOctaveBuffersHandler[
1340  scaleIdx ][ 0 ][ windCenterCol ];
1341  neighborMaximaDif_0_3 = windowCenterPixelValue - currOctaveBuffersHandler[
1342  scaleIdx ][ 0 ][ nextResponseBufferColIdx ];
1343  neighborMaximaDif_0_4 = windowCenterPixelValue - currOctaveBuffersHandler[
1344  scaleIdx ][ 1 ][ prevResponseBufferColIdx ];
1345  neighborMaximaDif_0_5 = windowCenterPixelValue - currOctaveBuffersHandler[
1346  scaleIdx ][ 1 ][ nextResponseBufferColIdx ];
1347  neighborMaximaDif_0_6 = windowCenterPixelValue - currOctaveBuffersHandler[
1348  scaleIdx ][ 2 ][ prevResponseBufferColIdx];
1349  neighborMaximaDif_0_7 = windowCenterPixelValue - currOctaveBuffersHandler[
1350  scaleIdx ][ 2 ][ windCenterCol ];
1351  neighborMaximaDif_0_8 = windowCenterPixelValue - currOctaveBuffersHandler[
1352  scaleIdx ][ 2 ][ nextResponseBufferColIdx ];
1353 
1354  if(
1355  ( windowCenterPixelValue > 0.0 )
1356  // verifying the current scale (center not included)
1357  && ( neighborMaximaDif_0_1 > 0.0 )
1358  && ( neighborMaximaDif_0_2 > 0.0 )
1359  && ( neighborMaximaDif_0_3 > 0.0 )
1360  && ( neighborMaximaDif_0_4 > 0.0 )
1361  && ( neighborMaximaDif_0_5 > 0.0 )
1362  && ( neighborMaximaDif_0_6 > 0.0 )
1363  && ( neighborMaximaDif_0_7 > 0.0 )
1364  && ( neighborMaximaDif_0_8 > 0.0 )
1365  )
1366  {
1367  neighborMaximaDif_1_1 = windowCenterPixelValue - currOctaveBuffersHandler[
1368  lastScaleIdx ][ 0 ][ prevResponseBufferColIdx ];
1369  neighborMaximaDif_1_2 = windowCenterPixelValue - currOctaveBuffersHandler[
1370  lastScaleIdx ][ 0 ][ windCenterCol ];
1371  neighborMaximaDif_1_3 = windowCenterPixelValue - currOctaveBuffersHandler[
1372  lastScaleIdx ][ 0 ][ nextResponseBufferColIdx ];
1373  neighborMaximaDif_1_4 = windowCenterPixelValue - currOctaveBuffersHandler[
1374  lastScaleIdx ][ 1 ][ prevResponseBufferColIdx ];
1375  neighborMaximaDif_1_5 = windowCenterPixelValue - currOctaveBuffersHandler[
1376  lastScaleIdx ][ 1 ][ windCenterCol ];
1377  neighborMaximaDif_1_6 = windowCenterPixelValue - currOctaveBuffersHandler[
1378  lastScaleIdx ][ 1 ][ nextResponseBufferColIdx ];
1379  neighborMaximaDif_1_7 = windowCenterPixelValue - currOctaveBuffersHandler[
1380  lastScaleIdx ][ 2 ][ prevResponseBufferColIdx];
1381  neighborMaximaDif_1_8 = windowCenterPixelValue - currOctaveBuffersHandler[
1382  lastScaleIdx ][ 2 ][ windCenterCol ];
1383  neighborMaximaDif_1_9 = windowCenterPixelValue - currOctaveBuffersHandler[
1384  lastScaleIdx ][ 2 ][ nextResponseBufferColIdx ];
1385 
1386  if(
1387  // verifying the top scale
1388  ( neighborMaximaDif_1_1 > 0.0 )
1389  && ( neighborMaximaDif_1_2 > 0.0 )
1390  && ( neighborMaximaDif_1_3 > 0.0 )
1391  && ( neighborMaximaDif_1_4 > 0.0 )
1392  && ( neighborMaximaDif_1_5 > 0.0 )
1393  && ( neighborMaximaDif_1_6 > 0.0 )
1394  && ( neighborMaximaDif_1_7 > 0.0 )
1395  && ( neighborMaximaDif_1_8 > 0.0 )
1396  && ( neighborMaximaDif_1_9 > 0.0 )
1397  )
1398  {
1399  neighborMaximaDif_2_1 = windowCenterPixelValue - currOctaveBuffersHandler[
1400  nextScaleIdx ][ 0 ][ prevResponseBufferColIdx ];
1401  neighborMaximaDif_2_2 = windowCenterPixelValue - currOctaveBuffersHandler[
1402  nextScaleIdx ][ 0 ][ windCenterCol ];
1403  neighborMaximaDif_2_3 = windowCenterPixelValue - currOctaveBuffersHandler[
1404  nextScaleIdx ][ 0 ][ nextResponseBufferColIdx ];
1405  neighborMaximaDif_2_4 = windowCenterPixelValue - currOctaveBuffersHandler[
1406  nextScaleIdx ][ 1 ][ prevResponseBufferColIdx ];
1407  neighborMaximaDif_2_5 = windowCenterPixelValue - currOctaveBuffersHandler[
1408  nextScaleIdx ][ 1 ][ windCenterCol ];
1409  neighborMaximaDif_2_6 = windowCenterPixelValue - currOctaveBuffersHandler[
1410  nextScaleIdx ][ 1 ][ nextResponseBufferColIdx ];
1411  neighborMaximaDif_2_7 = windowCenterPixelValue - currOctaveBuffersHandler[
1412  nextScaleIdx ][ 2 ][ prevResponseBufferColIdx];
1413  neighborMaximaDif_2_8 = windowCenterPixelValue - currOctaveBuffersHandler[
1414  nextScaleIdx ][ 2 ][ windCenterCol ];
1415  neighborMaximaDif_2_9 = windowCenterPixelValue - currOctaveBuffersHandler[
1416  nextScaleIdx ][ 2 ][ nextResponseBufferColIdx ];
1417 
1418  if(
1419  // verifying the next scale
1420  ( neighborMaximaDif_2_1 > 0.0 )
1421  && ( neighborMaximaDif_2_2 > 0.0 )
1422  && ( neighborMaximaDif_2_3 > 0.0 )
1423  && ( neighborMaximaDif_2_4 > 0.0 )
1424  && ( neighborMaximaDif_2_5 > 0.0 )
1425  && ( neighborMaximaDif_2_6 > 0.0 )
1426  && ( neighborMaximaDif_2_7 > 0.0 )
1427  && ( neighborMaximaDif_2_8 > 0.0 )
1428  && ( neighborMaximaDif_2_9 > 0.0 )
1429  && (
1430  maskRasterBufferPtr
1431  ?
1432  ( maskRasterBufferPtr[ 0 ][ windCenterCol ] != 0 )
1433  :
1434  true
1435  )
1436  )
1437  {
1438  auxInterestPoint.m_feature1 =
1439  neighborMaximaDif_0_1
1440  + neighborMaximaDif_0_2
1441  + neighborMaximaDif_0_3
1442  + neighborMaximaDif_0_4
1443  + neighborMaximaDif_0_5
1444  + neighborMaximaDif_0_6
1445  + neighborMaximaDif_0_7
1446  + neighborMaximaDif_0_8
1447  + neighborMaximaDif_1_1
1448  + neighborMaximaDif_1_2
1449  + neighborMaximaDif_1_3
1450  + neighborMaximaDif_1_4
1451  + neighborMaximaDif_1_5
1452  + neighborMaximaDif_1_6
1453  + neighborMaximaDif_1_7
1454  + neighborMaximaDif_1_8
1455  + neighborMaximaDif_1_9
1456  + neighborMaximaDif_2_1
1457  + neighborMaximaDif_2_2
1458  + neighborMaximaDif_2_3
1459  + neighborMaximaDif_2_4
1460  + neighborMaximaDif_2_5
1461  + neighborMaximaDif_2_6
1462  + neighborMaximaDif_2_7
1463  + neighborMaximaDif_2_8
1464  + neighborMaximaDif_2_9;
1465  auxInterestPoint.m_feature2 = (float)getSurfFilterSize(
1466  octaveIdx, scaleIdx );
1467  auxInterestPoint.m_feature3 = (float)
1468  laplacianSignBufferHandlers[ octaveIdx ][ scaleIdx ][
1469  1 ][ windCenterCol ] ;
1470 
1471  auxInterestPoint.m_x = windCenterCol;
1472  auxInterestPoint.m_y = rasterLine - maxGausFilterRadius - 1;
1473  assert( auxInterestPoint.m_x <
1474  paramsPtr->m_integralRasterDataPtr->getColumnsNumber() );
1475  assert( auxInterestPoint.m_y <
1476  paramsPtr->m_integralRasterDataPtr->getLinesNumber() );
1477 
1478  scaleGlobalIndex = ( octaveIdx *
1479  paramsPtr->m_scalesNumber ) + scaleIdx;
1480  subSectorIndex = ( ( auxInterestPoint.m_y /
1481  rowsBySubSector ) * tiePointsSubSectorsSplitFactor ) +
1482  ( auxInterestPoint.m_x / colsBySubSector );
1483  assert( scaleGlobalIndex < interestPointsSubSectors.size() );
1484  assert( subSectorIndex < interestPointsSubSectors[ scaleGlobalIndex ].size() );
1485 
1486  interestPointsSubSectors[ scaleGlobalIndex ][
1487  subSectorIndex ].insert( auxInterestPoint);
1488 
1489  if( interestPointsSubSectors[ scaleGlobalIndex ][
1490  subSectorIndex ].size() > maxInterestPointsByScaleSubSector )
1491  {
1492  interestPointsSubSectors[ scaleGlobalIndex ][
1493  subSectorIndex ].erase( interestPointsSubSectors[
1494  scaleGlobalIndex ][ subSectorIndex ].begin() );
1495  }
1496  }
1497  }
1498  }
1499  }
1500  }
1501  }
1502  }
1503  }
1504  }
1505  else
1506  {
1507  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1508  }
1509 
1510  // Copying the best found block maximas to the external maximas container
1511 
1512  paramsPtr->m_interestPointsAccessMutexPtr->lock();
1513 
1514  for( scaleGlobalIndex = 0 ; scaleGlobalIndex < interestPointsSubSectors.size() ;
1515  ++scaleGlobalIndex )
1516  {
1517  for( subSectorIndex = 0 ; subSectorIndex < interestPointsSubSectors[
1518  scaleGlobalIndex ].size() ; ++subSectorIndex )
1519  {
1520  double x, y;
1522  interestPointsSubSectors[ scaleGlobalIndex ][ subSectorIndex ], x, y ),
1523  "Duplicated tie-points" );
1524 
1525  paramsPtr->m_interestPointsSubSectorsPtr->operator[](
1526  subSectorIndex ).insert( interestPointsSubSectors[
1527  scaleGlobalIndex ][ subSectorIndex ].begin(),
1528  interestPointsSubSectors[ scaleGlobalIndex ][ subSectorIndex ].end() );
1529 
1530  while( paramsPtr->m_interestPointsSubSectorsPtr->operator[](
1531  subSectorIndex ).size() >
1532  maxInterestPointsBySubSector )
1533  {
1534  paramsPtr->m_interestPointsSubSectorsPtr->operator[](
1535  subSectorIndex ).erase(
1536  paramsPtr->m_interestPointsSubSectorsPtr->operator[](
1537  subSectorIndex ).begin() );
1538  }
1539  }
1540  }
1541 
1542  paramsPtr->m_interestPointsAccessMutexPtr->unlock();
1543  }
1544  }
1545 
1547  const InterestPointsSetT& interestPoints,
1548  const FloatsMatrix& integralRasterData,
1549  InterestPointsSetT& validInterestPoints,
1550  FloatsMatrix& features )
1551  {
1552  // Discovering the valid interest points
1553 
1554  validInterestPoints.clear();
1555 
1556  {
1557  InterestPointsSetT::const_iterator iPointsIt = interestPoints.begin();
1558  const InterestPointsSetT::const_iterator iPointsItEnd = interestPoints.end();
1559 
1560  while( iPointsIt != iPointsItEnd )
1561  {
1562  // Calculating the current interest point variables
1563 
1564  const unsigned int& currIPointCenterX = iPointsIt->m_x;
1565  const unsigned int& currIPointCenterY = iPointsIt->m_y;
1566  const float currIPointScale = 1.2f * iPointsIt->m_feature2 / 9.0f;
1567 
1568  unsigned int featureWindowWidth = (unsigned int)( 20.0 * currIPointScale );
1569  featureWindowWidth += ( ( featureWindowWidth % 2 ) ? 0 : 1 );
1570 
1571  const unsigned int feature90DegreeRotatedWindowRadius = (unsigned int)
1572  (
1573  std::ceil(
1574  std::sqrt(
1575  2.0
1576  *
1577  (
1578  ( (double)featureWindowWidth )
1579  *
1580  ( (double)featureWindowWidth )
1581  )
1582  )
1583  ) / 2.0
1584  );
1585 
1586  const unsigned int featureElementHaarWindowRadius =
1587  ((unsigned int)( 2.0 * currIPointScale )) / 2;
1588 
1589  const unsigned int currIPointCenterXAllowedMin = featureElementHaarWindowRadius +
1590  feature90DegreeRotatedWindowRadius + 1;
1591  const unsigned int currIPointCenterXAllowedMax = integralRasterData.getColumnsNumber() -
1592  currIPointCenterXAllowedMin - 1;
1593  const unsigned int currIPointCenterYAllowedMin = currIPointCenterXAllowedMin;
1594  const unsigned int currIPointCenterYAllowedMax = integralRasterData.getLinesNumber() -
1595  currIPointCenterXAllowedMin - 1;
1596 
1597  if( ( currIPointCenterX > currIPointCenterXAllowedMin ) &&
1598  ( currIPointCenterX < currIPointCenterXAllowedMax ) &&
1599  ( currIPointCenterY > currIPointCenterYAllowedMin ) &&
1600  ( currIPointCenterY < currIPointCenterYAllowedMax ) )
1601 
1602  {
1603  validInterestPoints.insert( *iPointsIt );
1604  }
1605 
1606  ++iPointsIt;
1607  }
1608  }
1609 
1610  TERP_TRUE_OR_RETURN_FALSE(features.reset(static_cast<unsigned int>(validInterestPoints.size()), 128),
1611  "Cannot allocate features matrix" );
1612 
1613  // globals
1614 
1615  float auxFeaturesBuffer[ 128 ];
1616 
1617  // iterating over each input innterest point
1618 
1619  InterestPointsSetT::const_iterator iPointsIt = validInterestPoints.begin();
1620  const InterestPointsSetT::const_iterator iPointsItEnd = validInterestPoints.end();
1621  unsigned int interestPointIdx = 0;
1622  while( iPointsIt != iPointsItEnd )
1623  {
1624  // Calculating the current interest point variables
1625 
1626  const unsigned int& currIPointCenterX = iPointsIt->m_x;
1627  const unsigned int& currIPointCenterY = iPointsIt->m_y;
1628  const float currIPointScale = 1.2f * iPointsIt->m_feature2 / 9.0f;
1629 
1630  unsigned int featureWindowWidth = (unsigned int)( 20.0 * currIPointScale );
1631  featureWindowWidth += ( ( featureWindowWidth % 2 ) ? 0 : 1 );
1632 
1633  const unsigned int featureWindowRadius = featureWindowWidth / 2;
1634  const float featureWindowRadiusDouble = (float)featureWindowRadius;
1635 
1636  const unsigned int featureSubWindowWidth = featureWindowWidth / 4;
1637 
1638  const unsigned int featureElementHaarWindowRadius =
1639  ((unsigned int)( 2.0 * currIPointScale )) / 2;
1640 
1641  const unsigned int featureWindowRasterXStart = currIPointCenterX -
1642  featureWindowRadius;
1643  const unsigned int featureWindowRasterYStart = currIPointCenterY -
1644  featureWindowRadius;
1645 
1646  // Initiating the features vector
1647 
1648  unsigned int currentFeaturePtrStartIdx = 0;
1649 
1650  for( currentFeaturePtrStartIdx = 0; currentFeaturePtrStartIdx < 128 ;
1651  ++currentFeaturePtrStartIdx )
1652  auxFeaturesBuffer[ currentFeaturePtrStartIdx ] = 0.0;
1653 
1654  // Estimating the intensity vectors
1655 
1656  assert( ((long int)currIPointCenterX) -
1657  ((long int)featureWindowRadius) >= 0 );
1658  assert( ((long int)currIPointCenterY) -
1659  ((long int)featureWindowRadius) >= 0 );
1660  assert( currIPointCenterX +
1661  featureWindowRadius < integralRasterData.getColumnsNumber() );
1662  assert( currIPointCenterY +
1663  featureWindowRadius < integralRasterData.getLinesNumber() );
1664 
1665  const float currIPointXIntensity = getHaarXVectorIntensity( integralRasterData, currIPointCenterX,
1666  currIPointCenterY, featureWindowRadius );
1667  const float currIPointYIntensity = getHaarYVectorIntensity( integralRasterData, currIPointCenterX,
1668  currIPointCenterY, featureWindowRadius );
1669 
1670  // Calculating the rotation parameters
1671 
1672  const float currIPointRotationNorm = std::sqrt( ( currIPointXIntensity * currIPointXIntensity ) +
1673  ( currIPointYIntensity * currIPointYIntensity ) );
1674 
1675  float currIPointRotationSin = 0; // default: no rotation
1676  float currIPointRotationCos = 1.0; // default: no rotation
1677 
1678  if( currIPointRotationNorm != 0.0 )
1679  {
1680  currIPointRotationCos = currIPointXIntensity / currIPointRotationNorm;
1681  currIPointRotationSin = currIPointYIntensity / currIPointRotationNorm;
1682  }
1683 
1684  assert( ( currIPointRotationCos >= -1.0 ) && ( currIPointRotationCos <= 1.0 ) );
1685  assert( ( currIPointRotationSin >= -1.0 ) && ( currIPointRotationSin <= 1.0 ) );
1686 
1687 // std::cout << "angle:";
1688 // std::cout << std::atan2( currIPointRotationSin, currIPointRotationCos ) * 180.0 / M_PI << std::endl;
1689 
1690  /* The region surrounding the interest point is split up regularly
1691  into smaller 44 square rotated by the haar intensity vectors
1692  calculated above
1693 
1694  counterclockwise rotation
1695  | u | |cos -sin| |X|
1696  | v | == |sin cos| x |Y|
1697 
1698  clockwise rotation
1699  | u | |cos sin| |X|
1700  | v | == |-sin cos| x |Y|
1701  */
1702 
1703  unsigned int featureWindowYOffset = 0;
1704  unsigned int featureWindowXOffset = 0;
1705  float featureElementZeroCenteredOriginalXIdx = 0;
1706  float featureElementZeroCenteredOriginalYIdx = 0;
1707  float featureElementZeroCenteredRotatedXIdx = 0;
1708  float featureElementZeroCenteredRotatedYIdx = 0;
1709  float featureElementRotatedXIdx = 0;
1710  float featureElementRotatedYIdx = 0;
1711  unsigned int featureElementRasterRotatedXIdx = 0;
1712  unsigned int featureElementRasterRotatedYIdx = 0;
1713  float featureElementOriginalHaarXIntensity = 0;
1714  float featureElementOriginalHaarYIntensity = 0;
1715  float featureElementZeroCenteredOriginalHaarXIntensity = 0;
1716  float featureElementZeroCenteredOriginalHaarYIntensity = 0;
1717  float featureElementRotatedHaarXIntensity = 0;
1718  float featureElementRotatedHaarYIntensity = 0;
1719  float featureElementZeroCenteredRotatedHaarXIntensity = 0;
1720  float featureElementZeroCenteredRotatedHaarYIntensity = 0;
1721  unsigned int featureSubWindowYIdx = 0;
1722  unsigned int featureSubWindowXIdx = 0;
1723 
1724  for( featureWindowYOffset = 0 ; featureWindowYOffset < featureWindowWidth ;
1725  featureWindowYOffset += 5 )
1726  {
1727  featureElementZeroCenteredOriginalYIdx = ((float)featureWindowYOffset)
1728  - featureWindowRadiusDouble;
1729 
1730  featureSubWindowYIdx = featureWindowYOffset / featureSubWindowWidth;
1731 
1732  for( featureWindowXOffset = 0 ; featureWindowXOffset < featureWindowWidth ;
1733  featureWindowXOffset += 5 )
1734  {
1735  featureSubWindowXIdx = featureWindowXOffset / featureSubWindowWidth;
1736 
1737  currentFeaturePtrStartIdx = ( featureSubWindowYIdx * 4 ) +
1738  featureSubWindowXIdx;
1739 
1740  featureElementZeroCenteredOriginalXIdx = ((float)featureWindowXOffset)
1741  - featureWindowRadiusDouble;
1742 
1743  /* finding the correspondent point over the original raster
1744  using a clockwize rotation */
1745 
1746  featureElementZeroCenteredRotatedXIdx =
1747  ( currIPointRotationCos * featureElementZeroCenteredOriginalXIdx ) +
1748  ( currIPointRotationSin * featureElementZeroCenteredOriginalYIdx );
1749  featureElementZeroCenteredRotatedYIdx =
1750  ( currIPointRotationCos * featureElementZeroCenteredOriginalYIdx )
1751  - ( currIPointRotationSin * featureElementZeroCenteredOriginalXIdx );
1752 
1753  featureElementRotatedXIdx = featureElementZeroCenteredRotatedXIdx +
1754  featureWindowRadiusDouble;
1755  featureElementRotatedYIdx = featureElementZeroCenteredRotatedYIdx +
1756  featureWindowRadiusDouble;
1757 
1758  featureElementRasterRotatedXIdx = featureWindowRasterXStart +
1759  (unsigned int)te::common::Round< float, unsigned int >( featureElementRotatedXIdx );
1760  featureElementRasterRotatedYIdx = featureWindowRasterYStart +
1761  (unsigned int)te::common::Round< float, unsigned int >( featureElementRotatedYIdx );
1762 
1763  assert( ((long int)featureElementRasterRotatedXIdx) -
1764  ((long int)featureElementHaarWindowRadius) >= 0 );
1765  assert( ((long int)featureElementRasterRotatedYIdx) -
1766  ((long int)featureElementHaarWindowRadius) >= 0 );
1767  assert( featureElementRasterRotatedXIdx +
1768  featureElementHaarWindowRadius < integralRasterData.getColumnsNumber() );
1769  assert( featureElementRasterRotatedYIdx +
1770  featureElementHaarWindowRadius < integralRasterData.getLinesNumber() );
1771 
1772  // Finding the original haar intesity vectors
1773 
1774  featureElementOriginalHaarXIntensity = getHaarXVectorIntensity( integralRasterData,
1775  featureElementRasterRotatedXIdx, featureElementRasterRotatedYIdx,
1776  featureElementHaarWindowRadius );
1777  featureElementOriginalHaarYIntensity = getHaarYVectorIntensity( integralRasterData,
1778  featureElementRasterRotatedXIdx, featureElementRasterRotatedYIdx,
1779  featureElementHaarWindowRadius );
1780 
1781  // Rotating the intensities by the central point haar intensities vectors
1782  // usigng a counterclockwise rotation
1783 
1784  featureElementZeroCenteredOriginalHaarXIntensity = featureElementOriginalHaarXIntensity +
1785  featureElementZeroCenteredOriginalXIdx;
1786  featureElementZeroCenteredOriginalHaarYIntensity = featureElementOriginalHaarYIntensity +
1787  featureElementZeroCenteredOriginalYIdx;
1788 
1789  featureElementZeroCenteredRotatedHaarXIntensity =
1790  ( currIPointRotationCos * featureElementZeroCenteredOriginalHaarXIntensity ) +
1791  ( currIPointRotationSin * featureElementZeroCenteredOriginalHaarYIntensity );
1792  featureElementZeroCenteredRotatedHaarYIntensity =
1793  ( currIPointRotationCos * featureElementZeroCenteredOriginalHaarYIntensity )
1794  - ( currIPointRotationSin * featureElementZeroCenteredOriginalHaarXIntensity );
1795 
1796  featureElementRotatedHaarXIntensity = featureElementZeroCenteredRotatedHaarXIntensity
1797  - featureElementZeroCenteredRotatedXIdx;
1798  featureElementRotatedHaarYIntensity = featureElementZeroCenteredRotatedHaarYIntensity
1799  - featureElementZeroCenteredRotatedYIdx;
1800 
1801  // Generating the related portion inside the output features vector
1802 
1803  assert( currentFeaturePtrStartIdx < 121 );
1804 
1805  auxFeaturesBuffer[ currentFeaturePtrStartIdx ] +=
1806  featureElementRotatedHaarXIntensity;
1807  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 1 ] +=
1808  featureElementRotatedHaarYIntensity;
1809  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 2 ] +=
1810  std::abs( featureElementRotatedHaarXIntensity );
1811  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 3 ] +=
1812  std::abs( featureElementRotatedHaarYIntensity );
1813  if( featureElementRotatedHaarXIntensity < 0.0 )
1814  {
1815  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 4 ] +=
1816  featureElementRotatedHaarXIntensity;
1817  }
1818  else
1819  {
1820  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 5 ] +=
1821  featureElementRotatedHaarXIntensity;
1822  }
1823  if( featureElementRotatedHaarYIntensity < 0.0 )
1824  {
1825  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 6 ] +=
1826  featureElementRotatedHaarYIntensity;
1827  }
1828  else
1829  {
1830  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 7 ] +=
1831  featureElementRotatedHaarYIntensity;
1832  }
1833  }
1834  }
1835 
1836  // turning the descriptor into a unit vector.(Invariance to contrast)
1837 
1838  float* currentFeaturePtr = features[ interestPointIdx ];
1839 
1840  float featureElementsNormalizeFactor = 0.0;
1841 
1842  for( currentFeaturePtrStartIdx = 0 ; currentFeaturePtrStartIdx < 128 ;
1843  ++currentFeaturePtrStartIdx )
1844  {
1845  featureElementsNormalizeFactor += ( auxFeaturesBuffer[ currentFeaturePtrStartIdx ]
1846  * auxFeaturesBuffer[ currentFeaturePtrStartIdx ] );
1847  }
1848 
1849  featureElementsNormalizeFactor = std::sqrt( featureElementsNormalizeFactor );
1850 
1851  if( featureElementsNormalizeFactor != 0.0 )
1852  {
1853  featureElementsNormalizeFactor = 1.0f / featureElementsNormalizeFactor;
1854  }
1855 
1856  for( currentFeaturePtrStartIdx = 0 ; currentFeaturePtrStartIdx < 128 ;
1857  ++currentFeaturePtrStartIdx )
1858  {
1859  currentFeaturePtr[ currentFeaturePtrStartIdx ] = (
1860  auxFeaturesBuffer[ currentFeaturePtrStartIdx ] *
1861  featureElementsNormalizeFactor );
1862  TERP_DEBUG_TRUE_OR_THROW( ( currentFeaturePtr[ currentFeaturePtrStartIdx ] <= 1.0 ),
1863  currentFeaturePtr[ currentFeaturePtrStartIdx ] );
1864  TERP_DEBUG_TRUE_OR_THROW( ( currentFeaturePtr[ currentFeaturePtrStartIdx ] >= -1.0 ),
1865  currentFeaturePtr[ currentFeaturePtrStartIdx ] );
1866  }
1867 
1868  ++interestPointIdx;
1869  ++iPointsIt;
1870  }
1871 
1872  return true;
1873  }
1874 
1876  const FloatsMatrix& featuresSet1,
1877  const FloatsMatrix& featuresSet2,
1878  const InterestPointsSetT& interestPointsSet1,
1879  const InterestPointsSetT& interestPointsSet2,
1880  te::gm::GeometricTransformation const * const raster1ToRaster2TransfPtr,
1881  const double raster1ToRaster2TransfDMapError,
1882  MatchedInterestPointsSetT& matchedPoints )
1883  {
1884  assert( featuresSet1.getColumnsNumber() == featuresSet2.getColumnsNumber() );
1885 
1886  matchedPoints.clear();
1887 
1888  const double maxEuclideanDist = ((Parameters*)m_inputParameters.getSpecStrategyParams())->m_surfMaxNormEuclideanDist
1889  * 2.0; /* since surf feature vectors are unitary verctors */
1890 
1891  const unsigned int interestPointsSet1Size = static_cast<unsigned int>(interestPointsSet1.size());
1892  if( interestPointsSet1Size == 0 ) return true;
1893 
1894  const unsigned int interestPointsSet2Size = static_cast<unsigned int>(interestPointsSet2.size());
1895  if( interestPointsSet2Size == 0 ) return true;
1896 
1897  assert( featuresSet1.getColumnsNumber() == featuresSet2.getColumnsNumber() );
1898  assert( featuresSet1.getLinesNumber() == interestPointsSet1Size );
1899  assert( featuresSet2.getLinesNumber() == interestPointsSet2Size );
1900 
1901  // Creating internal objects
1902 
1903  InterestPointsSetT::const_iterator it1 = interestPointsSet1.begin();
1904  boost::scoped_array< InterestPointT > internalInterestPointsSet1(
1905  new InterestPointT[ interestPointsSet1Size ] );
1906  for( unsigned int idx1 = 0 ; idx1 < interestPointsSet1Size ; ++idx1 )
1907  {
1908  internalInterestPointsSet1[ idx1 ] = *it1;
1909  ++it1;
1910  }
1911 
1912  InterestPointsSetT::const_iterator it2 = interestPointsSet2.begin();
1913  boost::scoped_array< InterestPointT > internalInterestPointsSet2(
1914  new InterestPointT[ interestPointsSet2Size ] );
1915  for( unsigned int idx2 = 0 ; idx2 < interestPointsSet2Size ; ++idx2 )
1916  {
1917  internalInterestPointsSet2[ idx2 ] = *it2;
1918  ++it2;
1919  }
1920 
1921  // Creating the distances matrix
1922 
1923  FloatsMatrix distMatrix;
1924  TERP_INSTANCE_TRUE_OR_RETURN_FALSE( distMatrix.reset( interestPointsSet1Size,
1925  interestPointsSet2Size, FloatsMatrix::RAMMemPol ),
1926  "Error crearting the correlation matrix" );
1927 
1928  unsigned int col = 0;
1929  unsigned int line = 0;
1930  float* linePtr = nullptr;
1931 
1932  for( line = 0 ; line < interestPointsSet1Size ; ++line )
1933  {
1934  linePtr = distMatrix[ line ];
1935 
1936  for( col = 0 ; col < interestPointsSet2Size ; ++col )
1937  {
1938  linePtr[ col ] = std::numeric_limits< float >::max();
1939  }
1940  }
1941 
1942  // Getting distances
1943 
1944  boost::mutex syncMutex;
1945  unsigned int nextFeatureIdx1ToProcess = 0;
1946 
1948  params.m_featuresSet1Ptr = &featuresSet1;
1949  params.m_featuresSet2Ptr = &featuresSet2;
1950  params.m_interestPointsSet1Ptr = internalInterestPointsSet1.get();
1951  params.m_interestPointsSet2Ptr = internalInterestPointsSet2.get();
1952  params.m_nextFeatureIdx1ToProcessPtr = &nextFeatureIdx1ToProcess;
1953  params.m_distMatrixPtr = &distMatrix;
1954  params.m_syncMutexPtr = &syncMutex;
1955  params.m_raster1ToRaster2TransfPtr = raster1ToRaster2TransfPtr;
1956  params.m_searchOptTreeSearchRadius = raster1ToRaster2TransfDMapError;
1957 
1959  {
1961  FloatsMatrix::RAMMemPol, "Invalid memory policy" )
1963  FloatsMatrix::RAMMemPol, "Invalid memory policy" )
1964 
1965  const unsigned int procsNumber = te::common::GetPhysProcNumber();
1966 
1967  boost::thread_group threads;
1968 
1969  for( unsigned int threadIdx = 0 ; threadIdx < procsNumber ;
1970  ++threadIdx )
1971  {
1972  threads.add_thread( new boost::thread(
1974  }
1975 
1976  threads.join_all();
1977 
1978  }
1979  else
1980  {
1982  }
1983 
1984  // finding the distances matrix minimum for each line and column
1985 
1986  std::vector< float > eachLineMinValues( interestPointsSet1Size,
1987  FLT_MAX );
1988  std::vector< unsigned int > eachLineMinIndexes( interestPointsSet1Size,
1989  interestPointsSet2Size );
1990  std::vector< float > eachColMinValues( interestPointsSet2Size,
1991  FLT_MAX );
1992  std::vector< unsigned int > eachColMinIndexes( interestPointsSet2Size,
1993  interestPointsSet1Size );
1994 
1995  for( line = 0 ; line < interestPointsSet1Size ; ++line )
1996  {
1997  linePtr = distMatrix[ line ];
1998 
1999  for( col = 0 ; col < interestPointsSet2Size ; ++col )
2000  {
2001  const float& value = linePtr[ col ];
2002 
2003  if( value <= maxEuclideanDist )
2004  {
2005  if( value < eachLineMinValues[ line ] )
2006  {
2007  eachLineMinValues[ line ] = value;
2008  eachLineMinIndexes[ line ] = col;
2009  }
2010 
2011  if( value < eachColMinValues[ col ] )
2012  {
2013  eachColMinValues[ col ] = value;
2014  eachColMinIndexes[ col ] = line;
2015  }
2016  }
2017  }
2018  }
2019 
2020  // Finding tiepoints
2021 
2022  MatchedInterestPointsT auxMatchedPoints;
2023 
2024  for( line = 0 ; line < interestPointsSet1Size ; ++line )
2025  {
2026  col = eachLineMinIndexes[ line ];
2027 
2028  if( ( col < interestPointsSet2Size ) &&
2029  ( eachColMinIndexes[ col ] == line ) )
2030  {
2031  auxMatchedPoints.m_point1 = internalInterestPointsSet1[ line ];
2032  auxMatchedPoints.m_point2 = internalInterestPointsSet2[ col ],
2033  auxMatchedPoints.m_feature = distMatrix( line, col );
2034 
2035  matchedPoints.insert( auxMatchedPoints );
2036  }
2037  }
2038 
2039  return true;
2040  }
2041 
2044  {
2045  assert( paramsPtr->m_featuresSet1Ptr->getMemPolicy() ==
2047  assert( paramsPtr->m_featuresSet2Ptr->getMemPolicy() ==
2049  assert( paramsPtr->m_distMatrixPtr->getMemPolicy() ==
2051  assert( paramsPtr->m_featuresSet1Ptr->getColumnsNumber() ==
2052  paramsPtr->m_featuresSet2Ptr->getColumnsNumber() );
2053 
2054  // Globals
2055 
2056  const double interestPointsSet2RTreeSearchRadius = paramsPtr->m_searchOptTreeSearchRadius;
2057  const unsigned int featureElementsNmb = paramsPtr->m_featuresSet1Ptr->getColumnsNumber();
2058  unsigned int feat2Idx = 0;
2059  float const* feat1Ptr = nullptr;
2060  float const* feat2Ptr = nullptr;
2061  float* corrMatrixLinePtr = nullptr;
2062  unsigned int featCol = 0;
2063  te::gm::Envelope auxEnvelope;
2064  float diff = 0;
2065  float euclideanDist = 0;
2066 
2067  // local transformation copy
2068 
2069  std::unique_ptr< te::gm::GeometricTransformation > raster1ToRaster2TransfPtr;
2070  if( paramsPtr->m_raster1ToRaster2TransfPtr )
2071  {
2072  paramsPtr->m_syncMutexPtr->lock();
2073  raster1ToRaster2TransfPtr.reset( paramsPtr->m_raster1ToRaster2TransfPtr->clone() );
2074  paramsPtr->m_syncMutexPtr->unlock();
2075  }
2076 
2077  // initializing the features 2 indexing
2078 
2079  const unsigned int featuresSet1Size =
2080  paramsPtr->m_featuresSet1Ptr->getLinesNumber();
2081  const unsigned int featuresSet2Size =
2082  paramsPtr->m_featuresSet2Ptr->getLinesNumber();
2083 
2084  te::sam::rtree::Index< unsigned int > interestPointsSet2RTree;
2085 
2086  std::vector< unsigned int > selectedFeaturesSet2Indexes;
2087  unsigned int selectedFeaturesSet2IndexesSize = 0;
2088 
2089  if( paramsPtr->m_raster1ToRaster2TransfPtr )
2090  {
2091  for( unsigned int feat2Idx = 0 ; feat2Idx < featuresSet2Size ; ++feat2Idx )
2092  {
2093  interestPointsSet2RTree.insert(
2095  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_x,
2096  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_y,
2097  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_x,
2098  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_y ),
2099  feat2Idx );
2100  }
2101  }
2102  else
2103  {
2104  selectedFeaturesSet2Indexes.resize( featuresSet2Size );
2105  selectedFeaturesSet2IndexesSize = featuresSet2Size;
2106  for( unsigned int feat2Idx = 0 ; feat2Idx < featuresSet2Size ; ++feat2Idx )
2107  {
2108  selectedFeaturesSet2Indexes[ feat2Idx ] = feat2Idx;
2109  }
2110  }
2111 
2112  // Analysing each feature
2113 
2114  for( unsigned int feat1Idx = 0 ; feat1Idx < featuresSet1Size ; ++feat1Idx )
2115  {
2116  paramsPtr->m_syncMutexPtr->lock();
2117 
2118  if( feat1Idx == (*paramsPtr->m_nextFeatureIdx1ToProcessPtr) )
2119  {
2120  ++(*paramsPtr->m_nextFeatureIdx1ToProcessPtr);
2121 
2122  paramsPtr->m_syncMutexPtr->unlock();
2123 
2124  if( paramsPtr->m_raster1ToRaster2TransfPtr )
2125  {
2126  raster1ToRaster2TransfPtr->directMap(
2127  paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_x,
2128  paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_y,
2129  auxEnvelope.m_llx,
2130  auxEnvelope.m_lly );
2131 
2132  auxEnvelope.m_urx = auxEnvelope.m_llx;
2133  auxEnvelope.m_ury = auxEnvelope.m_lly;
2134 
2135  auxEnvelope.m_llx -= interestPointsSet2RTreeSearchRadius;
2136  auxEnvelope.m_lly -= interestPointsSet2RTreeSearchRadius;
2137  auxEnvelope.m_urx += interestPointsSet2RTreeSearchRadius;
2138  auxEnvelope.m_ury += interestPointsSet2RTreeSearchRadius;
2139 
2140  selectedFeaturesSet2Indexes.clear();
2141  interestPointsSet2RTree.search( auxEnvelope,
2142  selectedFeaturesSet2Indexes );
2143 
2144  selectedFeaturesSet2IndexesSize = static_cast<unsigned int>(selectedFeaturesSet2Indexes.size());
2145  }
2146 
2147  corrMatrixLinePtr = paramsPtr->m_distMatrixPtr->operator[]( feat1Idx );
2148 
2149  feat1Ptr = paramsPtr->m_featuresSet1Ptr->operator[]( feat1Idx );
2150 
2151  for( unsigned int selectedFeaturesSet2IndexesIdx = 0 ;
2152  selectedFeaturesSet2IndexesIdx < selectedFeaturesSet2IndexesSize ;
2153  ++selectedFeaturesSet2IndexesIdx )
2154  {
2155  feat2Idx = selectedFeaturesSet2Indexes[ selectedFeaturesSet2IndexesIdx ];
2156 
2157  if(
2158  ( paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_feature2 ==
2159  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_feature2 )
2160  &&
2161  ( paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_feature3 ==
2162  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_feature3 )
2163  )
2164  {
2165  feat2Ptr = paramsPtr->m_featuresSet2Ptr->operator[]( feat2Idx );
2166 
2167  euclideanDist = 0.0;
2168 
2169  for( featCol = 0 ; featCol < featureElementsNmb ; ++featCol )
2170  {
2171  diff = feat1Ptr[ featCol ] - feat2Ptr[ featCol ];
2172  euclideanDist += ( diff * diff );
2173  }
2174 
2175  euclideanDist = std::sqrt( euclideanDist );
2176 
2177  corrMatrixLinePtr[ feat2Idx ] = euclideanDist;
2178  }
2179  }
2180  }
2181  else
2182  {
2183  paramsPtr->m_syncMutexPtr->unlock();
2184  }
2185  }
2186  }
2187 
2188  /* ----------------------------------------------------------------------- */
2189 
2191  : te::rp::TiePointsLocatorStrategyFactory( "SURF" )
2192  {
2193  }
2194 
2197 
2199  {
2201  }
2202 
2203  } // end namespace rp
2204 } // end namespace te
2205 
static bool createIntegralImage(const FloatsMatrix &inputData, FloatsMatrix &outputData)
Create an integral image.
AbstractParameters * clone() const
Create a clone copy of this instance.
void getSubSampledSpecStrategyParams(const double subSampleOptimizationRescaleFactor, const TiePointsLocatorStrategyParameters &inputSpecParams, std::unique_ptr< TiePointsLocatorStrategyParameters > &subSampledSpecParamsPtr) const
Returns a sub-sampled version of the given locator strategy specific input parameters.
TECOMMONEXPORT unsigned long long int GetTotalVirtualMemory()
Returns the amount of total virtual memory (bytes) that can be claimed by the current process (physic...
SURF tie-points locator strategy factory.
static float getSurfDxyDerivative(float **bufferPtr, const unsigned int &centerX, const unsigned int &centerY, const unsigned int &lobeWidth)
Return a SURF box filter Dxy derivative centered over the given position from the given integral imag...
void reset()
Clear all internal allocated resources and go back to the initial not-initialized state...
std::vector< unsigned int > m_inRaster2Bands
Bands to be used from the input raster 2.
unsigned int m_surfScalesNumber
The number of sub-sampling scales to generate, when applicable (default:3, minimum:3).
bool m_enableProgress
Enable/Disable the progress interface (default:false).
unsigned int m_raster2TargetAreaLineStart
The first line of the raster 2 target area to process (default:0 - The entire raster will be consider...
te::gm::GeometricTransformation const * m_raster1ToRaster2TransfPtr
A pointer to a transformation direct mapping raster 1 indexed coords into raster 2 indexed coords...
A class that represents an R-tree.
Base exception class for plugin module.
TiePointsLocatorStrategyParameters const * getSpecStrategyParams() const
Returns a pointer to the internal specific tie-points locator strategy parameters.
double m_subSampleOptimizationRescaleFactor
Sub-sampled optimization tie-points search rescale factor (Tie-ponts will be searched into a subsabmp...
te::rst::Raster const * m_inRaster2Ptr
Input raster 2.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
unsigned int m_tiePointsSubSectorsSplitFactor
The number of sectors along each direction.
double m_urx
Upper right corner x-coordinate.
TiePointsLocator SURF strategy parameters.
2D Geometric transformation base class.
Tie-Pointsr locator SURF strategy.
static float getSurfDyyDerivative(float **bufferPtr, const unsigned int &centerX, const unsigned int &centerY, const unsigned int &lobeWidth, const unsigned int &lobeRadius)
Return a SURF box filter Dxx derivative centered over the given position from the given integral imag...
unsigned int m_processingBlocksNumber
The raster data will be splitted into this number of blocks for processing.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
unsigned int m_maxTiePoints
The maximum number of tie-points to generate (0:Automatically calculated, default:2500).
MemoryPolicy getMemPolicy() const
Returns the current memory policy.
Definition: Matrix.h:837
#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:185
unsigned int line
unsigned int m_octavesNumber
The number of octaves to generate (minimum:1).
std::vector< InterestPointsSetT > * m_interestPointsSubSectorsPtr
A pointer to a valid interest points container (one element by subsector)..
static unsigned int getSurfOctaveBaseFilterSize(const unsigned int &octaveIndex)
Return the surf octave base filter size (width).
unsigned int unsigned int nCols
TECOMMONEXPORT unsigned int GetPhysProcNumber()
Returns the number of physical processors.
unsigned int m_raster1TargetAreaHeight
The raster 1 target area height (default:0 - The entire raster will be considered).
boost::mutex * m_rastaDataAccessMutexPtr
A pointer to a valid mutex to controle raster data access.
double m_llx
Lower left corner x-coordinate.
An Envelope defines a 2D rectangular region.
static unsigned int getSurfFilterSize(const unsigned int &octaveIndex, const unsigned int &scaleIndex)
Return the surf octave filter size (width).
double m_pixelSizeXRelation
The pixel resolution relation m_pixelSizeXRelation = raster1_pixel_res_x / raster2_pixel_res_x (defau...
te::rp::TiePointsLocatorInputParameters m_inputParameters
Input parameters.
The parameters passed to the executeMatchingByEuclideanDistThreadEntry method.
static bool generateSurfFeatures(const InterestPointsSetT &interestPoints, const FloatsMatrix &integralRasterData, InterestPointsSetT &validInterestPoints, FloatsMatrix &features)
Generate a Surf features matrix for the given interes points.
unsigned int getColumnsNumber() const
The number of current matrix columns.
Definition: Matrix.h:798
unsigned int m_surfOctavesNumber
The number of octaves to generate, when applicable (default: 2, minimum:2).
std::vector< unsigned int > m_inRaster1Bands
Bands to be used from the input raster 1.
mydialect insert("+", new te::da::BinaryOpEncoder("+"))
virtual void reset()
Clear all internal allocated resources and go back to the initial not-initialized state...
URI C++ Library.
Definition: Attributes.h:37
std::multiset< InterestPointT > InterestPointsSetT
bool getMatchedInterestPoints(te::gm::GeometricTransformation const *const raster1ToRaster2TransfPtr, const double raster1ToRaster2TransfDMapError, MatchedInterestPointsSetT &matchedInterestPoints)
Try to find matched interest points.
int search(const te::gm::Envelope &mbr, std::vector< DATATYPE > &report) const
Range search query.
static void executeMatchingByEuclideanDistThreadEntry(ExecuteMatchingByEuclideanDistThreadEntryParams *paramsPtr)
Correlation/Euclidean match thread entry.
unsigned int m_tiePointsSubSectorsSplitFactor
The algorithm will try to generate tie-points distributed over image sectors ( Default: 3 - 3x3 sub-s...
virtual GeometricTransformation * clone() const =0
Creat a clone copy of this instance.
static bool loadRasterData(te::rst::Raster const *rasterPtr, const std::vector< unsigned int > &rasterBands, te::rst::Raster const *maskRasterPtr, const unsigned int maskRasterBand, const unsigned int rasterTargetAreaLineStart, const unsigned int rasterTargetAreaColStart, const unsigned int rasterTargetAreaWidth, const unsigned int rasterTargetAreaHeight, const double desiredRescaleFactorX, const double desiredRescaleFactorY, const te::rst::Interpolator::Method rasterInterpMethod, const unsigned char maxMemPercentUsage, std::vector< boost::shared_ptr< FloatsMatrix > > &loadedRasterData, UCharsMatrix &loadedMaskRasterData, double &achievedRescaleFactorX, double &achievedRescaleFactorY)
Load rasters data (normalized between 0 and 1).
FloatsMatrix const * m_integralRasterDataPtr
The integral image raster data.
void reset()
Reset (clear) the active instance data.
Definition: Matrix.h:502
Tie-points locator SURF strategy.
Tie-points locator strategy.
te::rst::Raster const * m_inRaster1Ptr
Input raster 1.
double m_lly
Lower left corner y-coordinate.
void getDefaultSpecStrategyParams(std::unique_ptr< TiePointsLocatorStrategyParameters > &defaultSpecParamsPtr) const
Returns a sub-sampled version of the given locator strategy specific input parameters.
te::rp::TiePointsLocatorStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
TECOMMONEXPORT unsigned long long int GetTotalPhysicalMemory()
Returns the amount of total physical memory (bytes).
Abstract parameters base interface.
static void roolUpBuffer(BufferElementT **bufferPtr, const unsigned int &bufferLinesNumber)
RoolUp a buffer of lines.
unsigned int m_raster1TargetAreaWidth
The raster 1 target area width (default:0 - The entire raster will be considered).
The parameters passed to the surfLocatorThreadEntry method.
double m_pixelSizeYRelation
The pixel resolution relation m_pixelSizeYRelation = raster1_pixel_res_y / raster2_pixel_res_y (defau...
unsigned int m_raster1TargetAreaLineStart
The first line of the raster 1 target area to process (default:0 - The entire raster will be consider...
void insert(const te::gm::Envelope &mbr, const DATATYPE &data)
It inserts an item into the tree.
double m_ury
Upper right corner y-coordinate.
unsigned int m_raster2TargetAreaColStart
The first column of the raster 2 target area to process (default:0 - The entire raster will be consid...
float m_feature3
Interest point feature 3 value.
UCharsMatrix const * m_maskRasterDataPtr
The loaded mask raster data pointer (or zero if no mask is avaliable).
unsigned int m_raster2TargetAreaHeight
The raster 2 target area height (default:0 - The entire raster will be considered).
bool m_enableMultiThread
Enable/Disable the use of multi-threads (default:true).
bool executeMatchingByEuclideanDist(const FloatsMatrix &featuresSet1, const FloatsMatrix &featuresSet2, const InterestPointsSetT &interestPointsSet1, const InterestPointsSetT &interestPointsSet2, te::gm::GeometricTransformation const *const raster1ToRaster2TransfPtr, const double raster1ToRaster2TransfDMapError, MatchedInterestPointsSetT &matchedPoints)
Match each feature using eucliean distance.
A generic template matrix.
Definition: Matrix.h:55
TemplateElementType ElementTypeT
Public matrix element type definition.
Definition: Matrix.h:61
te::rst::Raster const * m_inMaskRaster1Ptr
Optional one band input mask raster 1 (tie-points will not be generated inside mask image areas marke...
te::rst::Raster const * m_inMaskRaster2Ptr
Optional one band input mask raster 2 (tie-points will not be generated inside mask image areas marke...
float m_feature2
Interest point feature 2 value.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
bool initialize(const te::rp::TiePointsLocatorInputParameters &inputParameters)
Initialize the strategy.
const Parameters & operator=(const Parameters &params)
static void locateSurfInterestPointsThreadEntry(SurfLocatorThreadParams *paramsPtr)
Surf locator thread entry.
Raster tie-points locator strategy factory base class.
boost::mutex * m_interestPointsAccessMutexPtr
A pointer to a valid mutex to control the output interest points container access.
#define TERP_DEBUG_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:400
TECOMMONEXPORT unsigned long long int GetUsedVirtualMemory()
Returns the amount of used virtual memory (bytes) for the current process (physical + swapped)...
bool locateSurfInterestPoints(const unsigned int maxInterestPoints, const FloatsMatrix &integralRasterData, UCharsMatrix const *maskRasterDataPtr, InterestPointsSetT &interestPoints) const
SURF interest points locator.
unsigned int m_maxInterestPointsBySubSector
The maximum number of interest points by sub-sector.
bool m_isInitialized
true if this instance is initialized.
unsigned int getAutoMaxTiePointsNumber() const
Returns a automatically calculated optimum maximum amount tie-points following the current parameters...
unsigned int * m_nextRasterLinesBlockToProcessValuePtr
A pointer to a valid counter to control the blocks processing sequence.
#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...
Definition: Macros.h:200
unsigned int nLines
static float getSurfDxxDerivative(float **bufferPtr, const unsigned int &centerX, const unsigned int &centerY, const unsigned int &lobeWidth, const unsigned int &lobeRadius)
Return a SURF box filter Dyy derivative centered over the given position from the given integral imag...
double m_surfMaxNormEuclideanDist
The maximum acceptable euclidean distance when matching features (when applicable), default:0.75, valid range: [0,1].
unsigned int m_raster1TargetAreaColStart
The first column of the raster 2 target area to process (default:0 - The entire raster will be consid...
unsigned int getLinesNumber() const
The number of current matrix lines.
Definition: Matrix.h:791
std::multiset< MatchedInterestPointsT > MatchedInterestPointsSetT
unsigned int m_raster2TargetAreaWidth
The raster 2 target area width (default:0 - The entire raster will be considered).
static bool checkForDuplicatedInterestPoints(const InterestPointsSetT &interestPoints, double &x, double &y)
Check for duplicated interest points.
unsigned int col
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:150
static float getHaarYVectorIntensity(BufferType &buffer, const unsigned int &centerX, const unsigned int &centerY, const unsigned int &radius)
Return a Haar Y intesity vector for the window centered at the given point.
virtual AbstractParameters * clone() const =0
Create a clone copy of this instance.
static float getHaarXVectorIntensity(BufferType &buffer, const unsigned int &centerX, const unsigned int &centerY, const unsigned int &radius)
Return a Haar X intesity vector for the window centered at the given point.
te::rst::Interpolator::Method m_interpMethod
The raster interpolator method (default:NearestNeighbor).
float m_feature1
Interest point feature 1 value.