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