All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
TiePointsLocator.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 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/TiePointsLocator.cpp
22  \brief Tie points locator.
23 */
24 
25 #include "TiePointsLocator.h"
26 #include "Macros.h"
27 #include "../geometry/GTFactory.h"
28 #include "../common/PlatformUtils.h"
29 #include "../common/StringUtils.h"
30 #include "../raster/Band.h"
31 #include "../raster/Grid.h"
32 #include "../raster/BandProperty.h"
33 #include "../raster/RasterFactory.h"
34 #include "../datatype/Enums.h"
35 #include "../geometry/GTFilter.h"
36 
37 #include <boost/scoped_array.hpp>
38 #include <boost/shared_array.hpp>
39 #include <boost/lexical_cast.hpp>
40 
41 #include <algorithm>
42 
43 #include <climits>
44 #include <cfloat>
45 #include <cstdio>
46 #include <cmath>
47 #include <boost/concept_check.hpp>
48 
49 #include <cstring>
50 
51 namespace te
52 {
53  namespace rp
54  {
55  // -----------------------------------------------------------------------
56 
58  {
59  reset();
60  }
61 
63  {
64  reset();
65  operator=( other );
66  }
67 
69  {
70  reset();
71  }
72 
73  void TiePointsLocator::InputParameters::reset() throw( te::rp::Exception )
74  {
75  m_interesPointsLocationStrategy = InputParameters::SurfStrategyT;
76  m_inRaster1Ptr = 0;
77  m_inMaskRaster1Ptr = 0;
78  m_inRaster1Bands.clear();
79  m_raster1TargetAreaLineStart = 0;
80  m_raster1TargetAreaColStart = 0;
81  m_raster1TargetAreaWidth = 0;
82  m_raster1TargetAreaHeight = 0;
83  m_inRaster2Ptr = 0;
84  m_inMaskRaster2Ptr = 0;
85  m_inRaster2Bands.clear();
86  m_raster2TargetAreaLineStart = 0;
87  m_raster2TargetAreaColStart = 0;
88  m_raster2TargetAreaWidth = 0;
89  m_raster2TargetAreaHeight = 0;
90  m_enableMultiThread = true;
91  m_enableProgress = false;
92  m_maxTiePoints = 0;
93  m_pixelSizeXRelation = 1;
94  m_pixelSizeYRelation = 1;
95  m_geomTransfName = "Affine";
96  m_geomTransfMaxError = 2;
97  m_moravecCorrelationWindowWidth = 11;
98  m_moravecWindowWidth = 5;
99  m_maxR1ToR2Offset = 0;
100  m_enableGeometryFilter = true;
101  m_geometryFilterAssurance = 0.1;
102  m_moravecGaussianFilterIterations = 1;
103  m_surfScalesNumber = 4;
104  m_surfOctavesNumber = 2;
105  m_rastersRescaleFactor = 1.0;
106  m_surfMaxNormEuclideanDist = 0.5;
107  m_moravecMinAbsCorrelation = 0.5;
109  }
110 
112  const TiePointsLocator::InputParameters& params )
113  {
114  reset();
115 
116  m_interesPointsLocationStrategy = params.m_interesPointsLocationStrategy;
117  m_inRaster1Ptr = params.m_inRaster1Ptr;
118  m_inMaskRaster1Ptr = params.m_inMaskRaster1Ptr;
119  m_inRaster1Bands = params.m_inRaster1Bands;
120  m_raster1TargetAreaLineStart = params.m_raster1TargetAreaLineStart;
121  m_raster1TargetAreaColStart = params.m_raster1TargetAreaColStart;
122  m_raster1TargetAreaWidth = params.m_raster1TargetAreaWidth;
123  m_raster1TargetAreaHeight = params.m_raster1TargetAreaHeight;
124  m_inRaster2Ptr = params.m_inRaster2Ptr;
125  m_inMaskRaster2Ptr = params.m_inMaskRaster2Ptr;
126  m_inRaster2Bands = params.m_inRaster2Bands;
127  m_raster2TargetAreaLineStart = params.m_raster2TargetAreaLineStart;
128  m_raster2TargetAreaColStart = params.m_raster2TargetAreaColStart;
129  m_raster2TargetAreaWidth = params.m_raster2TargetAreaWidth;
130  m_raster2TargetAreaHeight = params.m_raster2TargetAreaHeight;
131  m_enableMultiThread = params.m_enableMultiThread;
132  m_enableProgress = params.m_enableProgress;
133  m_maxTiePoints = params.m_maxTiePoints;
134  m_pixelSizeXRelation = params.m_pixelSizeXRelation;
135  m_pixelSizeYRelation = params.m_pixelSizeYRelation;
136  m_geomTransfName = params.m_geomTransfName;
137  m_geomTransfMaxError = params.m_geomTransfMaxError;
138  m_moravecCorrelationWindowWidth = params.m_moravecCorrelationWindowWidth;
139  m_moravecWindowWidth = params.m_moravecWindowWidth;
140  m_maxR1ToR2Offset = params.m_maxR1ToR2Offset;
141  m_enableGeometryFilter = params.m_enableGeometryFilter;
142  m_geometryFilterAssurance = params.m_geometryFilterAssurance;
143  m_moravecGaussianFilterIterations = params.m_moravecGaussianFilterIterations;
144  m_surfScalesNumber = params.m_surfScalesNumber;
145  m_surfOctavesNumber = params.m_surfOctavesNumber;
146  m_rastersRescaleFactor = params.m_rastersRescaleFactor;
147  m_surfMaxNormEuclideanDist = params.m_surfMaxNormEuclideanDist;
148  m_moravecMinAbsCorrelation = params.m_moravecMinAbsCorrelation;
149  m_interpMethod = params.m_interpMethod;
150 
151  return *this;
152  }
153 
155  {
156  return new InputParameters( *this );
157  }
158 
159  // -----------------------------------------------------------------------
160 
162  {
163  reset();
164  }
165 
167  {
168  reset();
169  operator=( other );
170  }
171 
173  {
174  reset();
175  }
176 
177  void TiePointsLocator::OutputParameters::reset() throw( te::rp::Exception )
178  {
179  m_tiePoints.clear();
180  m_transformationPtr.reset();
181  }
182 
184  const TiePointsLocator::OutputParameters& params )
185  {
186  reset();
187 
188  m_tiePoints = params.m_tiePoints;
189  m_transformationPtr.reset( params.m_transformationPtr->clone() );
190 
191  return *this;
192  }
193 
195  {
196  return new OutputParameters( *this );
197  }
198 
199  // -----------------------------------------------------------------------
200 
202  {
203  reset();
204  }
205 
207  {
208  }
209 
211  throw( te::rp::Exception )
212  {
213  if( ! m_isInitialized ) return false;
214 
215  TiePointsLocator::OutputParameters* outParamsPtr = dynamic_cast<
216  TiePointsLocator::OutputParameters* >( &outputParams );
217  TERP_TRUE_OR_THROW( outParamsPtr, "Invalid paramters" );
218 
219  /* Calculating the rescale factors
220  factor = rescaled_orignal_image / original_image */
221 
222  double raster1XRescFact = 1.0;
223  double raster1YRescFact = 1.0;
224  double raster2XRescFact = 1.0;
225  double raster2YRescFact = 1.0;
226 
228  {
229  /* The image 1 has poor resolution - bigger pixel resolution values -
230  and image 2 needs to be rescaled down */
231 
232  raster2XRescFact = 1.0 / m_inputParameters.m_pixelSizeXRelation;
233  }
234  else if( m_inputParameters.m_pixelSizeXRelation < 1.0 )
235  {
236  /* The image 2 has poor resolution - bigger pixel resolution values
237  and image 1 needs to be rescaled down */
238 
239  raster1XRescFact = m_inputParameters.m_pixelSizeXRelation;
240  }
241 
243  {
244  /* The image 1 has poor resolution - bigger pixel resolution values -
245  and image 2 needs to be rescaled down */
246 
247  raster2YRescFact = 1.0 / m_inputParameters.m_pixelSizeYRelation;
248  }
249  else if( m_inputParameters.m_pixelSizeYRelation < 1.0 )
250  {
251  /* The image 2 has poor resolution - bigger pixel resolution values
252  and image 1 needs to be rescaled down */
253 
254  raster1YRescFact = m_inputParameters.m_pixelSizeYRelation;
255  }
256 
257  // Applying the global rescale factor
258 
259  raster1XRescFact *= m_inputParameters.m_rastersRescaleFactor;
260  raster1YRescFact *= m_inputParameters.m_rastersRescaleFactor;
261  raster2XRescFact *= m_inputParameters.m_rastersRescaleFactor;
262  raster2YRescFact *= m_inputParameters.m_rastersRescaleFactor;
263 
264  // progress
265 
266  std::auto_ptr< te::common::TaskProgress > progressPtr;
268  {
269  progressPtr.reset( new te::common::TaskProgress );
270  progressPtr->setTotalSteps( 1 );
271  progressPtr->setMessage( "Locating tie points" );
272  progressPtr->pulse();
273  if( ! progressPtr->isActive() ) return false;
274  }
275 
276  // executing the choosed strategy
277 
278  std::vector< double > tiePointsWeights;
279 
281  {
283  {
284  if( !executeMoravec(
285  raster1XRescFact,
286  raster1YRescFact,
287  raster2XRescFact,
288  raster2YRescFact,
289  progressPtr.get(),
290  outParamsPtr,
291  tiePointsWeights ) )
292  {
293  return false;
294  }
295  break;
296  }
298  {
299  if( !executeSurf(
300  raster1XRescFact,
301  raster1YRescFact,
302  raster2XRescFact,
303  raster2YRescFact,
304  progressPtr.get(),
305  outParamsPtr,
306  tiePointsWeights ) )
307  {
308  return false;
309  }
310  break;
311  }
312  default :
313  {
314  TERP_LOG_AND_THROW( "Invalid strategy" );
315  break;
316  }
317  }
318 
319  // Execute outliers remotion, if required
320 
322  {
323  te::gm::GTParameters transfParams;
324  transfParams.m_tiePoints = outParamsPtr->m_tiePoints;
325 
326  te::gm::GTFilter filter;
327  if( !filter.applyRansac(
329  transfParams,
332  0,
335  tiePointsWeights,
336  outParamsPtr->m_tiePoints,
337  outParamsPtr->m_transformationPtr ) )
338  {
339  return false;
340  };
341  }
342  else
343  {
344  outParamsPtr->m_transformationPtr.reset( te::gm::GTFactory::make(
346  TERP_DEBUG_TRUE_OR_THROW( outParamsPtr->m_transformationPtr.get(),
347  "Invalid transformation" );
348 
349  te::gm::GTParameters transfParams;
350  transfParams.m_tiePoints = outParamsPtr->m_tiePoints;
351 
352  if( ! outParamsPtr->m_transformationPtr->initialize( transfParams ) )
353  {
354  outParamsPtr->m_transformationPtr.reset();
355  }
356  }
357 
359  {
360  progressPtr->pulse();
361  if( ! progressPtr->isActive() ) return false;
362  }
363 
364  return true;
365  }
366 
368  const double raster1XRescFact,
369  const double raster1YRescFact,
370  const double raster2XRescFact,
371  const double raster2YRescFact,
372  te::common::TaskProgress* progressPtr,
374  std::vector< double >& tiePointsWeights )
375  throw( te::rp::Exception )
376  {
377  outParamsPtr->m_tiePoints.clear();
378  tiePointsWeights.clear();
379 
380  // Calculating the number of tie points to be found
381 
382  unsigned int raster1MaxInterestPoints = m_inputParameters.m_maxTiePoints;
383  unsigned int raster2MaxInterestPoints = m_inputParameters.m_maxTiePoints;
384  {
385  double rescRaster1Area =
386  ( (double)( m_inputParameters.m_raster1TargetAreaWidth ) * raster1XRescFact ) *
387  ( (double)( m_inputParameters.m_raster1TargetAreaHeight ) * raster1YRescFact );
388  double rescRaster2Area =
389  ( (double)( m_inputParameters.m_raster2TargetAreaWidth ) * raster2XRescFact ) *
390  ( (double)( m_inputParameters.m_raster2TargetAreaHeight ) * raster2YRescFact );;
391 
392  if( rescRaster1Area > rescRaster2Area )
393  {
394  raster1MaxInterestPoints = (unsigned int)(
395  rescRaster1Area /
396  ( rescRaster2Area / ( (double)m_inputParameters.m_maxTiePoints ) ) );
397  }
398  else if( rescRaster1Area < rescRaster2Area )
399  {
400  raster2MaxInterestPoints = (unsigned int)(
401  rescRaster2Area /
402  ( rescRaster1Area / ( (double)m_inputParameters.m_maxTiePoints ) ) );
403  }
404  }
405 
406  // Updating the progress interface steps number
407 
408  if( progressPtr )
409  progressPtr->setTotalSteps( progressPtr->getTotalSteps() + 10 );
410 
411  // Generating raster 1 features
412 
413  FloatsMatrix raster1Features;
414  InterestPointsSetT raster1InterestPoints;
415  {
416  // loading raster data
417  std::vector< boost::shared_ptr< FloatsMatrix > > raster1Data;
418  UCharsMatrix maskRaster1Data;
419 
420  if( !loadRasterData(
424  0,
429  raster1XRescFact,
430  raster1YRescFact,
432  20,
433  raster1Data,
434  maskRaster1Data ) )
435  {
436  return false;
437  }
438 
439  if( progressPtr )
440  {
441  progressPtr->pulse();
442  if( ! progressPtr->isActive() ) return false;
443  }
444 
445  // applying the noise filter
446 
448  {
449  boost::shared_ptr< FloatsMatrix > tempMatrix(
450  new FloatsMatrix );
451  TERP_TRUE_OR_RETURN_FALSE( tempMatrix->reset(
452  0, 0,
454  raster1Data[ 0 ]->getMaxTmpFileSize(),
455  raster1Data[ 0 ]->getMaxMemPercentUsage() ),
456  "Cannot allocate image matrix" );
457 
458  if( !applyMeanFilter( *(raster1Data[ 0 ]),
460  {
461  return false;
462  }
463 
464  raster1Data[ 0 ]->reset();
465  raster1Data[ 0 ] = tempMatrix;
466 
467 // createTifFromMatrix( *(raster1Data[ 0 ]), InterestPointsSetT(), "raster1Filtered");
468  }
469 
470  if( progressPtr )
471  {
472  progressPtr->pulse();
473  if( ! progressPtr->isActive() ) return false;
474  }
475 
476  // locating interest points
477 
479  *(raster1Data[ 0 ]),
480  maskRaster1Data.getLinesNumber() ? (&maskRaster1Data) : 0,
482  raster1MaxInterestPoints,
484  raster1InterestPoints ) )
485  {
486  return false;
487  }
488 
489  if( progressPtr )
490  {
491  progressPtr->pulse();
492  if( ! progressPtr->isActive() ) return false;
493  }
494 
495  // Generting features (one feature per line)
496 
497  raster1Features.reset( FloatsMatrix::RAMMemPol );
498  InterestPointsSetT auxInterestPoints;
499 
501  raster1InterestPoints,
503  *(raster1Data[ 0 ]),
504  raster1Features,
505  auxInterestPoints ),
506  "Error generating raster 1 features" );
507 
508  raster1InterestPoints = auxInterestPoints;
509 
510 // features2Tiff( raster1Features, raster1InterestPoints, "raster1features" );
511 
512  if( progressPtr )
513  {
514  progressPtr->pulse();
515  if( ! progressPtr->isActive() ) return false;
516  }
517  }
518 
519  // Generating raster 2 features
520 
521  FloatsMatrix raster2Features;
522  InterestPointsSetT raster2InterestPoints;
523  {
524  // Loading image data
525 
526  std::vector< boost::shared_ptr< FloatsMatrix > > raster2Data;
527  UCharsMatrix maskRaster2Data;
528 
529  if( !loadRasterData(
533  0,
538  raster2XRescFact,
539  raster2YRescFact,
541  20,
542  raster2Data,
543  maskRaster2Data ) )
544  {
545  return false;
546  }
547 
548  if( progressPtr )
549  {
550  progressPtr->pulse();
551  if( ! progressPtr->isActive() ) return false;
552  }
553 
554  // applying the noise filter
555 
557  {
558  boost::shared_ptr< FloatsMatrix > tempMatrix(
559  new FloatsMatrix );
560 
561  tempMatrix.reset( new FloatsMatrix );
562  TERP_TRUE_OR_RETURN_FALSE( tempMatrix->reset(
563  0, 0,
565  raster2Data[ 0 ]->getMaxTmpFileSize(),
566  raster2Data[ 0 ]->getMaxMemPercentUsage() ),
567  "Cannot allocate image matrix" );
568 
569  if( !applyMeanFilter( *(raster2Data[ 0 ]),
571  {
572  return false;
573  }
574 
575  raster2Data[ 0 ] = tempMatrix;
576 
577 // createTifFromMatrix( *(raster2Data[ 0 ]), InterestPointsSetT(), "raster2Filtered");
578  }
579 
580  if( progressPtr )
581  {
582  progressPtr->pulse();
583  if( ! progressPtr->isActive() ) return false;
584  }
585 
586  // locating interest points
587 
589  *(raster2Data[ 0 ]),
590  maskRaster2Data.getLinesNumber() ? (&maskRaster2Data) : 0,
592  raster2MaxInterestPoints,
594  raster2InterestPoints ) )
595  {
596  return false;
597  }
598 
599  if( progressPtr )
600  {
601  progressPtr->pulse();
602  if( ! progressPtr->isActive() ) return false;
603  }
604 
605  // Generting features (one feature per line)
606 
607  raster2Features.reset( FloatsMatrix::RAMMemPol );
608  InterestPointsSetT auxInterestPoints;
609 
611  raster2InterestPoints,
613  *(raster2Data[ 0 ]),
614  raster2Features,
615  auxInterestPoints ),
616  "Error generating raster 2 features" );
617 
618  raster2InterestPoints = auxInterestPoints;
619 
620 // features2Tiff( raster2Features, raster2InterestPoints, "raster2features" );
621 
622  if( progressPtr )
623  {
624  progressPtr->pulse();
625  if( ! progressPtr->isActive() ) return false;
626  }
627  }
628 
629  // Matching features
630 
631  MatchedInterestPointsSetT matchedPoints;
632 
634  raster1Features,
635  raster2Features,
636  raster1InterestPoints,
637  raster2InterestPoints,
641  matchedPoints ),
642  "Error matching features" );
643 
644  if( progressPtr )
645  {
646  progressPtr->pulse();
647  if( ! progressPtr->isActive() ) return false;
648  }
649 
650  // Clean anused data
651 
652  raster1Features.clear();
653  raster2Features.clear();
654  raster1InterestPoints.clear();
655  raster2InterestPoints.clear();
656 
657  // Generating the output tie-points
658 
659  {
661  MatchedInterestPointsSetT::const_iterator itB = matchedPoints.begin();
662  const MatchedInterestPointsSetT::const_iterator itE = matchedPoints.end();
663 
664  float minFeatureValue1 = FLT_MAX;
665  float maxFeatureValue1 = (-1.0) * FLT_MAX;
666  float minFeatureValue2 = FLT_MAX;
667  float maxFeatureValue2 = (-1.0) * FLT_MAX;
668  float tiePointWeight = 0;
669 
670  itB = matchedPoints.begin();
671  while( itB != itE )
672  {
673  if( minFeatureValue1 > itB->m_point1.m_feature1 )
674  minFeatureValue1 = itB->m_point1.m_feature1;
675  if( maxFeatureValue1 < itB->m_point1.m_feature1 )
676  maxFeatureValue1 = itB->m_point1.m_feature1;
677 
678  if( minFeatureValue2 > itB->m_point2.m_feature1 )
679  minFeatureValue2 = itB->m_point2.m_feature1;
680  if( maxFeatureValue2 < itB->m_point2.m_feature1 )
681  maxFeatureValue2 = itB->m_point2.m_feature1;
682 
683  ++itB;
684  }
685 
686  float featureValue1Range = maxFeatureValue1 - minFeatureValue1;
687  float featureValue2Range = maxFeatureValue2 - minFeatureValue2;
688 
689  if( ( featureValue1Range == 0.0 ) || ( featureValue2Range == 0.0 ) )
690  {
691  tiePointsWeights.resize( matchedPoints.size(), 1.0 );
692  }
693  else
694  {
695  itB = matchedPoints.begin();
696  while( itB != itE )
697  {
698  auxTP.first.x = ( itB->m_point1.m_x / raster1XRescFact ) +
700  auxTP.first.y = ( itB->m_point1.m_y / raster1YRescFact ) +
702  auxTP.second.x = ( itB->m_point2.m_x / raster2XRescFact ) +
704  auxTP.second.y = ( itB->m_point2.m_y / raster2YRescFact ) +
706 
707  tiePointWeight =
708  (
709  ( 2.0f * itB->m_feature )
710  +
711  std::min(
712  (
713  ( itB->m_point1.m_feature1 - minFeatureValue1 )
714  /
715  featureValue1Range
716  )
717  ,
718  (
719  ( itB->m_point1.m_feature2 - minFeatureValue2 )
720  /
721  featureValue2Range
722  )
723  )
724  );
725 
726  tiePointsWeights.push_back( (double)tiePointWeight );
727 
728  outParamsPtr->m_tiePoints.push_back( auxTP );
729 
730  ++itB;
731  }
732  }
733  }
734 
735  if( progressPtr )
736  {
737  progressPtr->pulse();
738  if( ! progressPtr->isActive() ) return false;
739  }
740 
741  return true;
742  }
743 
745  const double raster1XRescFact,
746  const double raster1YRescFact,
747  const double raster2XRescFact,
748  const double raster2YRescFact,
749  te::common::TaskProgress* progressPtr,
751  std::vector< double >& tiePointsWeights )
752  throw( te::rp::Exception )
753  {
754  outParamsPtr->m_tiePoints.clear();
755  tiePointsWeights.clear();
756 
757  if( progressPtr )
758  progressPtr->setTotalSteps( progressPtr->getTotalSteps() + 8 );
759 
760  // Locating interest points and features from raster 1
761 
762  InterestPointsSetT raster1InterestPoints;
763  FloatsMatrix raster1Features;
764  {
765  // Loading image data
766 
767  std::vector< boost::shared_ptr< FloatsMatrix > > rasterData;
768  UCharsMatrix maskRasterData;
769 
770  if( !loadRasterData(
774  0,
779  raster1XRescFact,
780  raster1YRescFact,
782  20,
783  rasterData,
784  maskRasterData ) )
785  {
786  return false;
787  }
788 
789 // printMatrix( *(rasterData[ 0 ]) );
790 // createTifFromMatrix( *(rasterData[ 0 ]), InterestPointsSetT(), "loadedRaster1");
791 
792  if( progressPtr )
793  {
794  progressPtr->pulse();
795  if( ! progressPtr->isActive() ) return false;
796  }
797 
798  // Creating the integral image
799 
800  FloatsMatrix integralRaster;
801 
802  TERP_TRUE_OR_RETURN_FALSE( createIntegralImage( *(rasterData[ 0 ]),
803  integralRaster ), "Integral image creation error" );
804 
805  rasterData.clear();
806 
807  if( progressPtr )
808  {
809  progressPtr->pulse();
810  if( ! progressPtr->isActive() ) return false;
811  }
812 
813 // printMatrix( integralRaster );
814 // createTifFromMatrix( integralRaster, InterestPointsSetT(), "integralRaster1" );
815 
816  // locating interest points
817 
819  integralRaster,
820  maskRasterData.getLinesNumber() ? (&maskRasterData) : 0,
821  raster1InterestPoints ),
822  "Error locating raster 1 interest points" );
823 
824 // createTifFromMatrix( *(rasterData[ 0 ]), candidateInterestPoints, "surfInterestPoints1");
825 
826  if( progressPtr )
827  {
828  progressPtr->pulse();
829  if( ! progressPtr->isActive() ) return false;
830  }
831 
832 
833  InterestPointsSetT validInterestPoints;
834 
835  TERP_TRUE_OR_RETURN_FALSE( generateSurfFeatures( raster1InterestPoints,
836  integralRaster, validInterestPoints, raster1Features ),
837  "Error generating raster features" );
838 
839  raster1InterestPoints = validInterestPoints;
840 
841  if( progressPtr )
842  {
843  progressPtr->pulse();
844  if( ! progressPtr->isActive() ) return false;
845  }
846 
847  }
848 
849  // Locating interest points and features from raster 2
850 
851  InterestPointsSetT raster2InterestPoints;
852  FloatsMatrix raster2Features;
853  {
854  // Loading image data
855 
856  std::vector< boost::shared_ptr< FloatsMatrix > > rasterData;
857  UCharsMatrix maskRasterData;
858 
859  if( !loadRasterData(
863  0,
868  raster2XRescFact,
869  raster2YRescFact,
871  20,
872  rasterData,
873  maskRasterData ) )
874  {
875  return false;
876  }
877 
878 // printMatrix( *(rasterData[ 0 ]) );
879 // createTifFromMatrix( *(rasterData[ 0 ]), InterestPointsSetT(), "loadedRaster2");
880 
881  if( progressPtr )
882  {
883  progressPtr->pulse();
884  if( ! progressPtr->isActive() ) return false;
885  }
886 
887  // Creating the integral image
888 
889  FloatsMatrix integralRaster;
890 
891  TERP_TRUE_OR_RETURN_FALSE( createIntegralImage( *(rasterData[ 0 ]),
892  integralRaster ), "Integral image creation error" );
893 
894  if( progressPtr )
895  {
896  progressPtr->pulse();
897  if( ! progressPtr->isActive() ) return false;
898  }
899 
900  rasterData.clear();
901 
902 // printMatrix( integralRaster );
903 // createTifFromMatrix( integralRaster, InterestPointsSetT(), "integralRaster2" );
904 
905  // locating interest points
906 
908  integralRaster,
909  maskRasterData.getLinesNumber() ? (&maskRasterData) : 0,
910  raster2InterestPoints ),
911  "Error locating raster interest points" );
912 
913 // createTifFromMatrix( *(rasterData[ 0 ]), candidateInterestPoints, "surfInterestPoints2");
914 
915  if( progressPtr )
916  {
917  progressPtr->pulse();
918  if( ! progressPtr->isActive() ) return false;
919  }
920 
921  InterestPointsSetT validInterestPoints;
922 
923  TERP_TRUE_OR_RETURN_FALSE( generateSurfFeatures( raster2InterestPoints,
924  integralRaster, validInterestPoints, raster2Features ),
925  "Error generating raster features" );
926 
927  raster2InterestPoints = validInterestPoints;
928 
929  if( progressPtr )
930  {
931  progressPtr->pulse();
932  if( ! progressPtr->isActive() ) return false;
933  }
934  }
935 
936 // printMatrix( raster1Features );
937 // printMatrix( raster2Features );
938 
939  // Matching features
940 
941  MatchedInterestPointsSetT matchedPoints;
942 
944  raster1Features,
945  raster2Features,
946  raster1InterestPoints,
947  raster2InterestPoints,
949  m_inputParameters.m_surfMaxNormEuclideanDist * 2.0, /* since surf feature vectors are unitary verctors */
951  matchedPoints ),
952  "Error matching features" );
953 
954  if( progressPtr )
955  {
956  progressPtr->pulse();
957  if( ! progressPtr->isActive() ) return false;
958  }
959 
960  // Removing the repeated matched points (those present in more than one scale)
961  // keeping the higher MatchedInterestPointsT::m_feature value
962 
963  {
964  MatchedInterestPointsSetT::iterator it1 = matchedPoints.begin();
965  MatchedInterestPointsSetT::iterator it2;
966  MatchedInterestPointsSetT::iterator eraseIt;
967 
968  while( it1 != matchedPoints.end() )
969  {
970  it2 = it1;
971  ++it2;
972  eraseIt = matchedPoints.end();
973 
974  while( it2 != matchedPoints.end() )
975  {
976  if(
977  ( it1->m_point1.m_x == it2->m_point1.m_x )
978  &&
979  ( it1->m_point1.m_y == it2->m_point1.m_y )
980  &&
981  ( it1->m_point2.m_x == it2->m_point2.m_x )
982  &&
983  ( it1->m_point2.m_y == it2->m_point2.m_y )
984  )
985  {
986  if( it1->m_feature < it2->m_feature )
987  {
988  eraseIt = it1;
989  }
990  else if( it1->m_feature > it2->m_feature )
991  {
992  eraseIt = it2;
993  }
994 
995  break;
996  }
997  else
998  {
999  ++it2;
1000  }
1001  }
1002 
1003  if( eraseIt == it1 )
1004  {
1005  ++it1;
1006  matchedPoints.erase( eraseIt );
1007  }
1008  else if( eraseIt != matchedPoints.end() )
1009  {
1010  matchedPoints.erase( eraseIt );
1011  ++it1;
1012  }
1013  else
1014  {
1015  ++it1;
1016  }
1017  }
1018  }
1019 
1020  // Removing the worse mathed points to fitting the required amount of matched points
1021 
1022  while( matchedPoints.size() > m_inputParameters.m_maxTiePoints )
1023  {
1024  matchedPoints.erase( matchedPoints.begin() );
1025  }
1026 
1027  // Generating the output tie-points
1028 
1029  {
1031  MatchedInterestPointsSetT::const_iterator itB = matchedPoints.begin();
1032  const MatchedInterestPointsSetT::const_iterator itE = matchedPoints.end();
1033  float minFeature1P1 = FLT_MAX;
1034  float maxFeature1P1 = (-1.0) * FLT_MAX;
1035  float minFeature1P2 = FLT_MAX;
1036  float maxFeature1P2 = (-1.0) * FLT_MAX;
1037 
1038  while( itB != itE )
1039  {
1040  if( minFeature1P1 > itB->m_point1.m_feature1 )
1041  minFeature1P1 = itB->m_point1.m_feature1;
1042  if( maxFeature1P1 < itB->m_point1.m_feature1 )
1043  maxFeature1P1 = itB->m_point1.m_feature1;
1044 
1045  if( minFeature1P2 > itB->m_point2.m_feature1 )
1046  minFeature1P2 = itB->m_point2.m_feature1;
1047  if( maxFeature1P2 < itB->m_point2.m_feature1 )
1048  maxFeature1P2 = itB->m_point2.m_feature1;
1049 
1050  ++itB;
1051  }
1052 
1053  float feature1P1Range = maxFeature1P1 - minFeature1P1;
1054  float feature1P2Range = maxFeature1P2 - minFeature1P2;
1055 
1056  if( ( feature1P1Range == 0.0 ) || ( feature1P2Range == 0.0 ) )
1057  {
1058  tiePointsWeights.resize( matchedPoints.size(), 1.0 );
1059  }
1060  else
1061  {
1062  itB = matchedPoints.begin();
1063 
1064  while( itB != itE )
1065  {
1066  auxTP.first.x = ( itB->m_point1.m_x / raster1XRescFact ) +
1068  auxTP.first.y = ( itB->m_point1.m_y / raster1YRescFact ) +
1070  auxTP.second.x = ( itB->m_point2.m_x / raster2XRescFact ) +
1072  auxTP.second.y = ( itB->m_point2.m_y / raster2YRescFact ) +
1074 
1075  tiePointsWeights.push_back( (double)
1076  (
1077  ( 2.0 * itB->m_feature )
1078  +
1079  std::min(
1080  (
1081  ( itB->m_point1.m_feature1 - minFeature1P1 + feature1P1Range )
1082  /
1083  ( 2.0 * feature1P1Range )
1084  )
1085  ,
1086  (
1087  ( itB->m_point2.m_feature1 - minFeature1P2 + feature1P2Range )
1088  /
1089  ( 2.0 * feature1P2Range )
1090  )
1091  )
1092  )
1093  );
1094 
1095  outParamsPtr->m_tiePoints.push_back( auxTP );
1096 
1097  ++itB;
1098  }
1099  }
1100  }
1101 
1102  return true;
1103  }
1104 
1105 
1106  void TiePointsLocator::reset() throw( te::rp::Exception )
1107  {
1109  m_isInitialized = false;
1110  }
1111 
1113  throw( te::rp::Exception )
1114  {
1115  reset();
1116 
1117  {
1118  TiePointsLocator::InputParameters const* inputParamsPtr = dynamic_cast<
1119  TiePointsLocator::InputParameters const* >( &inputParams );
1120  TERP_TRUE_OR_RETURN_FALSE( inputParamsPtr, "Invalid parameters" );
1121 
1122  m_inputParameters = *inputParamsPtr;
1123  }
1124 
1125  // Checking m_inRaster1Ptr
1126 
1128  "Invalid m_inRaster1Ptr" );
1131  "Invalid m_inRaster1Ptr" );
1132 
1133  // Checking m_inMaskRaster1Ptr
1134 
1136  {
1139  "Invalid m_inMaskRaster1Ptr" );
1142  "Invalid m_inMaskRaster1Ptr" );
1146  "Invalid m_inMaskRaster1Ptr" );
1150  "Invalid m_inMaskRaster1Ptr" );
1151  }
1152 
1153  // Checking raster 1 target area
1154 
1157  "Invalid m_raster1TargetAreaLineStart" );
1158 
1161  "Invalid m_raster1TargetAreaColStart" );
1162 
1165  {
1168  ( ( unsigned int ) m_inputParameters.m_inRaster1Ptr->getNumberOfColumns() )
1170 
1173  ( ( unsigned int ) m_inputParameters.m_inRaster1Ptr->getNumberOfRows() )
1175  }
1176  else
1177  {
1182  }
1183 
1185  "Invalid m_raster1TargetAreaWidth" );
1187  "Invalid m_raster1TargetAreaHeight" );
1188 
1189  // Checking raster 1 bands
1190  {
1191  for( unsigned int bandIdx = 0 ; bandIdx <
1192  m_inputParameters.m_inRaster1Bands.size() ; ++bandIdx )
1193  {
1195  m_inputParameters.m_inRaster1Bands[ bandIdx ] <
1197  "Invalid m_inRaster1Bands" );
1198  }
1199  }
1200 
1201  // Checking raster 2
1202 
1204  "Invalid m_inRaster2Ptr" );
1207  "Invalid m_inRaster2Ptr" );
1208 
1209  // Checking m_inMaskRaster2Ptr
1210 
1212  {
1215  "Invalid m_inMaskRaster2Ptr" );
1218  "Invalid m_inMaskRaster2Ptr" );
1222  "Invalid m_inMaskRaster2Ptr" );
1226  "Invalid m_inMaskRaster2Ptr" );
1227  }
1228 
1229  // Checking raster target area
1230 
1233  "Invalid m_raster2TargetAreaLineStart" );
1234 
1237  "Invalid m_raster2TargetAreaColStart" );
1238 
1241  {
1244  ( ( unsigned int ) m_inputParameters.m_inRaster2Ptr->getNumberOfColumns() )
1246 
1249  ( ( unsigned int ) m_inputParameters.m_inRaster2Ptr->getNumberOfRows() )
1251  }
1252  else
1253  {
1258  }
1259 
1261  "Invalid m_raster2TargetAreaWidth" );
1263  "Invalid m_raster2TargetAreaHeight" );
1264 
1265  // Checking raster 2 bands
1266 
1267  {
1268  for( unsigned int bandIdx = 0 ; bandIdx <
1269  m_inputParameters.m_inRaster2Bands.size() ; ++bandIdx )
1270  {
1272  m_inputParameters.m_inRaster2Bands[ bandIdx ] <
1274  "Invalid m_inRaster2Bands" );
1275  }
1276  }
1277 
1278  // Checking strategy specific parameters
1279 
1281  {
1283  {
1285  == 1, "Invalid number of raster 1 bands" );
1287  == 1, "Invalid number of raster 2 bands" );
1288 
1289  // Defining the number of tie points
1290 
1292  {
1293  const unsigned int maxRastersArea =
1294  std::max(
1297  ,
1300  );
1301  const unsigned maxWindowSize = std::max(
1304  m_inputParameters.m_maxTiePoints = maxRastersArea /
1305  ( 4 * maxWindowSize * maxWindowSize );
1306 
1307  // This is because the features and matching matrix bare eing allocated in RAM
1308  const double totalPhysMem = (double)te::common::GetTotalPhysicalMemory();
1309  const double usedVMem = (double)te::common::GetUsedVirtualMemory();
1310  const double totalVMem = (double)te::common::GetTotalVirtualMemory();
1311  const double freeVMem = 0.4 * std::min( totalPhysMem, ( totalVMem - usedVMem ) );
1312  const double featSize = (double)( m_inputParameters.m_moravecCorrelationWindowWidth *
1315  std::min(
1317  (unsigned int)(
1318  std::sqrt(
1319  ( featSize * featSize )
1320  +
1321  ( freeVMem / (double)( sizeof( float ) ) )
1322  )
1323  -
1324  featSize
1325  )
1326  );
1327  }
1328 
1329  break;
1330  }
1332  {
1334  == 1, "Invalid number of raster 1 bands" );
1336  == 1, "Invalid number of raster 2 bands" );
1337 
1338  // Defining the number of tie points
1339 
1341  {
1342  const unsigned int maxRastersArea =
1343  std::max(
1346  ,
1349  );
1350  const unsigned int maxWindowSize = getSurfFilterSize(
1353  m_inputParameters.m_maxTiePoints = maxRastersArea /
1354  ( 4 * maxWindowSize * maxWindowSize );
1355 
1356  // This is because the features and matching matrix bare eing allocated in RAM
1357  const double totalPhysMem = (double)te::common::GetTotalPhysicalMemory();
1358  const double usedVMem = (double)te::common::GetUsedVirtualMemory();
1359  const double totalVMem = (double)te::common::GetTotalVirtualMemory();
1360  const double freeVMem = 0.4 * std::min( totalPhysMem, ( totalVMem - usedVMem ) );
1362  std::min(
1364  (unsigned int)(
1365  std::sqrt(
1366  ( 65 * 65 )
1367  +
1368  ( freeVMem / (double)( sizeof( float ) ) )
1369  )
1370  -
1371  65
1372  )
1373  );
1374  }
1375 
1376  break;
1377  }
1378  default :
1379  {
1380  TERP_LOG_AND_RETURN_FALSE( "Invalid strategy" );
1381  break;
1382  }
1383  };
1384 
1385  // Checking other parameters
1386 
1388  "Invalid m_maxTiePoints" )
1389 
1391  "Invalid m_pixelSizeXRelation" )
1392 
1394  "Invalid m_pixelSizeYRelation" )
1395 
1397  "Invalid m_geomTransfMaxError" )
1398 
1402  "Invalid m_moravecCorrelationWindowWidth" );
1403 
1407  "Invalid m_moravecWindowWidth" );
1408 
1411  "Invalid m_geomTransfName" );
1412 
1414  "Invalid m_surfScalesNumber" );
1415 
1417  "Invalid m_surfOctavesNumber" );
1418 
1420  "Invalid m_rastersRescaleFactor" );
1421 
1424  "Invalid m_surfMaxNormEuclideanDist" );
1425 
1428  "Invalid m_moravecMinAbsCorrelation" );
1429 
1432  "Invalid m_geometryFilterAssurance" );
1433 
1434  m_isInitialized = true;
1435 
1436  return true;
1437  }
1438 
1440  {
1441  return m_isInitialized;
1442  }
1443 
1445  te::rst::Raster const* rasterPtr,
1446  const std::vector< unsigned int >& rasterBands,
1447  te::rst::Raster const* maskRasterPtr,
1448  const unsigned int maskRasterBand,
1449  const unsigned int rasterTargetAreaLineStart,
1450  const unsigned int rasterTargetAreaColStart,
1451  const unsigned int rasterTargetAreaWidth,
1452  const unsigned int rasterTargetAreaHeight,
1453  const double rescaleFactorX,
1454  const double rescaleFactorY,
1455  const te::rst::Interpolator::Method rasterInterpMethod,
1456  const unsigned char maxMemPercentUsage,
1457  std::vector< boost::shared_ptr< FloatsMatrix > >& loadedRasterData,
1458  UCharsMatrix& loadedMaskRasterData )
1459  {
1460  // Allocating the output matrixes
1461 
1462  const unsigned int rescaledNLines = (unsigned int)(
1463  ((double)rasterTargetAreaHeight) * rescaleFactorY );
1464  const unsigned int rescaledNCols = (unsigned int)(
1465  ((double)rasterTargetAreaWidth) * rescaleFactorX );
1466 
1467  {
1468  unsigned char maxMemPercentUsagePerMatrix = MAX( 1u, maxMemPercentUsage /
1469  (
1470  ( maskRasterPtr ? 1 : 0 )
1471  +
1472  ((unsigned int)rasterBands.size()) )
1473  );
1474 
1475  loadedRasterData.resize( rasterBands.size() );
1476 
1477  for( unsigned int rasterBandsIdx = 0 ; rasterBandsIdx < rasterBands.size() ;
1478  ++rasterBandsIdx )
1479  {
1480  loadedRasterData[ rasterBandsIdx ].reset( new FloatsMatrix );
1481  TERP_TRUE_OR_RETURN_FALSE( loadedRasterData[ rasterBandsIdx ]->reset(
1482  rescaledNLines, rescaledNCols, FloatsMatrix::AutoMemPol,
1483  maxMemPercentUsagePerMatrix ),
1484  "Cannot allocate image 1 matrix" );
1485  maxMemPercentUsagePerMatrix *= 2;
1486  }
1487 
1488  if( maskRasterPtr )
1489  {
1490  TERP_TRUE_OR_RETURN_FALSE( loadedMaskRasterData.reset(
1491  rescaledNLines, rescaledNCols,
1492  UCharsMatrix::AutoMemPol, maxMemPercentUsagePerMatrix ),
1493  "Cannot allocate image 1 mask matrix" );
1494  }
1495  }
1496 
1497  // loading mask data
1498 
1499  if( maskRasterPtr )
1500  {
1501  te::rst::Band const* inMaskRasterBand = maskRasterPtr->getBand( maskRasterBand );
1502  assert( inMaskRasterBand );
1503 
1504  unsigned char* outMaskLinePtr = 0;
1505  unsigned int outLine = 0;
1506  unsigned int outCol = 0;
1507  unsigned int inLine = 0;
1508  unsigned int inCol = 0;
1509  double value = 0;
1510 
1511  for( outLine = 0 ; outLine < rescaledNLines ; ++outLine )
1512  {
1513  inLine = (unsigned int)( ( ( (double)outLine ) /
1514  rescaleFactorY ) + ( (double)rasterTargetAreaLineStart ) );
1515 
1516  outMaskLinePtr = loadedMaskRasterData[ outLine ];
1517 
1518  for( outCol = 0 ; outCol < rescaledNCols ; ++outCol )
1519  {
1520  inCol = (unsigned int)( ( ( (double)outCol ) /
1521  rescaleFactorX ) + ( (double)rasterTargetAreaColStart ) );
1522 
1523  inMaskRasterBand->getValue( inCol, inLine, value );
1524 
1525  if( value == 0 )
1526  outMaskLinePtr[ outCol ] = 0;
1527  else
1528  outMaskLinePtr[ outCol ] = 255;
1529  }
1530  }
1531  }
1532 
1533  // loading raster data
1534  {
1535  const double rasterTargetAreaLineStartDouble = (double)
1536  rasterTargetAreaLineStart;
1537  const double rasterTargetAreaColStartDouble = (double)
1538  rasterTargetAreaColStart;
1539  te::rst::Interpolator interpInstance( rasterPtr, rasterInterpMethod );
1540  float* floatLinePtr = 0;
1541  double* doubleLinePtr = 0;
1542  unsigned int outLine = 0;
1543  unsigned int outCol = 0;
1544  double inLine = 0;
1545  double inCol = 0;
1546  std::complex< double > interpolatedValue;
1547  unsigned int bandIdx = 0;
1548  double bandMin = 0;
1549  double bandMax = 0;
1550  double gain = 0;
1551 
1552  DoublesMatrix auxBandData;
1553  TERP_TRUE_OR_RETURN_FALSE( auxBandData.reset(
1554  rescaledNLines, rescaledNCols, DoublesMatrix::AutoMemPol, 40 ),
1555  "Cannot allocate auxiliar matrix" );
1556 
1557  for( unsigned int rasterBandsIdx = 0 ; rasterBandsIdx < rasterBands.size() ;
1558  ++rasterBandsIdx )
1559  {
1560  bandIdx= rasterBands[ rasterBandsIdx ];
1561  bandMin = DBL_MAX;
1562  bandMax = -1.0 * DBL_MAX;
1563 
1564  for( outLine = 0 ; outLine < rescaledNLines ; ++outLine )
1565  {
1566  inLine = ( ( (double)outLine ) / rescaleFactorY ) +
1567  rasterTargetAreaLineStartDouble;
1568 
1569  doubleLinePtr = auxBandData[ outLine ];
1570 
1571  for( outCol = 0 ; outCol < rescaledNCols ; ++outCol )
1572  {
1573  inCol = ( ( (double)outCol ) / rescaleFactorX ) +
1574  rasterTargetAreaColStartDouble;
1575 
1576  interpInstance.getValue( inCol, inLine, interpolatedValue,
1577  bandIdx );
1578 
1579  doubleLinePtr[ outCol ] = interpolatedValue.real();
1580 
1581  if( interpolatedValue.real() > bandMax ) bandMax = interpolatedValue.real();
1582  if( interpolatedValue.real() < bandMin ) bandMin = interpolatedValue.real();
1583  }
1584  }
1585 
1586  if( bandMin == bandMax )
1587  gain = 0.0;
1588  else
1589  gain = ( 1.0 / ( bandMax - bandMin ) );
1590 
1591  for( outLine = 0 ; outLine < rescaledNLines ; ++outLine )
1592  {
1593  doubleLinePtr = auxBandData[ outLine ];
1594  floatLinePtr = loadedRasterData[ rasterBandsIdx ]->operator[]( outLine );
1595 
1596  for( outCol = 0 ; outCol < rescaledNCols ; ++outCol )
1597  {
1598  floatLinePtr[ outCol ] = (float)( ( doubleLinePtr[ outCol ] - bandMin ) * gain );
1599  }
1600  }
1601  }
1602  }
1603 
1604  return true;
1605  }
1606 
1608  const FloatsMatrix& rasterData,
1609  UCharsMatrix const* maskRasterDataPtr,
1610  const unsigned int moravecWindowWidth,
1611  const unsigned int maxInterestPoints,
1612  const unsigned int enableMultiThread,
1613  InterestPointsSetT& interestPoints )
1614  {
1615  interestPoints.clear();
1616 
1617  const unsigned int minRasterWidthAndHeight = 2 * ( ( 2 *
1618  moravecWindowWidth ) - 1 );
1619  // There is not enough data to look for interest points!
1620  if( rasterData.getColumnsNumber() < minRasterWidthAndHeight ) return true;
1621  if( rasterData.getLinesNumber() < minRasterWidthAndHeight ) return true;
1622 
1623  bool returnValue = true;
1624  boost::mutex rastaDataAccessMutex;
1625  boost::mutex interestPointsAccessMutex;
1626  unsigned int nextRasterLinesBlockToProcess = 0;
1627 
1628  MoravecLocatorThreadParams threadParams;
1629  threadParams.m_returnValuePtr = &returnValue;
1630  threadParams.m_rastaDataAccessMutexPtr = &rastaDataAccessMutex;
1631  threadParams.m_interestPointsAccessMutexPtr = &interestPointsAccessMutex;
1633  &nextRasterLinesBlockToProcess;
1634  threadParams.m_interestPointsPtr = &interestPoints;
1635  threadParams.m_rasterDataPtr = &rasterData;
1636  threadParams.m_maskRasterDataPtr = maskRasterDataPtr;
1637  threadParams.m_moravecWindowWidth = moravecWindowWidth;
1638 
1639  if( enableMultiThread )
1640  {
1641  const unsigned int procsNumber = te::common::GetPhysProcNumber();
1642 
1643  threadParams.m_maxRasterLinesBlockMaxSize = std::max(
1644  minRasterWidthAndHeight, rasterData.getLinesNumber() / procsNumber );
1645 
1646  const unsigned int rasterLinesBlocksNumber =
1647  ( rasterData.getLinesNumber() / threadParams.m_maxRasterLinesBlockMaxSize ) +
1648  ( ( rasterData.getLinesNumber() % threadParams.m_maxRasterLinesBlockMaxSize ) ? 1 : 0 );
1649 
1651  maxInterestPoints / rasterLinesBlocksNumber;
1652 
1653  boost::thread_group threads;
1654 
1655  for( unsigned int threadIdx = 0 ; threadIdx < procsNumber ;
1656  ++threadIdx )
1657  {
1658  threads.add_thread( new boost::thread(
1660  &threadParams ) );
1661  }
1662 
1663  threads.join_all();
1664  }
1665  else
1666  {
1667  threadParams.m_maxRasterLinesBlockMaxSize = rasterData.getLinesNumber();
1668  threadParams.m_maxInterestPointsPerRasterLinesBlock = maxInterestPoints;
1669 
1670  locateMoravecInterestPointsThreadEntry( &threadParams );
1671  }
1672 
1673  return returnValue;
1674  }
1675 
1677  {
1678  assert( paramsPtr );
1679  assert( paramsPtr->m_returnValuePtr );
1680  assert( paramsPtr->m_moravecWindowWidth > 2 );
1681  assert( paramsPtr->m_rasterDataPtr );
1682  assert( paramsPtr->m_interestPointsPtr );
1683  assert( paramsPtr->m_rastaDataAccessMutexPtr );
1684  assert( paramsPtr->m_interestPointsAccessMutexPtr );
1685  assert( paramsPtr->m_maxRasterLinesBlockMaxSize > 2 );
1686  assert( paramsPtr->m_nextRasterLinesBlockToProcessValuePtr );
1687 
1688  const unsigned int moravecWindowWidth = paramsPtr->m_moravecWindowWidth;
1689  const unsigned int moravecWindowRadius = moravecWindowWidth / 2;
1690 
1691  // Allocating the internal raster data buffer
1692  // and the mask raster buffer
1693 
1694  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1695 
1696  const unsigned int rasterLines = paramsPtr->m_rasterDataPtr->getLinesNumber();
1697  const unsigned int bufferLines = moravecWindowWidth;
1698  const unsigned int lastBufferLineIdx = bufferLines - 1;
1699  const unsigned int bufferCols = paramsPtr->m_rasterDataPtr->getColumnsNumber();
1700  const unsigned int rasterBufferLineSizeBytes = sizeof(
1701  FloatsMatrix::ElementTypeT ) * bufferCols;
1702  const unsigned int maskRasterBufferLineSizeBytes = sizeof(
1704  bufferCols;
1705 
1706  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1707 
1708  FloatsMatrix rasterBufferDataHandler;
1709  if( ! rasterBufferDataHandler.reset( bufferLines, bufferCols,
1711  {
1712  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1713  *(paramsPtr->m_returnValuePtr) = false;
1714  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1715  return;
1716  }
1717 
1718  boost::scoped_array< float* > rasterBufferHandler( new float*[ bufferLines ] );
1719  for( unsigned int rasterBufferDataHandlerLine = 0 ; rasterBufferDataHandlerLine <
1720  bufferLines ; ++rasterBufferDataHandlerLine )
1721  {
1722  rasterBufferHandler[ rasterBufferDataHandlerLine ] = rasterBufferDataHandler[
1723  rasterBufferDataHandlerLine ];
1724  }
1725 
1726  float** rasterBufferPtr = rasterBufferHandler.get();
1727 
1728  // Allocating the mask raster buffer
1729 
1730  UCharsMatrix maskRasterBufferDataHandler;
1731 
1732  boost::scoped_array< unsigned char* > maskRasterBufferHandler( new unsigned char*[ bufferLines ] );
1733 
1734  unsigned char** maskRasterBufferPtr = 0;
1735 
1736  if( paramsPtr->m_maskRasterDataPtr )
1737  {
1738  if( ! maskRasterBufferDataHandler.reset( bufferLines, bufferCols,
1740  {
1741  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1742  *(paramsPtr->m_returnValuePtr) = false;
1743  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1744  return;
1745  }
1746 
1747  for( unsigned int maskRasterBufferDataHandlerLine = 0 ; maskRasterBufferDataHandlerLine <
1748  bufferLines ; ++maskRasterBufferDataHandlerLine )
1749  {
1750  maskRasterBufferHandler[ maskRasterBufferDataHandlerLine ] = maskRasterBufferDataHandler[
1751  maskRasterBufferDataHandlerLine ];
1752  }
1753 
1754  maskRasterBufferPtr = maskRasterBufferHandler.get();
1755  }
1756 
1757  // Allocating the internal maximas values data buffer
1758 
1759  FloatsMatrix maximasBufferDataHandler;
1760  if( ! maximasBufferDataHandler.reset( bufferLines, bufferCols,
1762  {
1763  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1764  *(paramsPtr->m_returnValuePtr) = false;
1765  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1766  return;
1767  }
1768 
1769  boost::scoped_array< float* > maximasBufferHandler( new float*[ bufferLines ] );
1770  float** maximasBufferPtr = maximasBufferHandler.get();
1771  unsigned int bufferCol = 0;
1772  for( unsigned int maximasBufferDataHandlerLine = 0 ; maximasBufferDataHandlerLine <
1773  bufferLines ; ++maximasBufferDataHandlerLine )
1774  {
1775  maximasBufferHandler[ maximasBufferDataHandlerLine ] = maximasBufferDataHandler[
1776  maximasBufferDataHandlerLine ];
1777  for( bufferCol = 0 ; bufferCol < bufferCols ; ++bufferCol )
1778  {
1779  maximasBufferPtr[ maximasBufferDataHandlerLine ][ bufferCol ] = 0;
1780  }
1781  }
1782 
1783  // Pick the next block to process
1784 
1785  const unsigned int rasterLinesBlocksNumber =
1786  ( rasterLines / paramsPtr->m_maxRasterLinesBlockMaxSize ) +
1787  ( ( rasterLines % paramsPtr->m_maxRasterLinesBlockMaxSize ) ? 1 : 0 );
1788 
1789  for( unsigned int rasterLinesBlockIdx = 0; rasterLinesBlockIdx <
1790  rasterLinesBlocksNumber ; ++rasterLinesBlockIdx )
1791  {
1792  InterestPointsSetT blockMaximas; // the maxima points found inside the current raster block
1793 
1794  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1795 
1796  if( rasterLinesBlockIdx == ( *(paramsPtr->m_nextRasterLinesBlockToProcessValuePtr ) ) )
1797  {
1798  ++( *(paramsPtr->m_nextRasterLinesBlockToProcessValuePtr ) );
1799 
1800  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1801 
1802  // Processing each raster line from the current block
1803 
1804  const unsigned int rasterLinesStart = (unsigned int)std::max( 0,
1805  (int)(rasterLinesBlockIdx * paramsPtr->m_maxRasterLinesBlockMaxSize ) -
1806  (int)( 2 * moravecWindowRadius ) );
1807  const unsigned int rasterLinesEndBound = std::min( 1 +
1808  (rasterLinesBlockIdx * paramsPtr->m_maxRasterLinesBlockMaxSize ) +
1809  paramsPtr->m_maxRasterLinesBlockMaxSize +
1810  ( 2 * moravecWindowRadius ), rasterLines );
1811  const unsigned int varianceCalcStartRasterLineStart = rasterLinesStart +
1812  moravecWindowWidth - 1;
1813  const unsigned int maximasLocationStartRasterLineStart =
1814  varianceCalcStartRasterLineStart + moravecWindowWidth - 1;
1815  unsigned int windowStartBufCol = 0;
1816  const unsigned int windowEndBufColsBound = bufferCols -
1817  moravecWindowWidth;
1818  unsigned int windowStartBufOffset = 0;
1819  unsigned int windowStartBufXOffset = 0;
1820  unsigned int windowStartBufYOffset = 0;
1821  float horVar = 0;
1822  float verVar = 0;
1823  float diagVar = 0;
1824  float adiagVar = 0;
1825  float diffValue = 0;
1826  bool isLocalMaxima = false;
1827  InterestPointT auxInterestPoint;
1828  float neighborMaximaDif = 0;
1829 
1830  for( unsigned int rasterLine = rasterLinesStart; rasterLine < rasterLinesEndBound ;
1831  ++rasterLine )
1832  {
1833  // read a new raster line into the last raster buffer line
1834  paramsPtr->m_rastaDataAccessMutexPtr->lock();
1835 
1836  roolUpBuffer( rasterBufferPtr, bufferLines );
1837  memcpy( rasterBufferPtr[ lastBufferLineIdx ],
1838  paramsPtr->m_rasterDataPtr->operator[]( rasterLine ),
1839  rasterBufferLineSizeBytes );
1840 
1841  // read a new mask raster line into the last mask raster buffer line
1842  if( paramsPtr->m_maskRasterDataPtr )
1843  {
1844  roolUpBuffer( maskRasterBufferPtr, bufferLines );
1845  memcpy( maskRasterBufferPtr[ lastBufferLineIdx ],
1846  paramsPtr->m_maskRasterDataPtr->operator[]( rasterLine ),
1847  maskRasterBufferLineSizeBytes );
1848  }
1849 
1850  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1851 
1852  // calc the diretional variance for last line from the
1853  // diretional variances buffer
1854  if( rasterLine >= varianceCalcStartRasterLineStart )
1855  {
1856  roolUpBuffer( maximasBufferPtr, bufferLines );
1857 
1858  for( windowStartBufCol = 0 ; windowStartBufCol < windowEndBufColsBound ;
1859  ++windowStartBufCol )
1860  {
1861  const float& windowCenterPixelValue = rasterBufferPtr[
1862  moravecWindowRadius ][ windowStartBufCol +
1863  moravecWindowRadius ];
1864  horVar = 0;
1865  verVar = 0;
1866  diagVar = 0;
1867  adiagVar = 0;
1868 
1869  for( windowStartBufOffset = 0 ; windowStartBufOffset <
1870  moravecWindowWidth ; ++windowStartBufOffset )
1871  {
1872  diffValue = windowCenterPixelValue - rasterBufferPtr[
1873  moravecWindowRadius ][ windowStartBufCol +
1874  windowStartBufOffset ];
1875  horVar += ( diffValue * diffValue );
1876 
1877  diffValue = windowCenterPixelValue - rasterBufferPtr[
1878  windowStartBufOffset ][ windowStartBufCol +
1879  moravecWindowRadius ];
1880  verVar += ( diffValue * diffValue );
1881 
1882  diffValue = windowCenterPixelValue - rasterBufferPtr[
1883  windowStartBufOffset ][ windowStartBufCol +
1884  windowStartBufOffset ];
1885  diagVar += ( diffValue * diffValue );
1886 
1887  diffValue = windowCenterPixelValue - rasterBufferPtr[
1888  moravecWindowWidth - 1 - windowStartBufOffset ][ windowStartBufCol +
1889  windowStartBufOffset ];
1890  adiagVar += ( diffValue * diffValue );
1891  }
1892 
1893  maximasBufferPtr[ lastBufferLineIdx ][ windowStartBufCol +
1894  moravecWindowRadius ] = std::min( horVar, std::min(
1895  verVar, std::min( diagVar, adiagVar ) ) );
1896  }
1897  }
1898 
1899  // find the local maxima points for the diretional variances buffer
1900  // center line.
1901  if( rasterLine >= maximasLocationStartRasterLineStart )
1902  {
1903  for( windowStartBufCol = 0 ; windowStartBufCol < windowEndBufColsBound ;
1904  ++windowStartBufCol )
1905  {
1906  isLocalMaxima = true;
1907  const float& windowCenterPixelValue = maximasBufferPtr[
1908  moravecWindowRadius ][ windowStartBufCol +
1909  moravecWindowRadius ];
1910  auxInterestPoint.m_feature1 = 0.0;
1911 
1912  for( windowStartBufYOffset = 0 ; windowStartBufYOffset <
1913  moravecWindowWidth ; ++windowStartBufYOffset )
1914  {
1915  for( windowStartBufXOffset = 0 ; windowStartBufXOffset <
1916  moravecWindowWidth ; ++windowStartBufXOffset )
1917  {
1918  neighborMaximaDif = windowCenterPixelValue - maximasBufferPtr[
1919  windowStartBufYOffset ][ windowStartBufCol +
1920  windowStartBufXOffset ];
1921 
1922  if( neighborMaximaDif < 0.0 )
1923  {
1924  isLocalMaxima = false;
1925  windowStartBufYOffset = moravecWindowWidth;
1926  break;
1927  }
1928 
1929  auxInterestPoint.m_feature1 += std::abs( neighborMaximaDif );
1930  }
1931  }
1932 
1933  if( isLocalMaxima )
1934  {
1935  auxInterestPoint.m_x = windowStartBufCol +
1936  moravecWindowRadius;
1937  auxInterestPoint.m_y = rasterLine - moravecWindowWidth + 1;
1938  assert( auxInterestPoint.m_x <
1939  paramsPtr->m_rasterDataPtr->getColumnsNumber() );
1940  assert( auxInterestPoint.m_y <
1941  paramsPtr->m_rasterDataPtr->getLinesNumber() );
1942 
1943  if( maskRasterBufferPtr )
1944  {
1945  if( maskRasterBufferPtr[ 0 ][ auxInterestPoint.m_x ] )
1946  {
1947  blockMaximas.insert( auxInterestPoint);
1948 
1949  if( blockMaximas.size() >
1951  {
1952  blockMaximas.erase( blockMaximas.begin() );
1953  }
1954  }
1955  }
1956  else
1957  {
1958  blockMaximas.insert( auxInterestPoint );
1959 
1960  if( blockMaximas.size() >
1962  {
1963  blockMaximas.erase( blockMaximas.begin() );
1964  }
1965  }
1966  }
1967  }
1968  }
1969  }
1970 
1971  // Copying the best found block maximas to the external maximas container
1972 
1973  paramsPtr->m_interestPointsAccessMutexPtr->lock();
1974 
1975  unsigned int pointsToAdd = std::min(
1977  (unsigned int)blockMaximas.size() );
1978  InterestPointsSetT::const_reverse_iterator blockMaximasIt =
1979  blockMaximas.rbegin();
1980 
1981  while( pointsToAdd )
1982  {
1983 // std::cout << std::endl << blockMaximasIt->m_featureValue
1984 // << std::endl;
1985 
1986  paramsPtr->m_interestPointsPtr->insert( *blockMaximasIt );
1987 
1988  ++blockMaximasIt;
1989  --pointsToAdd;
1990  }
1991 
1992  paramsPtr->m_interestPointsAccessMutexPtr->unlock();
1993  }
1994  else
1995  {
1996  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
1997  }
1998  }
1999  }
2000 
2002  const FloatsMatrix& integralRasterData,
2003  UCharsMatrix const* maskRasterDataPtr,
2004  InterestPointsSetT& interestPoints ) const
2005  {
2006  interestPoints.clear();
2007 
2008  // finding interest points
2009 
2010  bool returnValue = true;
2011  boost::mutex rastaDataAccessMutex;
2012  boost::mutex interestPointsAccessMutex;
2013  unsigned int nextRasterLinesBlockToProcess = 0;
2014 
2015  SurfLocatorThreadParams threadParams;
2016  threadParams.m_returnValuePtr = &returnValue;
2017  threadParams.m_rastaDataAccessMutexPtr = &rastaDataAccessMutex;
2018  threadParams.m_interestPointsAccessMutexPtr = &interestPointsAccessMutex;
2020  &nextRasterLinesBlockToProcess;
2021  threadParams.m_interestPointsPtr = &interestPoints;
2022  threadParams.m_integralRasterDataPtr = &integralRasterData;
2023  threadParams.m_maskRasterDataPtr = maskRasterDataPtr;
2026 
2028  {
2029  const unsigned int procsNumber = te::common::GetPhysProcNumber();
2030  const unsigned int maxGausFilterWidth = getSurfFilterSize(
2032 
2033  threadParams.m_maxRasterLinesBlockMaxSize = std::max(
2034  4 * maxGausFilterWidth, integralRasterData.getLinesNumber() / procsNumber );
2035  threadParams.m_maxRasterLinesBlockMaxSize = std::min(
2036  threadParams.m_maxRasterLinesBlockMaxSize,
2037  integralRasterData.getLinesNumber() );
2038 
2039  const unsigned int rasterLinesBlocksNumber =
2040  ( integralRasterData.getLinesNumber() / threadParams.m_maxRasterLinesBlockMaxSize ) +
2041  ( ( integralRasterData.getLinesNumber() % threadParams.m_maxRasterLinesBlockMaxSize ) ? 1 : 0 );
2042 
2044  m_inputParameters.m_maxTiePoints / rasterLinesBlocksNumber;
2045 
2046  boost::thread_group threads;
2047 
2048  for( unsigned int threadIdx = 0 ; threadIdx < procsNumber ;
2049  ++threadIdx )
2050  {
2051  threads.add_thread( new boost::thread(
2053  &threadParams ) );
2054  }
2055 
2056  threads.join_all();
2057  }
2058  else
2059  {
2060  threadParams.m_maxRasterLinesBlockMaxSize = integralRasterData.getLinesNumber();
2062 
2063  locateSurfInterestPointsThreadEntry( &threadParams );
2064  }
2065 
2066  return returnValue;
2067  }
2068 
2069 
2070 
2072  {
2073  assert( paramsPtr );
2074  assert( paramsPtr->m_returnValuePtr );
2075  assert( paramsPtr->m_integralRasterDataPtr );
2076  assert( paramsPtr->m_interestPointsPtr );
2077  assert( paramsPtr->m_rastaDataAccessMutexPtr );
2078  assert( paramsPtr->m_interestPointsAccessMutexPtr );
2079  assert( paramsPtr->m_maxRasterLinesBlockMaxSize > 2 );
2080  assert( paramsPtr->m_nextRasterLinesBlockToProcessValuePtr );
2081  assert( paramsPtr->m_scalesNumber > 2 );
2082  assert( paramsPtr->m_octavesNumber > 0 );
2083 
2084  // Globals
2085 
2086  const unsigned int maxGausFilterWidth = getSurfFilterSize(
2087  paramsPtr->m_octavesNumber - 1, paramsPtr->m_scalesNumber - 1 );
2088  const unsigned int maxGausFilterRadius = maxGausFilterWidth / 2;
2089  const unsigned int prevResponseBufferLineIdx = maxGausFilterRadius - 1;
2090  const unsigned int nextResponseBufferLineIdx = maxGausFilterRadius + 1;
2091  const unsigned int buffersLines = maxGausFilterWidth;
2092  const unsigned int lastBuffersLineIdx = buffersLines - 1;
2093 
2094  paramsPtr->m_rastaDataAccessMutexPtr->lock();
2095  const unsigned int rasterLines = paramsPtr->m_integralRasterDataPtr->getLinesNumber();
2096  const unsigned int buffersCols = paramsPtr->m_integralRasterDataPtr->getColumnsNumber();
2097  const unsigned int rasterBufferLineSizeBytes = sizeof( float ) *
2098  buffersCols;
2099  const unsigned int maskRasterBufferLineSizeBytes = sizeof( UCharsMatrix::ElementTypeT ) *
2100  buffersCols;
2101  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2102 
2103  const unsigned maxGausFilterCenterBufferColBound = buffersCols -
2104  maxGausFilterRadius;
2105 
2106  unsigned int scaleIdx = 0 ;
2107  unsigned int octaveIdx = 0 ;
2108 
2109  // Allocating the internal raster data buffer
2110  // and the mask raster buffer
2111 
2112  FloatsMatrix rasterBufferDataHandler;
2113  boost::scoped_array< float* > rasterBufferHandler( new float*[ buffersLines ] );
2114  {
2115  if( ! rasterBufferDataHandler.reset( buffersLines, buffersCols,
2117  {
2118  paramsPtr->m_rastaDataAccessMutexPtr->lock();
2119  *(paramsPtr->m_returnValuePtr) = false;
2120  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2121  return;
2122  }
2123 
2124  for( unsigned int rasterBufferDataHandlerLine = 0 ; rasterBufferDataHandlerLine <
2125  buffersLines ; ++rasterBufferDataHandlerLine )
2126  {
2127  rasterBufferHandler[ rasterBufferDataHandlerLine ] = rasterBufferDataHandler[
2128  rasterBufferDataHandlerLine ];
2129  }
2130  }
2131  float** rasterBufferPtr = rasterBufferHandler.get();
2132 
2133  // Allocating the mask raster buffer
2134 
2135  UCharsMatrix maskRasterBufferDataHandler;
2136 
2137  boost::scoped_array< unsigned char* > maskRasterBufferHandler( new unsigned char*[ buffersLines ] );
2138 
2139  unsigned char** maskRasterBufferPtr = 0;
2140 
2141  if( paramsPtr->m_maskRasterDataPtr )
2142  {
2143  if( ! maskRasterBufferDataHandler.reset( buffersLines, buffersCols,
2145  {
2146  paramsPtr->m_rastaDataAccessMutexPtr->lock();
2147  *(paramsPtr->m_returnValuePtr) = false;
2148  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2149  return;
2150  }
2151 
2152  for( unsigned int maskRasterBufferDataHandlerLine = 0 ; maskRasterBufferDataHandlerLine <
2153  buffersLines ; ++maskRasterBufferDataHandlerLine )
2154  {
2155  maskRasterBufferHandler[ maskRasterBufferDataHandlerLine ] = maskRasterBufferDataHandler[
2156  maskRasterBufferDataHandlerLine ];
2157  }
2158 
2159  maskRasterBufferPtr = maskRasterBufferHandler.get();
2160  }
2161 
2162  // Allocating the internal octaves buffers
2163 
2164  FloatsMatrix octavesBufferDataHandler;
2165  std::vector< std::vector< boost::shared_array< float* > > >
2166  octavesBufferHandlers;
2167  {
2168  const unsigned int octavesBufferDataHandlerLines =
2169  buffersLines * paramsPtr->m_octavesNumber * paramsPtr->m_scalesNumber;
2170  if( ! octavesBufferDataHandler.reset( octavesBufferDataHandlerLines ,
2171  buffersCols,
2173  {
2174  paramsPtr->m_rastaDataAccessMutexPtr->lock();
2175  *(paramsPtr->m_returnValuePtr) = false;
2176  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2177  return;
2178  }
2179  unsigned int octavesBufferDataHandlerLine = 0;
2180  unsigned int octavesBufferDataHandlerCol = 0;
2181  float* octavesBufferDataHandlerLinePtr = 0;
2182  for( octavesBufferDataHandlerLine = 0; octavesBufferDataHandlerLine <
2183  octavesBufferDataHandlerLines ; ++octavesBufferDataHandlerLine )
2184  {
2185  octavesBufferDataHandlerLinePtr = octavesBufferDataHandler[
2186  octavesBufferDataHandlerLine ];
2187 
2188  for( octavesBufferDataHandlerCol = 0; octavesBufferDataHandlerCol <
2189  buffersCols ; ++octavesBufferDataHandlerCol )
2190  {
2191  octavesBufferDataHandlerLinePtr[ octavesBufferDataHandlerCol ] = 0.0;
2192  }
2193  }
2194 
2195  octavesBufferDataHandlerLine = 0;
2196  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
2197  {
2198  octavesBufferHandlers.push_back( std::vector< boost::shared_array< float* > >() );
2199  std::vector< boost::shared_array< float* > >&
2200  currOctaveBuffersHandler = octavesBufferHandlers.back();
2201 
2202  for( scaleIdx = 0 ; scaleIdx < paramsPtr->m_scalesNumber ; ++scaleIdx )
2203  {
2204  currOctaveBuffersHandler.push_back( boost::shared_array< float* >(
2205  new float*[ buffersLines ] ) );
2206  boost::shared_array< float* >& currOctavesBuffer =
2207  currOctaveBuffersHandler.back();
2208  for( unsigned int bufferLine = 0 ; bufferLine < buffersLines ;
2209  ++bufferLine )
2210  {
2211  assert( octavesBufferDataHandlerLine <
2212  octavesBufferDataHandler.getLinesNumber() );
2213 
2214  currOctavesBuffer[ bufferLine ] = octavesBufferDataHandler[
2215  octavesBufferDataHandlerLine ];
2216 
2217  ++octavesBufferDataHandlerLine;
2218  }
2219  }
2220  }
2221  }
2222 
2223  // Allocating the laplacian sign buffers
2224 
2225  UCharsMatrix laplacianSignBufferDataHandler;
2226  std::vector< std::vector< boost::shared_array< unsigned char* > > >
2227  laplacianSignBufferHandlers;
2228  {
2229  const unsigned int laplacianSignBufferDataHandlerLines =
2230  buffersLines * paramsPtr->m_octavesNumber * paramsPtr->m_scalesNumber;
2231  if( ! laplacianSignBufferDataHandler.reset( laplacianSignBufferDataHandlerLines ,
2232  buffersCols,
2234  {
2235  paramsPtr->m_rastaDataAccessMutexPtr->lock();
2236  *(paramsPtr->m_returnValuePtr) = false;
2237  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2238  return;
2239  }
2240  unsigned int laplacianSignBufferDataHandlerLine = 0;
2241  unsigned int laplacianSignBufferDataHandlerCol = 0;
2242  unsigned char* laplacianSignBufferDataHandlerLinePtr = 0;
2243  for( laplacianSignBufferDataHandlerLine = 0; laplacianSignBufferDataHandlerLine <
2244  laplacianSignBufferDataHandlerLines ; ++laplacianSignBufferDataHandlerLine )
2245  {
2246  laplacianSignBufferDataHandlerLinePtr = laplacianSignBufferDataHandler[
2247  laplacianSignBufferDataHandlerLine ];
2248 
2249  for( laplacianSignBufferDataHandlerCol = 0; laplacianSignBufferDataHandlerCol <
2250  buffersCols ; ++laplacianSignBufferDataHandlerCol )
2251  {
2252  laplacianSignBufferDataHandlerLinePtr[ laplacianSignBufferDataHandlerCol ] =
2253  255;
2254  }
2255  }
2256 
2257  laplacianSignBufferDataHandlerLine = 0;
2258  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
2259  {
2260  laplacianSignBufferHandlers.push_back( std::vector< boost::shared_array< unsigned char* > >() );
2261  std::vector< boost::shared_array< unsigned char* > >&
2262  currlaplacianSignBuffersHandler = laplacianSignBufferHandlers.back();
2263 
2264  for( scaleIdx = 0 ; scaleIdx < paramsPtr->m_scalesNumber ; ++scaleIdx )
2265  {
2266  currlaplacianSignBuffersHandler.push_back( boost::shared_array< unsigned char* >(
2267  new unsigned char*[ buffersLines ] ) );
2268  boost::shared_array< unsigned char* >& currlaplacianSignBuffer =
2269  currlaplacianSignBuffersHandler.back();
2270  for( unsigned int bufferLine = 0 ; bufferLine < buffersLines ;
2271  ++bufferLine )
2272  {
2273  assert( laplacianSignBufferDataHandlerLine <
2274  laplacianSignBufferDataHandler.getLinesNumber() );
2275 
2276  currlaplacianSignBuffer[ bufferLine ] = laplacianSignBufferDataHandler[
2277  laplacianSignBufferDataHandlerLine ];
2278 
2279  ++laplacianSignBufferDataHandlerLine;
2280  }
2281  }
2282  }
2283  }
2284 
2285  // Pick the next block to process
2286 
2287  const unsigned int rasterLinesBlocksNumber =
2288  ( rasterLines / paramsPtr->m_maxRasterLinesBlockMaxSize ) +
2289  ( ( rasterLines % paramsPtr->m_maxRasterLinesBlockMaxSize ) ? 1 : 0 );
2290 
2291  for( unsigned int rasterLinesBlockIdx = 0; rasterLinesBlockIdx <
2292  rasterLinesBlocksNumber ; ++rasterLinesBlockIdx )
2293  {
2294  // the maxima points found inside the current raster block
2295  // for each combination of octaves and scales
2296  std::vector< InterestPointsSetT > blockMaximas( paramsPtr->m_scalesNumber *
2297  paramsPtr->m_octavesNumber, InterestPointsSetT() );
2298 
2299  paramsPtr->m_rastaDataAccessMutexPtr->lock();
2300 
2301  if( rasterLinesBlockIdx == ( *(paramsPtr->m_nextRasterLinesBlockToProcessValuePtr ) ) )
2302  {
2303  ++( *(paramsPtr->m_nextRasterLinesBlockToProcessValuePtr ) );
2304 
2305  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2306 
2307  // globals
2308 
2309  const unsigned int rasterLinesStart = (unsigned int)std::max( 0,
2310  (int)(rasterLinesBlockIdx * paramsPtr->m_maxRasterLinesBlockMaxSize ) -
2311  (int)( 2 * maxGausFilterRadius ) );
2312  const unsigned int rasterLinesEndBound = std::min( 1 +
2313  (rasterLinesBlockIdx * paramsPtr->m_maxRasterLinesBlockMaxSize ) +
2314  paramsPtr->m_maxRasterLinesBlockMaxSize +
2315  ( 2 * maxGausFilterRadius ), rasterLines );
2316  const unsigned int firstRasterLineToGenerateResponse =
2317  rasterLinesStart + maxGausFilterWidth - 1;
2318  const unsigned int firstRasterLineToLookForMaximas =
2319  firstRasterLineToGenerateResponse + maxGausFilterRadius + 1;
2320 // unsigned int baseFilterSize = 0;
2321 // unsigned int filterStepSize = 0;
2322  unsigned int filterWidth = 0;
2323  unsigned int filterLobeWidth = 0;
2324  unsigned int filterLobeRadius = 0;
2325  unsigned int filterCenterBufCol = 0 ;
2326 // unsigned int filterCenterBufColBound = 0 ;
2327  float dXX = 0;
2328  float dYY = 0;
2329  float dXY = 0;
2330  InterestPointT auxInterestPoint;
2331  float** currScaleBufferPtr = 0;
2332  unsigned char** currLaplacianSignBufferPtr = 0;
2333  unsigned int lastScaleIdx = 0;
2334  unsigned int nextScaleIdx = 0;
2335  unsigned int prevResponseBufferColIdx = 0;
2336  unsigned int nextResponseBufferColIdx = 0;
2337 
2338  float neighborMaximaDif_0_1 = 0.0;
2339  float neighborMaximaDif_0_2 = 0.0;
2340  float neighborMaximaDif_0_3 = 0.0;
2341  float neighborMaximaDif_0_4 = 0.0;
2342  float neighborMaximaDif_0_5 = 0.0;
2343  float neighborMaximaDif_0_6 = 0.0;
2344  float neighborMaximaDif_0_7 = 0.0;
2345  float neighborMaximaDif_0_8 = 0.0;
2346  float neighborMaximaDif_1_1 = 0.0;
2347  float neighborMaximaDif_1_2 = 0.0;
2348  float neighborMaximaDif_1_3 = 0.0;
2349  float neighborMaximaDif_1_4 = 0.0;
2350  float neighborMaximaDif_1_5 = 0.0;
2351  float neighborMaximaDif_1_6 = 0.0;
2352  float neighborMaximaDif_1_7 = 0.0;
2353  float neighborMaximaDif_1_8 = 0.0;
2354  float neighborMaximaDif_1_9 = 0.0;
2355  float neighborMaximaDif_2_1 = 0.0;
2356  float neighborMaximaDif_2_2 = 0.0;
2357  float neighborMaximaDif_2_3 = 0.0;
2358  float neighborMaximaDif_2_4 = 0.0;
2359  float neighborMaximaDif_2_5 = 0.0;
2360  float neighborMaximaDif_2_6 = 0.0;
2361  float neighborMaximaDif_2_7 = 0.0;
2362  float neighborMaximaDif_2_8 = 0.0;
2363  float neighborMaximaDif_2_9 = 0.0;
2364 
2365  // Processing each raster line from the current block
2366 
2367  for( unsigned int rasterLine = rasterLinesStart; rasterLine < rasterLinesEndBound ;
2368  ++rasterLine )
2369  {
2370  // read a new raster line into the last raster buffer line
2371  paramsPtr->m_rastaDataAccessMutexPtr->lock();
2372  //std::cout << std::endl << "rasterLine"; std::cout << rasterLine << std::endl;
2373  //printBuffer( rasterBufferPtr, buffersLines, buffersCols );
2374  roolUpBuffer( rasterBufferPtr, buffersLines );
2375 // printBuffer( rasterBufferPtr, buffersLines, buffersCols );
2376  memcpy( rasterBufferPtr[ lastBuffersLineIdx ],
2377  paramsPtr->m_integralRasterDataPtr->operator[]( rasterLine ),
2378  rasterBufferLineSizeBytes );
2379 // printBuffer( rasterBufferPtr, buffersLines, buffersCols );
2380  // read a new mask raster line into the last mask raster buffer line
2381  if( paramsPtr->m_maskRasterDataPtr )
2382  {
2383  roolUpBuffer( maskRasterBufferPtr, buffersLines );
2384  memcpy( maskRasterBufferPtr[ lastBuffersLineIdx ],
2385  paramsPtr->m_maskRasterDataPtr->operator[]( rasterLine ),
2386  maskRasterBufferLineSizeBytes );
2387  }
2388  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2389 
2390  // generating the response maps for each octave/scale
2391 
2392  if( rasterLine >= firstRasterLineToGenerateResponse )
2393  {
2394  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
2395  {
2396  for( scaleIdx = 0 ; scaleIdx < paramsPtr->m_scalesNumber ;
2397  ++scaleIdx )
2398  {
2399  assert( octavesBufferHandlers.size() > octaveIdx );
2400  assert( octavesBufferHandlers[ octaveIdx].size() > scaleIdx );
2401  currScaleBufferPtr = octavesBufferHandlers[ octaveIdx][ scaleIdx ].get();
2402  assert( currScaleBufferPtr );
2403 
2404  assert( laplacianSignBufferHandlers.size() > octaveIdx );
2405  assert( laplacianSignBufferHandlers[ octaveIdx].size() > scaleIdx );
2406  currLaplacianSignBufferPtr = laplacianSignBufferHandlers[ octaveIdx][ scaleIdx ].get();
2407  assert( currLaplacianSignBufferPtr );
2408 
2409  // Roll up buffers
2410 
2411  roolUpBuffer( currScaleBufferPtr, buffersLines );
2412  roolUpBuffer( currLaplacianSignBufferPtr, buffersLines );
2413 
2414  // applying the filter kernels for the current scale
2415 
2416  filterWidth = getSurfFilterSize( octaveIdx, scaleIdx );
2417  assert( filterWidth <= maxGausFilterWidth );
2418 
2419  filterLobeWidth = filterWidth / 3;
2420  filterLobeRadius = filterLobeWidth / 2;
2421 
2422  for( filterCenterBufCol = maxGausFilterRadius ;
2423  filterCenterBufCol < maxGausFilterCenterBufferColBound ;
2424  ++filterCenterBufCol )
2425  {
2426  dYY = getSurfDyyDerivative( rasterBufferPtr, filterCenterBufCol,
2427  maxGausFilterRadius, filterLobeWidth, filterLobeRadius);
2428  dYY /= (float)( filterWidth * filterWidth );
2429 
2430  dXX = getSurfDxxDerivative( rasterBufferPtr, filterCenterBufCol,
2431  maxGausFilterRadius, filterLobeWidth, filterLobeRadius);
2432  dXX /= (float)( filterWidth * filterWidth );
2433 
2434  dXY = getSurfDxyDerivative( rasterBufferPtr, filterCenterBufCol,
2435  maxGausFilterRadius, filterLobeWidth );
2436  dXY /= (float)( filterWidth * filterWidth );
2437 
2438  currScaleBufferPtr[ lastBuffersLineIdx ][ filterCenterBufCol ] =
2439  ( dXX * dYY ) - ( 0.81f * dXY * dXY );
2440  currLaplacianSignBufferPtr[ lastBuffersLineIdx ][ filterCenterBufCol ] =
2441  ( ( dXX + dYY ) >= 0.0 ) ? 1 : 0;
2442  }
2443  }
2444  }
2445  }
2446 
2447  // Finding local maximas over all scales using 3 x 3 x 3 window
2448  // at the lowest scale
2449 
2450  if( rasterLine >= firstRasterLineToLookForMaximas )
2451  {
2452 // printBuffer( octavesBufferHandlers[ 0 ][ 0 ].get(), buffersLines, buffersCols );
2453 // printBuffer( octavesBufferHandlers[ 0 ][ 1 ].get(), buffersLines, buffersCols );
2454 // printBuffer( octavesBufferHandlers[ 0 ][ 2 ].get(), buffersLines, buffersCols );
2455 // return;
2456 
2457  for( unsigned int windCenterCol = maxGausFilterRadius ;
2458  windCenterCol < maxGausFilterCenterBufferColBound ; ++windCenterCol )
2459  {
2460  prevResponseBufferColIdx = windCenterCol - 1;
2461  nextResponseBufferColIdx = windCenterCol + 1;
2462  auxInterestPoint.m_feature1 = (-1.0) * FLT_MAX;
2463 
2464  for( octaveIdx = 0 ; octaveIdx < paramsPtr->m_octavesNumber ; ++octaveIdx )
2465  {
2466  std::vector< boost::shared_array< float* > >&
2467  currOctaveBuffersHandler = octavesBufferHandlers[ octaveIdx ];
2468 
2469  for( scaleIdx = 1 ; scaleIdx < ( paramsPtr->m_scalesNumber - 1 );
2470  ++scaleIdx )
2471  {
2472  const float& windowCenterPixelValue = currOctaveBuffersHandler[
2473  scaleIdx ][ maxGausFilterRadius ][ windCenterCol ];
2474  lastScaleIdx = scaleIdx - 1;
2475  nextScaleIdx = scaleIdx + 1;
2476 
2477  neighborMaximaDif_0_1 = windowCenterPixelValue - currOctaveBuffersHandler[
2478  scaleIdx ][ prevResponseBufferLineIdx ][ prevResponseBufferColIdx ];
2479  neighborMaximaDif_0_2 = windowCenterPixelValue - currOctaveBuffersHandler[
2480  scaleIdx ][ prevResponseBufferLineIdx ][ windCenterCol ];
2481  neighborMaximaDif_0_3 = windowCenterPixelValue - currOctaveBuffersHandler[
2482  scaleIdx ][ prevResponseBufferLineIdx ][ nextResponseBufferColIdx ];
2483  neighborMaximaDif_0_4 = windowCenterPixelValue - currOctaveBuffersHandler[
2484  scaleIdx ][ maxGausFilterRadius ][ prevResponseBufferColIdx ];
2485  neighborMaximaDif_0_5 = windowCenterPixelValue - currOctaveBuffersHandler[
2486  scaleIdx ][ maxGausFilterRadius ][ nextResponseBufferColIdx ];
2487  neighborMaximaDif_0_6 = windowCenterPixelValue - currOctaveBuffersHandler[
2488  scaleIdx ][ nextResponseBufferLineIdx ][ prevResponseBufferColIdx];
2489  neighborMaximaDif_0_7 = windowCenterPixelValue - currOctaveBuffersHandler[
2490  scaleIdx ][ nextResponseBufferLineIdx ][ windCenterCol ];
2491  neighborMaximaDif_0_8 = windowCenterPixelValue - currOctaveBuffersHandler[
2492  scaleIdx ][ nextResponseBufferLineIdx ][ nextResponseBufferColIdx ];
2493 
2494  if(
2495  ( windowCenterPixelValue > 0.0 )
2496  // verifying the current scale (center not included)
2497  && ( neighborMaximaDif_0_1 > 0.0 )
2498  && ( neighborMaximaDif_0_2 > 0.0 )
2499  && ( neighborMaximaDif_0_3 > 0.0 )
2500  && ( neighborMaximaDif_0_4 > 0.0 )
2501  && ( neighborMaximaDif_0_5 > 0.0 )
2502  && ( neighborMaximaDif_0_6 > 0.0 )
2503  && ( neighborMaximaDif_0_7 > 0.0 )
2504  && ( neighborMaximaDif_0_8 > 0.0 )
2505  )
2506  {
2507  neighborMaximaDif_1_1 = windowCenterPixelValue - currOctaveBuffersHandler[
2508  lastScaleIdx ][ prevResponseBufferLineIdx ][ prevResponseBufferColIdx ];
2509  neighborMaximaDif_1_2 = windowCenterPixelValue - currOctaveBuffersHandler[
2510  lastScaleIdx ][ prevResponseBufferLineIdx ][ windCenterCol ];
2511  neighborMaximaDif_1_3 = windowCenterPixelValue - currOctaveBuffersHandler[
2512  lastScaleIdx ][ prevResponseBufferLineIdx ][ nextResponseBufferColIdx ];
2513  neighborMaximaDif_1_4 = windowCenterPixelValue - currOctaveBuffersHandler[
2514  lastScaleIdx ][ maxGausFilterRadius ][ prevResponseBufferColIdx ];
2515  neighborMaximaDif_1_5 = windowCenterPixelValue - currOctaveBuffersHandler[
2516  lastScaleIdx ][ maxGausFilterRadius ][ windCenterCol ];
2517  neighborMaximaDif_1_6 = windowCenterPixelValue - currOctaveBuffersHandler[
2518  lastScaleIdx ][ maxGausFilterRadius ][ nextResponseBufferColIdx ];
2519  neighborMaximaDif_1_7 = windowCenterPixelValue - currOctaveBuffersHandler[
2520  lastScaleIdx ][ nextResponseBufferLineIdx ][ prevResponseBufferColIdx];
2521  neighborMaximaDif_1_8 = windowCenterPixelValue - currOctaveBuffersHandler[
2522  lastScaleIdx ][ nextResponseBufferLineIdx ][ windCenterCol ];
2523  neighborMaximaDif_1_9 = windowCenterPixelValue - currOctaveBuffersHandler[
2524  lastScaleIdx ][ nextResponseBufferLineIdx ][ nextResponseBufferColIdx ];
2525 
2526  if(
2527  // verifying the top scale
2528  ( neighborMaximaDif_1_1 > 0.0 )
2529  && ( neighborMaximaDif_1_2 > 0.0 )
2530  && ( neighborMaximaDif_1_3 > 0.0 )
2531  && ( neighborMaximaDif_1_4 > 0.0 )
2532  && ( neighborMaximaDif_1_5 > 0.0 )
2533  && ( neighborMaximaDif_1_6 > 0.0 )
2534  && ( neighborMaximaDif_1_7 > 0.0 )
2535  && ( neighborMaximaDif_1_8 > 0.0 )
2536  && ( neighborMaximaDif_1_9 > 0.0 )
2537  )
2538  {
2539  neighborMaximaDif_2_1 = windowCenterPixelValue - currOctaveBuffersHandler[
2540  nextScaleIdx ][ prevResponseBufferLineIdx ][ prevResponseBufferColIdx ];
2541  neighborMaximaDif_2_2 = windowCenterPixelValue - currOctaveBuffersHandler[
2542  nextScaleIdx ][ prevResponseBufferLineIdx ][ windCenterCol ];
2543  neighborMaximaDif_2_3 = windowCenterPixelValue - currOctaveBuffersHandler[
2544  nextScaleIdx ][ prevResponseBufferLineIdx ][ nextResponseBufferColIdx ];
2545  neighborMaximaDif_2_4 = windowCenterPixelValue - currOctaveBuffersHandler[
2546  nextScaleIdx ][ maxGausFilterRadius ][ prevResponseBufferColIdx ];
2547  neighborMaximaDif_2_5 = windowCenterPixelValue - currOctaveBuffersHandler[
2548  nextScaleIdx ][ maxGausFilterRadius ][ windCenterCol ];
2549  neighborMaximaDif_2_6 = windowCenterPixelValue - currOctaveBuffersHandler[
2550  nextScaleIdx ][ maxGausFilterRadius ][ nextResponseBufferColIdx ];
2551  neighborMaximaDif_2_7 = windowCenterPixelValue - currOctaveBuffersHandler[
2552  nextScaleIdx ][ nextResponseBufferLineIdx ][ prevResponseBufferColIdx];
2553  neighborMaximaDif_2_8 = windowCenterPixelValue - currOctaveBuffersHandler[
2554  nextScaleIdx ][ nextResponseBufferLineIdx ][ windCenterCol ];
2555  neighborMaximaDif_2_9 = windowCenterPixelValue - currOctaveBuffersHandler[
2556  nextScaleIdx ][ nextResponseBufferLineIdx ][ nextResponseBufferColIdx ];
2557 
2558  if(
2559  // verifying the next scale
2560  ( neighborMaximaDif_2_1 > 0.0 )
2561  && ( neighborMaximaDif_2_2 > 0.0 )
2562  && ( neighborMaximaDif_2_3 > 0.0 )
2563  && ( neighborMaximaDif_2_4 > 0.0 )
2564  && ( neighborMaximaDif_2_5 > 0.0 )
2565  && ( neighborMaximaDif_2_6 > 0.0 )
2566  && ( neighborMaximaDif_2_7 > 0.0 )
2567  && ( neighborMaximaDif_2_8 > 0.0 )
2568  && ( neighborMaximaDif_2_9 > 0.0 )
2569  && (
2570  maskRasterBufferPtr
2571  ?
2572  ( maskRasterBufferPtr[ 0 ][ windCenterCol ] != 0 )
2573  :
2574  true
2575  )
2576  )
2577  {
2578  auxInterestPoint.m_feature1 =
2579  neighborMaximaDif_0_1
2580  + neighborMaximaDif_0_2
2581  + neighborMaximaDif_0_3
2582  + neighborMaximaDif_0_4
2583  + neighborMaximaDif_0_5
2584  + neighborMaximaDif_0_6
2585  + neighborMaximaDif_0_7
2586  + neighborMaximaDif_0_8
2587  + neighborMaximaDif_1_1
2588  + neighborMaximaDif_1_2
2589  + neighborMaximaDif_1_3
2590  + neighborMaximaDif_1_4
2591  + neighborMaximaDif_1_5
2592  + neighborMaximaDif_1_6
2593  + neighborMaximaDif_1_7
2594  + neighborMaximaDif_1_8
2595  + neighborMaximaDif_1_9
2596  + neighborMaximaDif_2_1
2597  + neighborMaximaDif_2_2
2598  + neighborMaximaDif_2_3
2599  + neighborMaximaDif_2_4
2600  + neighborMaximaDif_2_5
2601  + neighborMaximaDif_2_6
2602  + neighborMaximaDif_2_7
2603  + neighborMaximaDif_2_8
2604  + neighborMaximaDif_2_9;
2605  auxInterestPoint.m_feature2 = (float)getSurfFilterSize(
2606  octaveIdx, scaleIdx );
2607  auxInterestPoint.m_feature3 = (float)
2608  laplacianSignBufferHandlers[ octaveIdx ][ scaleIdx ][
2609  maxGausFilterRadius ][ windCenterCol ] ;
2610 
2611  auxInterestPoint.m_x = windCenterCol;
2612  auxInterestPoint.m_y = rasterLine - ( 2 * maxGausFilterRadius) ;
2613  assert( auxInterestPoint.m_x <
2614  paramsPtr->m_integralRasterDataPtr->getColumnsNumber() );
2615  assert( auxInterestPoint.m_y <
2616  paramsPtr->m_integralRasterDataPtr->getLinesNumber() );
2617 
2618  assert( ( ( octaveIdx * paramsPtr->m_scalesNumber ) +
2619  scaleIdx ) < blockMaximas.size() );
2620  InterestPointsSetT& currScalePointsSet = blockMaximas[
2621  ( octaveIdx * paramsPtr->m_scalesNumber ) + scaleIdx ];
2622 
2623  currScalePointsSet.insert( auxInterestPoint);
2624 
2625  if( currScalePointsSet.size() >
2627  {
2628  currScalePointsSet.erase( currScalePointsSet.begin() );
2629  }
2630  }
2631  }
2632  }
2633  }
2634  }
2635  }
2636  }
2637  }
2638  }
2639  else
2640  {
2641  paramsPtr->m_rastaDataAccessMutexPtr->unlock();
2642  }
2643 
2644  // Copying the best found block maximas to the external maximas container
2645 
2646  paramsPtr->m_interestPointsAccessMutexPtr->lock();
2647 
2648  for( unsigned int blockMaximasIdx = 0 ; blockMaximasIdx <
2649  blockMaximas.size() ; ++blockMaximasIdx )
2650  {
2651  paramsPtr->m_interestPointsPtr->insert(
2652  blockMaximas[ blockMaximasIdx ].begin(),
2653  blockMaximas[ blockMaximasIdx ].end() );
2654  }
2655 
2656  paramsPtr->m_interestPointsAccessMutexPtr->unlock();
2657  }
2658  }
2659 
2661  const DoublesMatrix& rasterData,
2662  const InterestPointsSetT& interestPoints,
2663  const std::string& tifFileName )
2664  {
2665  std::map<std::string, std::string> rInfo;
2666  rInfo["URI"] = tifFileName + ".tif";
2667 
2668  std::vector<te::rst::BandProperty*> bandsProperties;
2669  bandsProperties.push_back(new te::rst::BandProperty( 0, te::dt::UCHAR_TYPE, "" ));
2670  bandsProperties[0]->m_colorInterp = te::rst::RedCInt;
2671  bandsProperties[0]->m_noDataValue = 0;
2672  bandsProperties.push_back(new te::rst::BandProperty( *bandsProperties[0] ));
2673  bandsProperties[1]->m_colorInterp = te::rst::GreenCInt;
2674  bandsProperties.push_back(new te::rst::BandProperty( *bandsProperties[0] ));
2675  bandsProperties[2]->m_colorInterp = te::rst::BlueCInt;
2676 
2677  te::rst::Grid* newgrid = new te::rst::Grid( rasterData.getColumnsNumber(),
2678  rasterData.getLinesNumber(), 0, -1 );
2679 
2680  std::auto_ptr< te::rst::Raster > outputRasterPtr(
2681  te::rst::RasterFactory::make( "GDAL", newgrid, bandsProperties, rInfo, 0, 0));
2682  TERP_TRUE_OR_THROW( outputRasterPtr.get(), "Output raster creation error");
2683 
2684  unsigned int line = 0;
2685  unsigned int col = 0;
2686  const unsigned int nLines = rasterData.getLinesNumber();
2687  const unsigned int nCols = rasterData.getColumnsNumber();
2688  double rasterDataMin = DBL_MAX;
2689  double rasterDataMax = (-1.0) * DBL_MAX;
2690  double value = 0;
2691 
2692  for( line = 0 ; line < nLines ; ++line )
2693  for( col = 0 ; col < nCols ; ++col )
2694  {
2695  value = rasterData[ line ][ col ];
2696 
2697  if( rasterDataMin > value )
2698  rasterDataMin = value;
2699  if( rasterDataMax < value )
2700  rasterDataMax = value;
2701  }
2702 
2703  if( rasterDataMax == rasterDataMin )
2704  {
2705  rasterDataMin = 0.0;
2706  rasterDataMax = 1.0;
2707  }
2708 
2709  for( line = 0 ; line < nLines ; ++line )
2710  for( col = 0 ; col < nCols ; ++col )
2711  {
2712  value = rasterData[ line ][ col ];
2713  value = ( value - rasterDataMin ) / ( rasterDataMax - rasterDataMin );
2714  value *= 255.0;
2715  value = std::max( 0.0, value );
2716  value = std::min( 255.0, value );
2717 
2718  outputRasterPtr->setValue( col, line, value, 0 );
2719  outputRasterPtr->setValue( col, line, value, 1 );
2720  outputRasterPtr->setValue( col, line, value, 2 );
2721  }
2722 
2723  InterestPointsSetT::const_iterator itB = interestPoints.begin();
2724  InterestPointsSetT::const_iterator itE = interestPoints.end();
2725 
2726  while( itB != itE )
2727  {
2728  outputRasterPtr->setValue( itB->m_x, itB->m_y, 0, 0 );
2729  outputRasterPtr->setValue( itB->m_x, itB->m_y, 255, 1 );
2730  outputRasterPtr->setValue( itB->m_x, itB->m_y, 0, 2 );
2731 
2732  ++itB;
2733  }
2734  }
2735 
2737  DoublesMatrix& outputData, const unsigned int iterationsNumber )
2738  {
2739  if( iterationsNumber == 0 ) return false;
2740 
2741  TERP_TRUE_OR_RETURN_FALSE( outputData.reset( inputData.getLinesNumber(),
2742  inputData.getColumnsNumber() ), "Cannot allocate image matrix" );
2743 
2744  const unsigned int nLines = inputData.getLinesNumber();
2745  const unsigned int nCols = inputData.getColumnsNumber();
2746  const unsigned int lastLineIndex = nLines - 1;
2747  const unsigned int lastColIndex = nCols - 1;
2748  unsigned int currLine = 0;
2749  unsigned int currCol = 0;
2750 
2751  // internal temp matrixes
2752 
2753  DoublesMatrix tempMatrix;
2754 
2755  if( iterationsNumber > 1 )
2756  {
2757  TERP_TRUE_OR_RETURN_FALSE( tempMatrix.reset( nLines, nCols,
2759  "Cannot allocate image matrix" );
2760  }
2761 
2762  /* Fill borders with zero */
2763 
2764  for( currLine = 0 ; currLine < nLines ; ++currLine ) {
2765  outputData( currLine, 0 ) = 0.0;
2766  outputData( currLine, lastColIndex ) = 0.0;
2767  }
2768 
2769  for( currCol = 0 ; currCol < nCols ; ++currCol ) {
2770  outputData( 0, currCol ) = 0.0;
2771  outputData( lastLineIndex, currCol ) = 0.0;
2772  }
2773 
2774  /* Smoothing */
2775 
2776  DoublesMatrix const* inputPtr = 0;
2777  DoublesMatrix* outputPtr = 0;
2778  DoublesMatrix const* auxPtr = 0;
2779 
2780  for( unsigned int iteration = 0 ; iteration < iterationsNumber ;
2781  ++iteration )
2782  {
2783  if( iteration == 0 )
2784  {
2785  inputPtr = &inputData;
2786 
2787  if( iterationsNumber > 1 )
2788  outputPtr = &tempMatrix;
2789  else
2790  outputPtr = &outputData;
2791  }
2792  else if( iteration == iterationsNumber - 1 )
2793  {
2794  inputPtr = outputPtr;
2795  outputPtr = &outputData;
2796  }
2797  else
2798  {
2799  auxPtr = inputPtr;
2800  inputPtr = outputPtr;
2801  outputPtr = (DoublesMatrix*)auxPtr;
2802  }
2803 
2804  for( currLine = 1 ; currLine < lastLineIndex ; ++currLine )
2805  {
2806  for( currCol = 1 ; currCol < lastColIndex ; ++currCol )
2807  {
2808  outputPtr->operator()( currLine, currCol ) =
2809  (
2810  inputPtr->operator()( currLine - 1, currCol ) +
2811  ( 4.0 * inputData( currLine, currCol ) ) +
2812  inputPtr->operator()( currLine + 1, currCol ) +
2813  inputPtr->operator()( currLine, currCol - 1 ) +
2814  inputPtr->operator()( currLine, currCol + 1 )
2815  ) / 8.0;
2816  }
2817  }
2818  }
2819 
2820  return true;
2821  }
2822 
2824  FloatsMatrix& outputData, const unsigned int iterationsNumber )
2825  {
2826  if( iterationsNumber == 0 )
2827  {
2828  outputData = inputData;
2829  }
2830  else
2831  {
2832  if( inputData.getColumnsNumber() < 3 )
2833  {
2834  return false;
2835  }
2836  if( inputData.getLinesNumber() < 3 )
2837  {
2838  return false;
2839  }
2840 
2841  TERP_TRUE_OR_RETURN_FALSE( outputData.reset( inputData.getLinesNumber(),
2842  inputData.getColumnsNumber() ), "Cannot allocate image matrix" );
2843 
2844  const unsigned int nLines = inputData.getLinesNumber();
2845  const unsigned int nCols = inputData.getColumnsNumber();
2846  const unsigned int lastLineIndex = nLines - 1;
2847  const unsigned int lastColIndex = nCols - 1;
2848  unsigned int currLine = 0;
2849  unsigned int currCol = 0;
2850 
2851  // internal temp matrixes
2852 
2853  FloatsMatrix tempMatrix;
2854 
2855  if( iterationsNumber > 1 )
2856  {
2857  TERP_TRUE_OR_RETURN_FALSE( tempMatrix.reset( nLines, nCols,
2859  "Cannot allocate image matrix" );
2860  }
2861 
2862  /* Fill borders with zero */
2863 
2864  for( currLine = 0 ; currLine < nLines ; ++currLine ) {
2865  outputData( currLine, 0 ) = 0.0;
2866  outputData( currLine, lastColIndex ) = 0.0;
2867  }
2868 
2869  for( currCol = 0 ; currCol < nCols ; ++currCol ) {
2870  outputData( 0, currCol ) = 0.0;
2871  outputData( lastLineIndex, currCol ) = 0.0;
2872  }
2873 
2874  /* Smoothing */
2875 
2876  FloatsMatrix const* inputPtr = 0;
2877  FloatsMatrix* outputPtr = 0;
2878  FloatsMatrix const* auxPtr = 0;
2879  float* outputLinePtr = 0;
2880  unsigned int prevLine = 0;
2881  unsigned int prevCol = 0;
2882  unsigned int nextLine = 0;
2883  unsigned int nextCol = 0;
2884 
2885  for( unsigned int iteration = 0 ; iteration < iterationsNumber ;
2886  ++iteration )
2887  {
2888  if( iteration == 0 )
2889  {
2890  inputPtr = &inputData;
2891 
2892  if( iterationsNumber > 1 )
2893  outputPtr = &tempMatrix;
2894  else
2895  outputPtr = &outputData;
2896  }
2897  else if( iteration == iterationsNumber - 1 )
2898  {
2899  inputPtr = outputPtr;
2900  outputPtr = &outputData;
2901  }
2902  else
2903  {
2904  auxPtr = inputPtr;
2905  inputPtr = outputPtr;
2906  outputPtr = (FloatsMatrix*)auxPtr;
2907  }
2908 
2909  const FloatsMatrix& internalInputMatrix = *inputPtr;
2910 
2911  for( currLine = 1 ; currLine < lastLineIndex ; ++currLine )
2912  {
2913  prevLine = currLine - 1;
2914  nextLine = currLine + 1;
2915 
2916  outputLinePtr = outputPtr->operator[]( currLine );
2917 
2918  for( currCol = 1 ; currCol < lastColIndex ; ++currCol )
2919  {
2920  prevCol = currCol - 1;
2921  nextCol = currCol + 1;
2922 
2923  outputLinePtr[ currCol ] =
2924  (
2925  internalInputMatrix( prevLine, prevCol )
2926  + internalInputMatrix( prevLine, currCol )
2927  + internalInputMatrix( prevLine, nextCol )
2928  + internalInputMatrix( currLine, prevCol )
2929  + internalInputMatrix( currLine, nextCol )
2930  + internalInputMatrix( nextLine, prevCol )
2931  + internalInputMatrix( nextLine, currCol )
2932  + internalInputMatrix( nextLine, nextCol )
2933  ) / 8.0f;
2934  }
2935  }
2936  }
2937  }
2938 
2939  return true;
2940  }
2941 
2943  FloatsMatrix& outputData )
2944  {
2945  TERP_TRUE_OR_RETURN_FALSE( outputData.reset( inputData.getLinesNumber(),
2946  inputData.getColumnsNumber() ), "Cannot allocate image matrix" );
2947 
2948  const unsigned int nLines = inputData.getLinesNumber();
2949  const unsigned int nCols = inputData.getColumnsNumber();
2950 
2951  unsigned int outCol = 0;
2952  float currSum = 0;
2953 
2954  for( unsigned int outLine = 0 ; outLine < nLines ; ++outLine )
2955  for( outCol = 0; outCol < nCols ; ++outCol )
2956  {
2957  currSum = inputData[ outLine ][ outCol ];
2958 
2959  if( outLine )
2960  currSum += outputData[ outLine - 1 ][ outCol ];
2961  if( outCol )
2962  currSum += outputData[ outLine ][ outCol - 1 ];
2963  if( outLine && outCol )
2964  currSum -= outputData[ outLine - 1 ][ outCol - 1 ];
2965 
2966  outputData[ outLine ][ outCol ] = currSum;
2967  }
2968 
2969  return true;
2970  }
2971 
2973  const InterestPointsSetT& interestPoints,
2974  const unsigned int correlationWindowWidth,
2975  const FloatsMatrix& rasterData,
2976  FloatsMatrix& features,
2977  InterestPointsSetT& validInteresPoints )
2978  {
2979  validInteresPoints.clear();
2980 
2981  /* The radius of a feature window rotated by 90 degrees.
2982  * over the input image */
2983 
2984  const unsigned int rotated90CorralationWindowRadius = (unsigned int)
2985  (
2986  std::ceil(
2987  sqrt(
2988  2
2989  *
2990  (
2991  ( (double)correlationWindowWidth )
2992  *
2993  ( (double)correlationWindowWidth )
2994  )
2995  ) / 2.0
2996  )
2997  );
2998 
2999  // Locating the the valid interest points
3000 
3001  {
3002  /* The radius of a feature window rotated by 90 degrees.
3003  * over the input image */
3004 
3005  const unsigned int rasterDataCols = rasterData.getColumnsNumber();
3006  const unsigned int rasterDataLines = rasterData.getLinesNumber();
3007  const unsigned int firstValidInterestPointX =
3008  rotated90CorralationWindowRadius + 1;
3009  const unsigned int lastValidInterestPointX = rasterDataCols
3010  - rotated90CorralationWindowRadius - 2;
3011  const unsigned int firstValidInterestPointY =
3012  rotated90CorralationWindowRadius + 1;
3013  const unsigned int lastValidInterestPointY = rasterDataLines
3014  - rotated90CorralationWindowRadius - 2;
3015 
3016  {
3017  InterestPointsSetT::const_iterator iPointsIt = interestPoints.begin();
3018  const InterestPointsSetT::const_iterator iPointsItEnd = interestPoints.end();
3019 
3020  while( iPointsIt != iPointsItEnd )
3021  {
3022  if( ( iPointsIt->m_x >= firstValidInterestPointX ) &&
3023  ( iPointsIt->m_x <= lastValidInterestPointX ) &&
3024  ( iPointsIt->m_y >= firstValidInterestPointY ) &&
3025  ( iPointsIt->m_y <= lastValidInterestPointY ) )
3026  {
3027  validInteresPoints.insert( *iPointsIt );
3028  }
3029 
3030  ++iPointsIt;
3031  }
3032  }
3033  }
3034 
3035  // Allocating the features matrix
3036 
3037  const unsigned int featureElemsNmb = correlationWindowWidth *
3038  correlationWindowWidth;
3039  const unsigned int featureSizeBytes = sizeof( float ) *
3040  featureElemsNmb;
3041 
3042  TERP_TRUE_OR_RETURN_FALSE( features.reset(
3043  validInteresPoints.size(), featureElemsNmb ),
3044  "Cannot allocate features matrix" );
3045 
3046  // Allocating the auxiliary features buffer
3047 
3048  boost::scoped_array< float > auxFeatureBufferHandler(
3049  new float[ featureElemsNmb ] );
3050  float* auxFeatureBufferPtr = auxFeatureBufferHandler.get();
3051 
3052  // Creating features
3053 
3054  unsigned int curr_window_x_start = 0; //related to the current window over the hole image
3055  unsigned int curr_window_y_start = 0; //related to the current window over the hole image
3056  unsigned int curr_window_x_center = 0; //related to the current window over the hole image
3057  unsigned int curr_window_y_center = 0; //related to the current window over the hole image
3058  unsigned int curr_window_x_end = 0; // this coord is also counted in
3059  unsigned int curr_window_y_end = 0; // this coord is also counted in
3060  const unsigned int wind_radius = correlationWindowWidth / 2; //output window radius
3061  const float wind_radius_double = (float)wind_radius;
3062  unsigned int curr_x = 0;
3063  unsigned int curr_y = 0;
3064  float curr_x_minus_radius = 0;
3065  float curr_y_minus_radius = 0;
3066  unsigned int curr_offset = 0;
3067  float int_x_dir = 0;
3068  float int_y_dir = 0;
3069  float int_norm = 0;
3070  float rotated_curr_x = 0;/* rotaded coord - window ref */
3071  float rotated_curr_y = 0;/* rotaded coord - window ref */
3072  float rot_cos = 0;
3073  float rot_sin = 0;
3074  unsigned int rotated_curr_x_img = 0; //coords rotated but in the hole image reference
3075  unsigned int rotated_curr_y_img = 0; //coords rotated but in the hole image reference
3076  float featureElementsNormalizeFactor = 0.0;
3077  unsigned int featureElementIdx = 0;
3078  float* featurePtr = 0;
3079  float featureElementValue = 0.0;
3080  float featureElementMaxValue = 0.0;
3081  float featureElementMinValue = 0.0;
3082 
3083  InterestPointsSetT::const_iterator viPointsIt = validInteresPoints.begin();
3084  const InterestPointsSetT::const_iterator viPointsItEnd = validInteresPoints.end();
3085  unsigned int validInteresPointsIndex = 0 ;
3086 
3087  while( viPointsIt != viPointsItEnd )
3088  {
3089  /* Calculating the current window position */
3090 
3091  curr_window_x_center = viPointsIt->m_x;
3092  assert( curr_window_x_center >= rotated90CorralationWindowRadius );
3093  assert( curr_window_x_center < ( rasterData.getColumnsNumber() - 1 -
3094  rotated90CorralationWindowRadius ) );
3095  curr_window_y_center = viPointsIt->m_y;
3096  assert( curr_window_y_center >= rotated90CorralationWindowRadius );
3097  assert( curr_window_y_center < ( rasterData.getLinesNumber() - 1 -
3098  rotated90CorralationWindowRadius ) );
3099 
3100  curr_window_x_start = curr_window_x_center - wind_radius;
3101  curr_window_y_start = curr_window_y_center - wind_radius;
3102  curr_window_x_end = curr_window_x_start + correlationWindowWidth - 1;
3103  curr_window_y_end = curr_window_y_start + correlationWindowWidth - 1;
3104 
3105  /* Estimating the intensity vector X direction */
3106 
3107  int_x_dir = 0;
3108 
3109  for( curr_y = curr_window_y_start ; curr_y <= curr_window_y_end ;
3110  ++curr_y )
3111  {
3112  for( curr_offset = 0 ; curr_offset < wind_radius ;
3113  ++curr_offset )
3114  {
3115  int_x_dir += rasterData( curr_y, curr_window_x_end - curr_offset ) -
3116  rasterData( curr_y, curr_window_x_start + curr_offset );
3117  }
3118  }
3119 
3120  /* Estimating the intensity vector y direction */
3121 
3122  int_y_dir = 0;
3123 
3124  for( curr_x = curr_window_x_start ; curr_x <= curr_window_x_end ;
3125  ++curr_x )
3126  {
3127  for( curr_offset = 0 ; curr_offset < wind_radius ; ++curr_offset )
3128  {
3129  int_y_dir += rasterData( curr_window_y_start + curr_offset, curr_x ) -
3130  rasterData( curr_window_y_end - curr_offset, curr_x );
3131  }
3132  }
3133 
3134  /* Calculating the rotation parameters -
3135  */
3136  int_norm = std::sqrt( ( int_x_dir * int_x_dir ) +
3137  ( int_y_dir * int_y_dir ) );
3138 
3139  if( int_norm != 0.0 ) {
3140  rot_cos = int_x_dir / int_norm;
3141  rot_sin = int_y_dir / int_norm;
3142  } else {
3143  /* No rotation */
3144  rot_cos = 1.0;
3145  rot_sin = 0.0;
3146  }
3147 
3148  assert( ( rot_cos >= -1.0 ) && ( rot_cos <= 1.0 ) );
3149  assert( ( rot_sin >= -1.0 ) && ( rot_sin <= 1.0 ) );
3150 
3151  /* Generating the rotated window data and inserting it into
3152  the img_features_matrix by setting the intensity vector
3153  to the direction (1,0)
3154 
3155  counterclockwise rotation
3156  | u | |cos -sin| |X|
3157  | v | == |sin cos| x |Y|
3158 
3159  clockwise rotation
3160  | u | |cos sin| |X|
3161  | v | == |-sin cos| x |Y|
3162  */
3163 
3164  memset( auxFeatureBufferPtr, 0, featureSizeBytes );
3165  featureElementIdx = 0;
3166  featureElementMaxValue = -1.0 * FLT_MAX;
3167  featureElementMinValue = FLT_MAX;
3168 
3169  for( curr_y = 0 ; curr_y < correlationWindowWidth ; ++curr_y )
3170  {
3171  for( curr_x = 0 ; curr_x < correlationWindowWidth ; ++curr_x )
3172  {
3173  /* briging the window to the coord system center */
3174 
3175  curr_x_minus_radius = ((float)curr_x) -
3176  wind_radius_double;
3177  curr_y_minus_radius = ((float)curr_y) -
3178  wind_radius_double;
3179 
3180  /* rotating the centered window */
3181 
3182  rotated_curr_x =
3183  ( rot_cos * curr_x_minus_radius ) +
3184  ( rot_sin * curr_y_minus_radius );
3185 
3186  rotated_curr_y =
3187  ( rot_cos * curr_y_minus_radius )
3188  - ( rot_sin * curr_x_minus_radius );
3189 
3190  /* bringing the window back to its original
3191  location with the correct new scale */
3192 
3193  rotated_curr_x += wind_radius_double;
3194  rotated_curr_y += wind_radius_double;
3195 
3196  /* copy the new rotated window to the output vector */
3197 
3198  rotated_curr_x_img = curr_window_x_start +
3199  (unsigned int)ROUND( rotated_curr_x );
3200  rotated_curr_y_img = curr_window_y_start +
3201  (unsigned int)ROUND( rotated_curr_y );
3202 
3203  featureElementValue = rasterData( rotated_curr_y_img,
3204  rotated_curr_x_img );
3205 
3206  auxFeatureBufferPtr[ featureElementIdx++ ] = featureElementValue;
3207 
3208  if( featureElementMaxValue < featureElementValue )
3209  featureElementMaxValue = featureElementValue;
3210 
3211  if( featureElementMinValue > featureElementValue )
3212  featureElementMinValue = featureElementValue;
3213 
3214  }
3215  }
3216 
3217  // feature normaliztion
3218 
3219  if( featureElementMaxValue == featureElementMinValue )
3220  featureElementsNormalizeFactor = 0.0;
3221  else
3222  featureElementsNormalizeFactor = 1.0f / ( featureElementMaxValue -
3223  featureElementMinValue );
3224 
3225  featurePtr = features[ validInteresPointsIndex ];
3226 
3227  for( featureElementIdx = 0 ; featureElementIdx < featureElemsNmb ;
3228  ++featureElementIdx )
3229  {
3230  featurePtr[ featureElementIdx ] = (
3231  ( auxFeatureBufferPtr[ featureElementIdx ] - featureElementMinValue )
3232  * featureElementsNormalizeFactor );
3233  assert( featurePtr[ featureElementIdx ] >= 0.0 );
3234  assert( featurePtr[ featureElementIdx ] <= 1.0 );
3235  }
3236 
3237  ++validInteresPointsIndex;
3238  ++viPointsIt;
3239  }
3240 
3241  return true;
3242  }
3243 
3245  const InterestPointsSetT& interestPoints,
3246  const FloatsMatrix& integralRasterData,
3247  InterestPointsSetT& validInterestPoints,
3248  FloatsMatrix& features )
3249  {
3250  // Discovering the valid interest points
3251 
3252  validInterestPoints.clear();
3253 
3254  {
3255  InterestPointsSetT::const_iterator iPointsIt = interestPoints.begin();
3256  const InterestPointsSetT::const_iterator iPointsItEnd = interestPoints.end();
3257 
3258  while( iPointsIt != iPointsItEnd )
3259  {
3260  // Calculating the current interest point variables
3261 
3262  const unsigned int& currIPointCenterX = iPointsIt->m_x;
3263  const unsigned int& currIPointCenterY = iPointsIt->m_y;
3264  const float currIPointScale = 1.2f * iPointsIt->m_feature2 / 9.0f;
3265 
3266  unsigned int featureWindowWidth = (unsigned int)( 20.0 * currIPointScale );
3267  featureWindowWidth += ( ( featureWindowWidth % 2 ) ? 0 : 1 );
3268 
3269  const unsigned int feature90DegreeRotatedWindowRadius = (unsigned int)
3270  (
3271  std::ceil(
3272  std::sqrt(
3273  2.0
3274  *
3275  (
3276  ( (double)featureWindowWidth )
3277  *
3278  ( (double)featureWindowWidth )
3279  )
3280  )
3281  ) / 2.0
3282  );
3283 
3284  const unsigned int featureElementHaarWindowRadius =
3285  ((unsigned int)( 2.0 * currIPointScale )) / 2;
3286 
3287  const unsigned int currIPointCenterXAllowedMin = featureElementHaarWindowRadius +
3288  feature90DegreeRotatedWindowRadius + 1;
3289  const unsigned int currIPointCenterXAllowedMax = integralRasterData.getColumnsNumber() -
3290  currIPointCenterXAllowedMin - 1;
3291  const unsigned int currIPointCenterYAllowedMin = currIPointCenterXAllowedMin;
3292  const unsigned int currIPointCenterYAllowedMax = integralRasterData.getLinesNumber() -
3293  currIPointCenterXAllowedMin - 1;
3294 
3295  if( ( currIPointCenterX > currIPointCenterXAllowedMin ) &&
3296  ( currIPointCenterX < currIPointCenterXAllowedMax ) &&
3297  ( currIPointCenterY > currIPointCenterYAllowedMin ) &&
3298  ( currIPointCenterY < currIPointCenterYAllowedMax ) )
3299 
3300  {
3301  validInterestPoints.insert( *iPointsIt );
3302  }
3303 
3304  ++iPointsIt;
3305  }
3306  }
3307 
3308  TERP_TRUE_OR_RETURN_FALSE( features.reset( validInterestPoints.size(), 65 ),
3309  "Cannot allocate features matrix" );
3310 
3311  // globals
3312 
3313  float auxFeaturesBuffer[ 65 ];
3314 
3315  // iterating over each input innterest point
3316 
3317  InterestPointsSetT::const_iterator iPointsIt = validInterestPoints.begin();
3318  const InterestPointsSetT::const_iterator iPointsItEnd = validInterestPoints.end();
3319  unsigned int interestPointIdx = 0;
3320  while( iPointsIt != iPointsItEnd )
3321  {
3322  // Calculating the current interest point variables
3323 
3324  const unsigned int& currIPointCenterX = iPointsIt->m_x;
3325  const unsigned int& currIPointCenterY = iPointsIt->m_y;
3326  const float currIPointScale = 1.2f * iPointsIt->m_feature2 / 9.0f;
3327 
3328  unsigned int featureWindowWidth = (unsigned int)( 20.0 * currIPointScale );
3329  featureWindowWidth += ( ( featureWindowWidth % 2 ) ? 0 : 1 );
3330 
3331  const unsigned int featureWindowRadius = featureWindowWidth / 2;
3332  const float featureWindowRadiusDouble = (float)featureWindowRadius;
3333 
3334  const unsigned int featureSubWindowWidth = featureWindowWidth / 4;
3335 
3336  const unsigned int featureElementHaarWindowRadius =
3337  ((unsigned int)( 2.0 * currIPointScale )) / 2;
3338 
3339  const unsigned int featureWindowRasterXStart = currIPointCenterX -
3340  featureWindowRadius;
3341  const unsigned int featureWindowRasterYStart = currIPointCenterY -
3342  featureWindowRadius;
3343 
3344  // Initiating the features vector
3345 
3346  unsigned int currentFeaturePtrStartIdx = 0;
3347 
3348  for( currentFeaturePtrStartIdx = 0; currentFeaturePtrStartIdx < 65 ;
3349  ++currentFeaturePtrStartIdx )
3350  auxFeaturesBuffer[ currentFeaturePtrStartIdx ] = 0.0;
3351 
3352  // Estimating the intensity vectors
3353 
3354  assert( ((long int)currIPointCenterX) -
3355  ((long int)featureWindowRadius) >= 0 );
3356  assert( ((long int)currIPointCenterY) -
3357  ((long int)featureWindowRadius) >= 0 );
3358  assert( currIPointCenterX +
3359  featureWindowRadius < integralRasterData.getColumnsNumber() );
3360  assert( currIPointCenterY +
3361  featureWindowRadius < integralRasterData.getLinesNumber() );
3362 
3363  const float currIPointXIntensity = getHaarXVectorIntensity( integralRasterData, currIPointCenterX,
3364  currIPointCenterY, featureWindowRadius );
3365  const float currIPointYIntensity = getHaarYVectorIntensity( integralRasterData, currIPointCenterX,
3366  currIPointCenterY, featureWindowRadius );
3367 
3368  // Calculating the rotation parameters
3369 
3370  const float currIPointRotationNorm = std::sqrt( ( currIPointXIntensity * currIPointXIntensity ) +
3371  ( currIPointYIntensity * currIPointYIntensity ) );
3372 
3373  float currIPointRotationSin = 0; // default: no rotation
3374  float currIPointRotationCos = 1.0; // default: no rotation
3375 
3376  if( currIPointRotationNorm != 0.0 )
3377  {
3378  currIPointRotationCos = currIPointXIntensity / currIPointRotationNorm;
3379  currIPointRotationSin = currIPointYIntensity / currIPointRotationNorm;
3380  }
3381 
3382  assert( ( currIPointRotationCos >= -1.0 ) && ( currIPointRotationCos <= 1.0 ) );
3383  assert( ( currIPointRotationSin >= -1.0 ) && ( currIPointRotationSin <= 1.0 ) );
3384 
3385 // std::cout << "angle:";
3386 // std::cout << std::atan2( currIPointRotationSin, currIPointRotationCos ) * 180.0 / M_PI << std::endl;
3387 
3388  /* The region surrounding the interest point is split up regularly
3389  into smaller 44 square rotated by the haar intensity vectors
3390  calculated above
3391 
3392  counterclockwise rotation
3393  | u | |cos -sin| |X|
3394  | v | == |sin cos| x |Y|
3395 
3396  clockwise rotation
3397  | u | |cos sin| |X|
3398  | v | == |-sin cos| x |Y|
3399  */
3400 
3401  unsigned int featureWindowYOffset = 0;
3402  unsigned int featureWindowXOffset = 0;
3403  float featureElementZeroCenteredOriginalXIdx = 0;
3404  float featureElementZeroCenteredOriginalYIdx = 0;
3405  float featureElementZeroCenteredRotatedXIdx = 0;
3406  float featureElementZeroCenteredRotatedYIdx = 0;
3407  float featureElementRotatedXIdx = 0;
3408  float featureElementRotatedYIdx = 0;
3409  unsigned int featureElementRasterRotatedXIdx = 0;
3410  unsigned int featureElementRasterRotatedYIdx = 0;
3411  float featureElementOriginalHaarXIntensity = 0;
3412  float featureElementOriginalHaarYIntensity = 0;
3413  float featureElementZeroCenteredOriginalHaarXIntensity = 0;
3414  float featureElementZeroCenteredOriginalHaarYIntensity = 0;
3415  float featureElementRotatedHaarXIntensity = 0;
3416  float featureElementRotatedHaarYIntensity = 0;
3417  float featureElementZeroCenteredRotatedHaarXIntensity = 0;
3418  float featureElementZeroCenteredRotatedHaarYIntensity = 0;
3419  unsigned int featureSubWindowYIdx = 0;
3420  unsigned int featureSubWindowXIdx = 0;
3421 
3422  for( featureWindowYOffset = 0 ; featureWindowYOffset < featureWindowWidth ;
3423  featureWindowYOffset += 5 )
3424  {
3425  featureElementZeroCenteredOriginalYIdx = ((float)featureWindowYOffset)
3426  - featureWindowRadiusDouble;
3427 
3428  featureSubWindowYIdx = featureWindowYOffset / featureSubWindowWidth;
3429 
3430  for( featureWindowXOffset = 0 ; featureWindowXOffset < featureWindowWidth ;
3431  featureWindowXOffset += 5 )
3432  {
3433  featureSubWindowXIdx = featureWindowXOffset / featureSubWindowWidth;
3434 
3435  currentFeaturePtrStartIdx = ( featureSubWindowYIdx * 4 ) +
3436  featureSubWindowXIdx;
3437 
3438  featureElementZeroCenteredOriginalXIdx = ((float)featureWindowXOffset)
3439  - featureWindowRadiusDouble;
3440 
3441  /* finding the correspondent point over the original raster
3442  using a clockwize rotation */
3443 
3444  featureElementZeroCenteredRotatedXIdx =
3445  ( currIPointRotationCos * featureElementZeroCenteredOriginalXIdx ) +
3446  ( currIPointRotationSin * featureElementZeroCenteredOriginalYIdx );
3447  featureElementZeroCenteredRotatedYIdx =
3448  ( currIPointRotationCos * featureElementZeroCenteredOriginalYIdx )
3449  - ( currIPointRotationSin * featureElementZeroCenteredOriginalXIdx );
3450 
3451  featureElementRotatedXIdx = featureElementZeroCenteredRotatedXIdx +
3452  featureWindowRadiusDouble;
3453  featureElementRotatedYIdx = featureElementZeroCenteredRotatedYIdx +
3454  featureWindowRadiusDouble;
3455 
3456  featureElementRasterRotatedXIdx = featureWindowRasterXStart +
3457  (unsigned int)ROUND( featureElementRotatedXIdx );
3458  featureElementRasterRotatedYIdx = featureWindowRasterYStart +
3459  (unsigned int)ROUND( featureElementRotatedYIdx );
3460 
3461  assert( ((long int)featureElementRasterRotatedXIdx) -
3462  ((long int)featureElementHaarWindowRadius) >= 0 );
3463  assert( ((long int)featureElementRasterRotatedYIdx) -
3464  ((long int)featureElementHaarWindowRadius) >= 0 );
3465  assert( featureElementRasterRotatedXIdx +
3466  featureElementHaarWindowRadius < integralRasterData.getColumnsNumber() );
3467  assert( featureElementRasterRotatedYIdx +
3468  featureElementHaarWindowRadius < integralRasterData.getLinesNumber() );
3469 
3470  // Finding the original haar intesity vectors
3471 
3472  featureElementOriginalHaarXIntensity = getHaarXVectorIntensity( integralRasterData,
3473  featureElementRasterRotatedXIdx, featureElementRasterRotatedYIdx,
3474  featureElementHaarWindowRadius );
3475  featureElementOriginalHaarYIntensity = getHaarYVectorIntensity( integralRasterData,
3476  featureElementRasterRotatedXIdx, featureElementRasterRotatedYIdx,
3477  featureElementHaarWindowRadius );
3478 
3479  // Rotating the intensities by the central point haar intensities vectors
3480  // usigng a counterclockwise rotation
3481 
3482  featureElementZeroCenteredOriginalHaarXIntensity = featureElementOriginalHaarXIntensity +
3483  featureElementZeroCenteredOriginalXIdx;
3484  featureElementZeroCenteredOriginalHaarYIntensity = featureElementOriginalHaarYIntensity +
3485  featureElementZeroCenteredOriginalYIdx;
3486 
3487  featureElementZeroCenteredRotatedHaarXIntensity =
3488  ( currIPointRotationCos * featureElementZeroCenteredOriginalHaarXIntensity ) +
3489  ( currIPointRotationSin * featureElementZeroCenteredOriginalHaarYIntensity );
3490  featureElementZeroCenteredRotatedHaarYIntensity =
3491  ( currIPointRotationCos * featureElementZeroCenteredOriginalHaarYIntensity )
3492  - ( currIPointRotationSin * featureElementZeroCenteredOriginalHaarXIntensity );
3493 
3494  featureElementRotatedHaarXIntensity = featureElementZeroCenteredRotatedHaarXIntensity
3495  - featureElementZeroCenteredRotatedXIdx;
3496  featureElementRotatedHaarYIntensity = featureElementZeroCenteredRotatedHaarYIntensity
3497  - featureElementZeroCenteredRotatedYIdx;
3498 
3499  // Generating the related portion inside the output features vector
3500 
3501  assert( currentFeaturePtrStartIdx < 61 );
3502 
3503  auxFeaturesBuffer[ currentFeaturePtrStartIdx ] +=
3504  featureElementRotatedHaarXIntensity;
3505  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 1 ] +=
3506  featureElementRotatedHaarYIntensity;
3507  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 2 ] +=
3508  std::abs( featureElementRotatedHaarXIntensity );
3509  auxFeaturesBuffer[ currentFeaturePtrStartIdx + 3 ] +=
3510  std::abs( featureElementRotatedHaarYIntensity );
3511  }
3512  }
3513 
3514  // turning the descriptor into a unit vector.(Invariance to contrast)
3515 
3516  float* currentFeaturePtr = features[ interestPointIdx ];
3517 
3518  float featureElementsNormalizeFactor = 0.0;
3519 
3520  for( currentFeaturePtrStartIdx = 0 ; currentFeaturePtrStartIdx < 64 ;
3521  ++currentFeaturePtrStartIdx )
3522  {
3523  featureElementsNormalizeFactor += ( auxFeaturesBuffer[ currentFeaturePtrStartIdx ]
3524  * auxFeaturesBuffer[ currentFeaturePtrStartIdx ] );
3525  }
3526 
3527  featureElementsNormalizeFactor = std::sqrt( featureElementsNormalizeFactor );
3528 
3529  if( featureElementsNormalizeFactor != 0.0 )
3530  {
3531  featureElementsNormalizeFactor = 1.0f / featureElementsNormalizeFactor;
3532  }
3533 
3534  for( currentFeaturePtrStartIdx = 0 ; currentFeaturePtrStartIdx < 64 ;
3535  ++currentFeaturePtrStartIdx )
3536  {
3537  currentFeaturePtr[ currentFeaturePtrStartIdx ] = (
3538  auxFeaturesBuffer[ currentFeaturePtrStartIdx ] *
3539  featureElementsNormalizeFactor );
3540  TERP_DEBUG_TRUE_OR_THROW( ( currentFeaturePtr[ currentFeaturePtrStartIdx ] <= 1.0 ),
3541  currentFeaturePtr[ currentFeaturePtrStartIdx ] );
3542  TERP_DEBUG_TRUE_OR_THROW( ( currentFeaturePtr[ currentFeaturePtrStartIdx ] >= -1.0 ),
3543  currentFeaturePtr[ currentFeaturePtrStartIdx ] );
3544  }
3545 
3546  // Adding an attribute based on the sign of the Laplacian to
3547  // distinguishes bright blobs
3548  // on dark backgrounds from the reverse situation.
3549 
3550  currentFeaturePtr[ 64 ] = ( iPointsIt->m_feature3 * 64.0f );
3551 
3552  ++interestPointIdx;
3553  ++iPointsIt;
3554  }
3555 
3556  return true;
3557  }
3558 
3560  const InterestPointsSetT& interestPoints,
3561  const std::string& fileNameBeginning )
3562  {
3563  const unsigned int tifLinesNumber = (unsigned int)std::sqrt( (double)
3564  features.getColumnsNumber() );
3565  const unsigned int featuresColsNumber = features.getColumnsNumber();
3566 
3567  double const* featureLinePtr = 0;
3568 
3569  InterestPointsSetT::const_iterator iIt = interestPoints.begin();
3570 
3571  for( unsigned int featuresIdx = 0 ; featuresIdx < features.getLinesNumber() ;
3572  ++featuresIdx )
3573  {
3574  featureLinePtr = features[ featuresIdx ];
3575 
3576  std::vector<te::rst::BandProperty*> bandsProperties;
3577  bandsProperties.push_back(new te::rst::BandProperty( 0, te::dt::UCHAR_TYPE, "" ));
3578  bandsProperties[0]->m_colorInterp = te::rst::RedCInt;
3579  bandsProperties[0]->m_noDataValue = 0;
3580 
3581  std::map<std::string, std::string> rInfo;
3582  rInfo["URI"] = fileNameBeginning + "_" + boost::lexical_cast< std::string >( iIt->m_x )
3583  + "_" + boost::lexical_cast< std::string >( iIt->m_y ) + ".tif";
3584 
3585  te::rst::Grid* newgrid = new te::rst::Grid( tifLinesNumber,
3586  tifLinesNumber, 0, -1 );
3587 
3588  std::auto_ptr< te::rst::Raster > outputRasterPtr(
3589  te::rst::RasterFactory::make( "GDAL", newgrid, bandsProperties, rInfo, 0, 0));
3590  TERP_TRUE_OR_THROW( outputRasterPtr.get(), "Output raster creation error");
3591 
3592  unsigned int line = 0;
3593  unsigned int col = 0;
3594  double value = 0;
3595  double min = 0;
3596  double max = 0;
3597  double gain = 1.0;
3598 
3599  for( col = 0 ; col < featuresColsNumber ; ++col )
3600  {
3601  if( min > featureLinePtr[ col ] ) min = featureLinePtr[ col ];
3602  if( max < featureLinePtr[ col ] ) max = featureLinePtr[ col ];
3603  }
3604 
3605  gain = 255.0 / ( max - min );
3606 
3607  for( line = 0 ; line < tifLinesNumber ; ++line )
3608  for( col = 0 ; col < tifLinesNumber ; ++col )
3609  {
3610  value = featureLinePtr[ ( line * tifLinesNumber ) + col ];
3611  value *= gain;
3612  value -= min;
3613  value = MIN( 255.0, value );
3614  value = MAX( 0.0, value );
3615 
3616  outputRasterPtr->setValue( col, line, value, 0 );
3617  }
3618 
3619  ++iIt;
3620  }
3621  }
3622 
3624  const FloatsMatrix& featuresSet1,
3625  const FloatsMatrix& featuresSet2,
3626  const InterestPointsSetT& interestPointsSet1,
3627  const InterestPointsSetT& interestPointsSet2,
3628  const unsigned int maxPt1ToPt2Distance,
3629  const unsigned int enableMultiThread,
3630  const double minAllowedAbsCorrelation,
3631  MatchedInterestPointsSetT& matchedPoints )
3632  {
3633  matchedPoints.clear();
3634 
3635  const unsigned int interestPointsSet1Size = interestPointsSet1.size();
3636  if( interestPointsSet1Size == 0 ) return true;
3637 
3638  const unsigned int interestPointsSet2Size = interestPointsSet2.size();
3639  if( interestPointsSet2Size == 0 ) return true;
3640 
3641  assert( featuresSet1.getColumnsNumber() == featuresSet2.getColumnsNumber() );
3642  assert( featuresSet1.getLinesNumber() == interestPointsSet1Size );
3643  assert( featuresSet2.getLinesNumber() == interestPointsSet2Size );
3644 
3645  // Creating internal objects
3646 
3647  InterestPointsSetT::const_iterator it1 = interestPointsSet1.begin();
3648  boost::scoped_array< InterestPointT > internalInterestPointsSet1(
3649  new InterestPointT[ interestPointsSet1Size ] );
3650  for( unsigned int idx1 = 0 ; idx1 < interestPointsSet1Size ; ++idx1 )
3651  {
3652  internalInterestPointsSet1[ idx1 ] = *it1;
3653 
3654  ++it1;
3655  }
3656 
3657  InterestPointsSetT::const_iterator it2 = interestPointsSet2.begin();
3658  boost::scoped_array< InterestPointT > internalInterestPointsSet2(
3659  new InterestPointT[ interestPointsSet2Size ] );
3660  for( unsigned int idx2 = 0 ; idx2 < interestPointsSet2Size ; ++idx2 )
3661  {
3662  internalInterestPointsSet2[ idx2 ] = *it2;
3663 
3664  ++it2;
3665  }
3666 
3667  // Creating the correlation matrix
3668 
3669  FloatsMatrix corrMatrix;
3670  TERP_TRUE_OR_RETURN_FALSE( corrMatrix.reset( interestPointsSet1Size,
3671  interestPointsSet2Size, FloatsMatrix::RAMMemPol ),
3672  "Error crearting the correlation matrix" );
3673 
3674  unsigned int col = 0;
3675  unsigned int line = 0;
3676  float* linePtr = 0;
3677 
3678  for( line = 0 ; line < interestPointsSet1Size ; ++line )
3679  {
3680  linePtr = corrMatrix[ line ];
3681 
3682  for( col = 0 ; col < interestPointsSet2Size ; ++col )
3683  {
3684  linePtr[ col ] = 0;
3685  }
3686  }
3687 
3688  boost::mutex syncMutex;
3689  unsigned int nextFeatureIdx1ToProcess = 0;
3690 // unsigned int nextFeatureIdx2ToProcess = 0;
3691 
3693  params.m_featuresSet1Ptr = &featuresSet1;
3694  params.m_featuresSet2Ptr = &featuresSet2;
3695  params.m_interestPointsSet1Ptr = internalInterestPointsSet1.get();
3696  params.m_interestPointsSet2Ptr = internalInterestPointsSet2.get();
3697  params.m_nextFeatureIdx1ToProcessPtr = &nextFeatureIdx1ToProcess;
3698  params.m_corrMatrixPtr = &corrMatrix;
3699  params.m_syncMutexPtr = &syncMutex;
3700  params.m_maxPt1ToPt2Distance = maxPt1ToPt2Distance;
3701 
3702  if( enableMultiThread )
3703  {
3704  TERP_TRUE_OR_RETURN_FALSE( featuresSet1.getMemPolicy() ==
3705  FloatsMatrix::RAMMemPol, "Invalid memory policy" )
3706  TERP_TRUE_OR_RETURN_FALSE( featuresSet2.getMemPolicy() ==
3707  FloatsMatrix::RAMMemPol, "Invalid memory policy" )
3708 
3709  const unsigned int procsNumber = te::common::GetPhysProcNumber();
3710 
3711  boost::thread_group threads;
3712 
3713  for( unsigned int threadIdx = 0 ; threadIdx < procsNumber ;
3714  ++threadIdx )
3715  {
3716  threads.add_thread( new boost::thread(
3718  }
3719 
3720  threads.join_all();
3721 
3722  }
3723  else
3724  {
3726  }
3727 
3728  // finding the correlation matrix maximas for each line and column
3729 
3730  std::vector< float > eachLineMaxABSValues( interestPointsSet1Size,
3731  0.0 );
3732  std::vector< unsigned int > eachLineMaxABSIndexes( interestPointsSet1Size,
3733  interestPointsSet2Size );
3734  std::vector< float > eachColMaxABSValues( interestPointsSet2Size,
3735  0.0 );
3736  std::vector< unsigned int > eachColMaxABSIndexes( interestPointsSet2Size,
3737  interestPointsSet1Size );
3738  float absValue = 0;
3739 
3740  for( line = 0 ; line < interestPointsSet1Size ; ++line )
3741  {
3742  linePtr = corrMatrix[ line ];
3743 
3744  for( col = 0 ; col < interestPointsSet2Size ; ++col )
3745  {
3746  absValue = std::abs( linePtr[ col ] );
3747 
3748  if( absValue >= minAllowedAbsCorrelation )
3749  {
3750  if( absValue > eachLineMaxABSValues[ line ] )
3751  {
3752  eachLineMaxABSValues[ line ] = absValue;
3753  eachLineMaxABSIndexes[ line ] = col;
3754  }
3755 
3756  if( absValue > eachColMaxABSValues[ col ] )
3757  {
3758  eachColMaxABSValues[ col ] = absValue;
3759  eachColMaxABSIndexes[ col ] = line;
3760  }
3761  }
3762  }
3763  }
3764 
3765  // Finding tiepoints
3766 
3767  MatchedInterestPointsT auxMatchedPoints;
3768 
3769  for( line = 0 ; line < interestPointsSet1Size ; ++line )
3770  {
3771  col = eachLineMaxABSIndexes[ line ];
3772 
3773  if( ( col < interestPointsSet2Size ) &&
3774  ( eachColMaxABSIndexes[ col ] == line ) )
3775  {
3776  auxMatchedPoints.m_point1 = internalInterestPointsSet1[ line ];
3777  auxMatchedPoints.m_point2 = internalInterestPointsSet2[ col ];
3778  auxMatchedPoints.m_feature = std::abs( corrMatrix( line, col ) );
3779 
3780  matchedPoints.insert( auxMatchedPoints );
3781  }
3782  }
3783 
3784  return true;
3785  }
3786 
3789  {
3790  assert( paramsPtr->m_featuresSet1Ptr->getMemPolicy() ==
3792  assert( paramsPtr->m_featuresSet2Ptr->getMemPolicy() ==
3794  assert( paramsPtr->m_corrMatrixPtr->getMemPolicy() ==
3796 
3797  // globals
3798 
3799  const unsigned int featureElementsNmb = paramsPtr->m_featuresSet1Ptr->getColumnsNumber();
3800  unsigned int feat2Idx = 0;
3801  float const* feat1Ptr = 0;
3802  float const* feat2Ptr = 0;
3803  float* corrMatrixLinePtr = 0;
3804  unsigned int featCol = 0;
3805  float sumAA = 0;
3806  float sumBB = 0;
3807  float cc_norm = 0;
3808  float ccorrelation = 0;
3809  te::gm::Envelope auxEnvelope;
3810 
3811  // Indexing tree building
3812 
3813  const unsigned int featuresSet1Size =
3814  paramsPtr->m_featuresSet1Ptr->getLinesNumber();
3815  const unsigned int featuresSet2Size =
3816  paramsPtr->m_featuresSet2Ptr->getLinesNumber();
3817 
3818  te::sam::rtree::Index< unsigned int > interestPointsSet2RTree;
3819 
3820  std::vector< unsigned int > selectedFeaturesSet2Indexes;
3821  unsigned int selectedFeaturesSet2IndexesSize = 0;
3822 
3823  if( paramsPtr->m_maxPt1ToPt2Distance )
3824  {
3825  for( unsigned int feat2Idx = 0 ; feat2Idx < featuresSet2Size ; ++feat2Idx )
3826  {
3827  interestPointsSet2RTree.insert(
3829  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_x,
3830  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_y,
3831  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_x,
3832  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_y ),
3833  feat2Idx );
3834  }
3835  }
3836  else
3837  {
3838  selectedFeaturesSet2Indexes.resize( featuresSet2Size );
3839  selectedFeaturesSet2IndexesSize = featuresSet2Size;
3840  for( unsigned int feat2Idx = 0 ; feat2Idx < featuresSet2Size ; ++feat2Idx )
3841  {
3842  selectedFeaturesSet2Indexes[ feat2Idx ] = feat2Idx;
3843  }
3844  }
3845 
3846  // Analysing each feature
3847 
3848  for( unsigned int feat1Idx = 0 ; feat1Idx < featuresSet1Size ; ++feat1Idx )
3849  {
3850  paramsPtr->m_syncMutexPtr->lock();
3851 
3852  if( feat1Idx == (*paramsPtr->m_nextFeatureIdx1ToProcessPtr) )
3853  {
3854  ++(*paramsPtr->m_nextFeatureIdx1ToProcessPtr);
3855 
3856  paramsPtr->m_syncMutexPtr->unlock();
3857 
3858  if( paramsPtr->m_maxPt1ToPt2Distance )
3859  {
3860  auxEnvelope.m_llx = auxEnvelope.m_urx =
3861  paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_x;
3862  auxEnvelope.m_llx -= (double)paramsPtr->m_maxPt1ToPt2Distance;
3863  auxEnvelope.m_urx += (double)paramsPtr->m_maxPt1ToPt2Distance;
3864  auxEnvelope.m_lly = auxEnvelope.m_ury =
3865  paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_y;
3866  auxEnvelope.m_lly -= (double)paramsPtr->m_maxPt1ToPt2Distance;;
3867  auxEnvelope.m_ury += (double)paramsPtr->m_maxPt1ToPt2Distance;;
3868 
3869  selectedFeaturesSet2Indexes.clear();
3870  interestPointsSet2RTree.search( auxEnvelope,
3871  selectedFeaturesSet2Indexes );
3872 
3873  selectedFeaturesSet2IndexesSize = selectedFeaturesSet2Indexes.size();
3874  }
3875 
3876  corrMatrixLinePtr = paramsPtr->m_corrMatrixPtr->operator[]( feat1Idx );
3877 
3878  feat1Ptr = paramsPtr->m_featuresSet1Ptr->operator[]( feat1Idx );
3879 
3880  for( unsigned int selectedFSIIdx = 0 ; selectedFSIIdx <
3881  selectedFeaturesSet2IndexesSize ; ++selectedFSIIdx )
3882  {
3883  feat2Idx = selectedFeaturesSet2Indexes[ selectedFSIIdx ];
3884 
3885  feat2Ptr = paramsPtr->m_featuresSet2Ptr->operator[]( feat2Idx );
3886 
3887  sumAA = 0.0;
3888  sumBB = 0.0;
3889  for( featCol = 0 ; featCol < featureElementsNmb ; ++featCol )
3890  {
3891  sumAA += feat1Ptr[ featCol ] * feat1Ptr[ featCol ];
3892  sumBB += feat2Ptr[ featCol ] * feat2Ptr[ featCol ];
3893  }
3894 
3895  cc_norm = std::sqrt( sumAA * sumBB );
3896 
3897  if( cc_norm == 0.0 )
3898  {
3899  corrMatrixLinePtr[ feat2Idx ] = 0;
3900  }
3901  else
3902  {
3903  ccorrelation = 0.0;
3904  for( featCol = 0 ; featCol < featureElementsNmb ; ++featCol )
3905  {
3906  ccorrelation += ( feat1Ptr[ featCol ] * feat2Ptr[ featCol ] ) /
3907  cc_norm;
3908  }
3909 
3910  corrMatrixLinePtr[ feat2Idx ] = ccorrelation;
3911  }
3912  }
3913  }
3914  else
3915  {
3916  paramsPtr->m_syncMutexPtr->unlock();
3917  }
3918  }
3919  }
3920 
3922  const FloatsMatrix& featuresSet1,
3923  const FloatsMatrix& featuresSet2,
3924  const InterestPointsSetT& interestPointsSet1,
3925  const InterestPointsSetT& interestPointsSet2,
3926  const unsigned int maxPt1ToPt2PixelDistance,
3927  const double maxEuclideanDist,
3928  const unsigned int enableMultiThread,
3929  MatchedInterestPointsSetT& matchedPoints )
3930  {
3931  matchedPoints.clear();
3932 
3933  const unsigned int interestPointsSet1Size = interestPointsSet1.size();
3934  if( interestPointsSet1Size == 0 ) return true;
3935 
3936  const unsigned int interestPointsSet2Size = interestPointsSet2.size();
3937  if( interestPointsSet2Size == 0 ) return true;
3938 
3939  assert( featuresSet1.getColumnsNumber() == featuresSet2.getColumnsNumber() );
3940  assert( featuresSet1.getLinesNumber() == interestPointsSet1Size );
3941  assert( featuresSet2.getLinesNumber() == interestPointsSet2Size );
3942 
3943  // Creating internal objects
3944 
3945  InterestPointsSetT::const_iterator it1 = interestPointsSet1.begin();
3946  boost::scoped_array< InterestPointT > internalInterestPointsSet1(
3947  new InterestPointT[ interestPointsSet1Size ] );
3948  for( unsigned int idx1 = 0 ; idx1 < interestPointsSet1Size ; ++idx1 )
3949  {
3950  internalInterestPointsSet1[ idx1 ] = *it1;
3951  ++it1;
3952  }
3953 
3954  InterestPointsSetT::const_iterator it2 = interestPointsSet2.begin();
3955  boost::scoped_array< InterestPointT > internalInterestPointsSet2(
3956  new InterestPointT[ interestPointsSet2Size ] );
3957  for( unsigned int idx2 = 0 ; idx2 < interestPointsSet2Size ; ++idx2 )
3958  {
3959  internalInterestPointsSet2[ idx2 ] = *it2;
3960  ++it2;
3961  }
3962 
3963  // Creating the distances matrix
3964 
3965  FloatsMatrix distMatrix;
3966  TERP_TRUE_OR_RETURN_FALSE( distMatrix.reset( interestPointsSet1Size,
3967  interestPointsSet2Size, FloatsMatrix::RAMMemPol ),
3968  "Error crearting the correlation matrix" );
3969 
3970  unsigned int col = 0;
3971  unsigned int line = 0;
3972  float* linePtr = 0;
3973 
3974  for( line = 0 ; line < interestPointsSet1Size ; ++line )
3975  {
3976  linePtr = distMatrix[ line ];
3977 
3978  for( col = 0 ; col < interestPointsSet2Size ; ++col )
3979  {
3980  linePtr[ col ] = FLT_MAX;
3981  }
3982  }
3983 
3984  boost::mutex syncMutex;
3985  unsigned int nextFeatureIdx1ToProcess = 0;
3986 
3988  params.m_featuresSet1Ptr = &featuresSet1;
3989  params.m_featuresSet2Ptr = &featuresSet2;
3990  params.m_interestPointsSet1Ptr = internalInterestPointsSet1.get();
3991  params.m_interestPointsSet2Ptr = internalInterestPointsSet2.get();
3992  params.m_nextFeatureIdx1ToProcessPtr = &nextFeatureIdx1ToProcess;
3993  params.m_distMatrixPtr = &distMatrix;
3994  params.m_syncMutexPtr = &syncMutex;
3995  params.m_maxPt1ToPt2Distance = maxPt1ToPt2PixelDistance;
3996 
3997  if( enableMultiThread )
3998  {
3999  TERP_TRUE_OR_RETURN_FALSE( featuresSet1.getMemPolicy() ==
4000  FloatsMatrix::RAMMemPol, "Invalid memory policy" )
4001  TERP_TRUE_OR_RETURN_FALSE( featuresSet2.getMemPolicy() ==
4002  FloatsMatrix::RAMMemPol, "Invalid memory policy" )
4003 
4004  const unsigned int procsNumber = te::common::GetPhysProcNumber();
4005 
4006  boost::thread_group threads;
4007 
4008  for( unsigned int threadIdx = 0 ; threadIdx < procsNumber ;
4009  ++threadIdx )
4010  {
4011  threads.add_thread( new boost::thread(
4013  }
4014 
4015  threads.join_all();
4016 
4017  }
4018  else
4019  {
4021  }
4022 
4023  // finding the distances matrix minimum for each line and column
4024 
4025  std::vector< float > eachLineMinValues( interestPointsSet1Size,
4026  FLT_MAX );
4027  std::vector< unsigned int > eachLineMinIndexes( interestPointsSet1Size,
4028  interestPointsSet2Size );
4029  std::vector< float > eachColMinValues( interestPointsSet2Size,
4030  FLT_MAX );
4031  std::vector< unsigned int > eachColMinIndexes( interestPointsSet2Size,
4032  interestPointsSet1Size );
4033  float maxDistValue = FLT_MAX * (-1.0);
4034 
4035  for( line = 0 ; line < interestPointsSet1Size ; ++line )
4036  {
4037  linePtr = distMatrix[ line ];
4038 
4039  for( col = 0 ; col < interestPointsSet2Size ; ++col )
4040  {
4041  const float& value = linePtr[ col ];
4042 
4043  if( value <= maxEuclideanDist )
4044  {
4045  if( value < eachLineMinValues[ line ] )
4046  {
4047  eachLineMinValues[ line ] = value;
4048  eachLineMinIndexes[ line ] = col;
4049  }
4050 
4051  if( value < eachColMinValues[ col ] )
4052  {
4053  eachColMinValues[ col ] = value;
4054  eachColMinIndexes[ col ] = line;
4055  }
4056 
4057  if( value > maxDistValue ) maxDistValue = value;
4058  }
4059  }
4060  }
4061 
4062  if( maxDistValue == 0.0 ) maxDistValue = 1.0;
4063 
4064  // Finding tiepoints
4065 
4066  MatchedInterestPointsT auxMatchedPoints;
4067 
4068  for( line = 0 ; line < interestPointsSet1Size ; ++line )
4069  {
4070  col = eachLineMinIndexes[ line ];
4071 
4072  if( ( col < interestPointsSet2Size ) &&
4073  ( eachColMinIndexes[ col ] == line ) )
4074  {
4075  const float& distValue = distMatrix( line, col );
4076 
4077  auxMatchedPoints.m_point1 = internalInterestPointsSet1[ line ];
4078  auxMatchedPoints.m_point2 = internalInterestPointsSet2[ col ],
4079  auxMatchedPoints.m_feature = ( maxDistValue - distValue ) /
4080  maxDistValue;
4081 
4082  matchedPoints.insert( auxMatchedPoints );
4083  }
4084  }
4085 
4086  return true;
4087  }
4088 
4091  {
4092  assert( paramsPtr->m_featuresSet1Ptr->getMemPolicy() ==
4094  assert( paramsPtr->m_featuresSet2Ptr->getMemPolicy() ==
4096  assert( paramsPtr->m_distMatrixPtr->getMemPolicy() ==
4098  assert( paramsPtr->m_featuresSet1Ptr->getColumnsNumber() ==
4099  paramsPtr->m_featuresSet2Ptr->getColumnsNumber() );
4100 
4101  // Glogals
4102 
4103  const unsigned int featureElementsNmb = paramsPtr->m_featuresSet1Ptr->getColumnsNumber();
4104  unsigned int feat2Idx = 0;
4105  float const* feat1Ptr = 0;
4106  float const* feat2Ptr = 0;
4107  float* corrMatrixLinePtr = 0;
4108  unsigned int featCol = 0;
4109  te::gm::Envelope auxEnvelope;
4110  float diff = 0;
4111  float euclideanDist = 0;
4112 
4113  // initializing the features 2 indexing
4114 
4115  const unsigned int featuresSet1Size =
4116  paramsPtr->m_featuresSet1Ptr->getLinesNumber();
4117  const unsigned int featuresSet2Size =
4118  paramsPtr->m_featuresSet2Ptr->getLinesNumber();
4119 
4120  te::sam::rtree::Index< unsigned int > interestPointsSet2RTree;
4121 
4122  std::vector< unsigned int > selectedFeaturesSet2Indexes;
4123  unsigned int selectedFeaturesSet2IndexesSize = 0;
4124 
4125  if( paramsPtr->m_maxPt1ToPt2Distance )
4126  {
4127  for( unsigned int feat2Idx = 0 ; feat2Idx < featuresSet2Size ; ++feat2Idx )
4128  {
4129  interestPointsSet2RTree.insert(
4131  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_x,
4132  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_y,
4133  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_x,
4134  paramsPtr->m_interestPointsSet2Ptr[ feat2Idx ].m_y ),
4135  feat2Idx );
4136  }
4137  }
4138  else
4139  {
4140  selectedFeaturesSet2Indexes.resize( featuresSet2Size );
4141  selectedFeaturesSet2IndexesSize = featuresSet2Size;
4142  for( unsigned int feat2Idx = 0 ; feat2Idx < featuresSet2Size ; ++feat2Idx )
4143  {
4144  selectedFeaturesSet2Indexes[ feat2Idx ] = feat2Idx;
4145  }
4146  }
4147 
4148  // Analysing each feature
4149 
4150  for( unsigned int feat1Idx = 0 ; feat1Idx < featuresSet1Size ; ++feat1Idx )
4151  {
4152  paramsPtr->m_syncMutexPtr->lock();
4153 
4154  if( feat1Idx == (*paramsPtr->m_nextFeatureIdx1ToProcessPtr) )
4155  {
4156  ++(*paramsPtr->m_nextFeatureIdx1ToProcessPtr);
4157 
4158  paramsPtr->m_syncMutexPtr->unlock();
4159 
4160  if( paramsPtr->m_maxPt1ToPt2Distance )
4161  {
4162  auxEnvelope.m_llx = auxEnvelope.m_urx =
4163  paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_x;
4164  auxEnvelope.m_llx -= (double)paramsPtr->m_maxPt1ToPt2Distance;
4165  auxEnvelope.m_urx += (double)paramsPtr->m_maxPt1ToPt2Distance;
4166  auxEnvelope.m_lly = auxEnvelope.m_ury =
4167  paramsPtr->m_interestPointsSet1Ptr[ feat1Idx ].m_y;
4168  auxEnvelope.m_lly -= (double)paramsPtr->m_maxPt1ToPt2Distance;;
4169  auxEnvelope.m_ury += (double)paramsPtr->m_maxPt1ToPt2Distance;;
4170 
4171  selectedFeaturesSet2Indexes.clear();
4172  interestPointsSet2RTree.search( auxEnvelope,
4173  selectedFeaturesSet2Indexes );
4174 
4175  selectedFeaturesSet2IndexesSize = selectedFeaturesSet2Indexes.size();
4176  }
4177 
4178  corrMatrixLinePtr = paramsPtr->m_distMatrixPtr->operator[]( feat1Idx );
4179 
4180  feat1Ptr = paramsPtr->m_featuresSet1Ptr->operator[]( feat1Idx );
4181 
4182  for( unsigned int selectedFSIIdx = 0 ; selectedFSIIdx <
4183  selectedFeaturesSet2IndexesSize ; ++selectedFSIIdx )
4184  {
4185  feat2Idx = selectedFeaturesSet2Indexes[ selectedFSIIdx ];
4186 
4187  feat2Ptr = paramsPtr->m_featuresSet2Ptr->operator[]( feat2Idx );
4188 
4189  euclideanDist = 0.0;
4190 
4191  for( featCol = 0 ; featCol < featureElementsNmb ; ++featCol )
4192  {
4193  diff = feat1Ptr[ featCol ] - feat2Ptr[ featCol ];
4194  euclideanDist += ( diff * diff );
4195  }
4196 
4197  euclideanDist = std::sqrt( euclideanDist );
4198 
4199  corrMatrixLinePtr[ feat2Idx ] = euclideanDist;
4200  }
4201  }
4202  else
4203  {
4204  paramsPtr->m_syncMutexPtr->unlock();
4205  }
4206  }
4207  }
4208 
4209  void TiePointsLocator::printBuffer( double** buffer, const unsigned int nLines,
4210  const unsigned int nCols )
4211  {
4212  std::cout << std::endl;
4213 
4214  for( unsigned int line = 0 ; line < nLines ; ++line )
4215  {
4216  std::cout << std::endl << "[";
4217 
4218  for( unsigned int col = 0 ; col < nCols ; ++col )
4219  {
4220  std::cout << " " << buffer[ line ][ col ];
4221  }
4222 
4223  std::cout << "]";
4224  }
4225 
4226  std::cout << std::endl;
4227  }
4228 
4229  } // end namespace rp
4230 } // end namespace te
4231 
void clear()
Clear all allocated resources and go back to the initial default parameters.
Definition: Matrix.h:642
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...
The parameters passed to the matchCorrelationEuclideanThreadEntry method.
std::vector< te::gm::GTParameters::TiePoint > m_tiePoints
The generated tie-pionts (te::gm::GTParameters::TiePoint::first are raster 1 line/column indexes...
double m_geomTransfMaxError
The maximum allowed transformation error (pixel units, default:2).
bool m_enableGeometryFilter
Enable/disable the geometry filter/outliers remotion (default:true).
const InputParameters & operator=(const InputParameters &params)
std::vector< TiePoint > m_tiePoints
Tie points.
Definition: GTParameters.h:95
bool m_enableProgress
Enable/Disable the progress interface (default:false).
static void executeMatchingByEuclideanDistThreadEntry(ExecuteMatchingByEuclideanDistThreadEntryParams *paramsPtr)
Correlation/Euclidean match thread entry.
virtual void getValue(unsigned int c, unsigned int r, double &value) const =0
Returns the cell attribute value.
AbstractParameters * clone() const
Create a clone copy of this instance.
boost::mutex * m_rastaDataAccessMutexPtr
A pointer to a valid mutex to controle raster data access.
void reset()
Clear all internal allocated objects and reset the algorithm to its initial state.
double m_pixelSizeXRelation
The pixel resolution relation m_pixelSizeXRelation = raster1_pixel_res_x / raster2_pixel_res_x (defau...
te::rst::Interpolator::Method m_interpMethod
The raster interpolator method (default:NearestNeighbor).
unsigned int m_moravecGaussianFilterIterations
The number of noise Gaussin iterations, when applicable (used to remove image noise, zero will disable the Gaussian Filter, default:1).
A raster band description.
Definition: BandProperty.h:61
A class that represents an R-tree.
Definition: Index.h:56
bool executeMoravec(const double raster1XRescFact, const double raster1YRescFact, const double raster2XRescFact, const double raster2YRescFact, te::common::TaskProgress *progressPtr, TiePointsLocator::OutputParameters *outParamsPtr, std::vector< double > &tiePointsWeights)
Executes the Moravec algorithm using the supplied parameters.
std::multiset< InterestPointT > InterestPointsSetT
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
double m_surfMaxNormEuclideanDist
The maximum acceptable euclidean distance when matching features (when applicable), default:0.5, valid range: [0,1].
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
unsigned int m_maxPt1ToPt2Distance
Zero (disabled) or the maximum distance between a point from set 1 to a point from set 1 (points beyo...
It interpolates one pixel based on a selected algorithm. Methods currently available are Nearest Neig...
Definition: Interpolator.h:54
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
TiePointsLocator input parameters.
Raster Processing algorithm output parameters base interface.
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
#define MIN(a, b)
Macro that returns min between two values.
boost::mutex * m_interestPointsAccessMutexPtr
A pointer to a valid mutex to control the output interest points container access.
unsigned int m_raster1TargetAreaLineStart
The first line of the raster 1 target area to process (default:0 - The entire raster will be consider...
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
Red channel color interpretation.
Definition: Enums.h:59
unsigned int m_maxRasterLinesBlockMaxSize
The maximum lines number of each raster block to process.
unsigned int m_maxInterestPointsPerRasterLinesBlock
The maximum number of points to find for each raster lines block.
static bool generateCorrelationFeatures(const InterestPointsSetT &interestPoints, const unsigned int correlationWindowWidth, const FloatsMatrix &rasterData, FloatsMatrix &features, InterestPointsSetT &validInteresPoints)
Generate correlation features ( normalized - unit vector ) matrix for the given interes points...
unsigned int m_octavesNumber
The number of octaves to generate (minimum:1).
void getValue(const double &c, const double &r, std::complex< double > &v, const std::size_t &b)
Get the interpolated value at specific band.
Definition: Interpolator.h:96
unsigned int m_scalesNumber
Thread return value pointer.
bool execute(AlgorithmOutputParameters &outputParams)
Executes the algorithm using the supplied parameters.
#define MAX(a, b)
Macro that returns max between two values.
boost::mutex * m_rastaDataAccessMutexPtr
A pointer to a valid mutex to controle raster data access.
double m_moravecMinAbsCorrelation
The minimum acceptable absolute correlation value when matching features (when applicable), default:0.5, valid range: [0,1].
std::pair< Coord2D, Coord2D > TiePoint
Tie point type definition.
Definition: GTParameters.h:59
2D Geometric transformation tie-points filter (outliers remotion).
Definition: GTFilter.h:52
unsigned int m_raster2TargetAreaWidth
The raster 2 target area width (default:0 - The entire raster will be considered).
double m_rastersRescaleFactor
Global rescale factor to apply to all input rasters (default:1, valid range: non-zero positive values...
unsigned int m_raster2TargetAreaLineStart
The first line of the raster 2 target area to process (default:0 - The entire raster will be consider...
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
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...
const Algorithm & operator=(const Algorithm &)
Definition: Algorithm.cpp:43
te::common::AccessPolicy getAccessPolicy() const
Returns the raster access policy.
Definition: Raster.cpp:89
static bool locateMoravecInterestPoints(const FloatsMatrix &rasterData, UCharsMatrix const *maskRasterDataPtr, const unsigned int moravecWindowWidth, const unsigned int maxInterestPoints, const unsigned int enableMultiThread, InterestPointsSetT &interestPoints)
Moravec interest points locator.
bool locateSurfInterestPoints(const FloatsMatrix &integralRasterData, UCharsMatrix const *maskRasterDataPtr, InterestPointsSetT &interestPoints) const
SURF interest points locator.
unsigned int m_moravecCorrelationWindowWidth
The correlation window width used to correlate points between the images (minimum 3...
static bool generateSurfFeatures(const InterestPointsSetT &interestPoints, const FloatsMatrix &integralRasterData, InterestPointsSetT &validInterestPoints, FloatsMatrix &features)
Generate a Surf features matrix for the given interes points.
TECOMMONEXPORT unsigned int GetPhysProcNumber()
Returns the number of physical processors.
std::vector< unsigned int > m_inRaster2Bands
Bands to be used from the input raster 2.
unsigned int * m_nextRasterLinesBlockToProcessValuePtr
A pointer to a valid counter to control the blocks processing sequence.
bool applyRansac(const std::string &transfName, const GTParameters &inputParams, const double maxDirectMapError, const double maxInverseMapError, const RansacItCounterT &maxIterations, const double &assurance, const bool enableMultiThread, const std::vector< double > &tiePointsWeights, std::vector< te::gm::GTParameters::TiePoint > &outTiePoints, std::auto_ptr< GeometricTransformation > &outTransf)
Apply a RANSAC based outliers remotion strategy.
Definition: GTFilter.cpp:199
unsigned int m_moravecWindowWidth
The Moravec window width used to locate canditate tie-points (minimum 3, default: 5 )...
te::rst::Raster const * m_inRaster1Ptr
Input raster 1.
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
static bool createIntegralImage(const FloatsMatrix &inputData, FloatsMatrix &outputData)
Create an integral image.
static void locateMoravecInterestPointsThreadEntry(MoravecLocatorThreadParams *paramsPtr)
Movavec locator thread entry.
TiePointsLocator::InputParameters m_inputParameters
TiePointsLocator input execution parameters.
static void executeMatchingByCorrelationThreadEntry(ExecuteMatchingByCorrelationThreadEntryParams *paramsPtr)
Correlation/Euclidean match thread entry.
unsigned int m_surfScalesNumber
The number of sub-sampling scales to generate, when applicable (default:4, minimum:3).
unsigned int m_maxTiePoints
The maximum number of tie-points to generate (default=0 - Automatically found).
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
std::auto_ptr< te::gm::GeometricTransformation > m_transformationPtr
The generated geometric transformation with the base mininum required tie-points set ( depending on t...
TECOMMONEXPORT unsigned long int GetUsedVirtualMemory()
Returns the amount of used virtual memory (bytes) for the current process (physical + swapped)...
An abstract class for raster data strucutures.
Definition: Raster.h:71
unsigned int m_maxPt1ToPt2Distance
Zero (disabled) or the maximum distance between a point from set 1 to a point from set 1 (points beyo...
unsigned int getNumberOfRows() const
Returns the raster number of rows.
Definition: Raster.cpp:208
#define TERP_LOG_AND_THROW(message)
Logs a error message and throws.
Definition: Macros.h:138
std::multiset< MatchedInterestPointsT > MatchedInterestPointsSetT
unsigned int getColumnsNumber() const
The number of current matrix columns.
Definition: Matrix.h:678
static unsigned int getSurfFilterSize(const unsigned int &octaveIndex, const unsigned int &scaleIndex)
Return the surf octave filter size (width).
static void features2Tiff(const DoublesMatrix &features, const InterestPointsSetT &interestPoints, const std::string &fileNameBeginning)
Save the generated features to tif files.
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
unsigned int * m_nextRasterLinesBlockToProcessValuePtr
A pointer to a valid counter to control the blocks processing sequence.
std::string m_geomTransfName
The name of the geometric transformation used to ensure tie-points consistency (see each te::gm::GTFa...
The parameters passed to the executeMatchingByEuclideanDistThreadEntry method.
InterestPointsSetT * m_interestPointsPtr
A pointer to a valid interest points container.
bool executeSurf(const double raster1XRescFact, const double raster1YRescFact, const double raster2XRescFact, const double raster2YRescFact, te::common::TaskProgress *progressPtr, TiePointsLocator::OutputParameters *outParamsPtr, std::vector< double > &tiePointsWeights)
Executes the SURF algorithm using the supplied parameters.
static bool executeMatchingByCorrelation(const FloatsMatrix &featuresSet1, const FloatsMatrix &featuresSet2, const InterestPointsSetT &interestPointsSet1, const InterestPointsSetT &interestPointsSet2, const unsigned int maxPt1ToPt2PixelDistance, const unsigned int enableMultiThread, const double minAllowedAbsCorrelation, MatchedInterestPointsSetT &matchedPoints)
Match each feature using correlation.
static bool applyMeanFilter(const FloatsMatrix &inputData, FloatsMatrix &outputData, const unsigned int iterationsNumber)
Mean Filter.
A raster band description.
Definition: Band.h:63
unsigned int m_maxInterestPointsPerRasterLinesBlock
The maximum number of points to find for each raster lines block for each scale.
unsigned int m_raster1TargetAreaWidth
The raster 1 target area width (default:0 - The entire raster will be considered).
int search(const te::gm::Envelope &mbr, std::vector< DATATYPE > &report) const
Range search query.
Definition: Index.h:326
static void locateSurfInterestPointsThreadEntry(SurfLocatorThreadParams *paramsPtr)
Surf locator thread entry.
static GeometricTransformation * make(const std::string &factoryKey)
It creates an object with the appropriated factory.
TiePointsLocator output parameters.
unsigned int m_raster1TargetAreaColStart
The first column of the raster 2 target area to process (default:0 - The entire raster will be consid...
double m_pixelSizeYRelation
The pixel resolution relation m_pixelSizeYRelation = raster1_pixel_res_y / raster2_pixel_res_y (defau...
void reset()
Reset (clear) the active instance data.
Definition: Matrix.h:480
unsigned int m_raster2TargetAreaColStart
The first column of the raster 2 target area to process (default:0 - The entire raster will be consid...
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
float m_feature3
Interest point feature 3 value.
static void createTifFromMatrix(const DoublesMatrix &rasterData, const InterestPointsSetT &interestPoints, const std::string &tifFileName)
Moravec interest points locator.
boost::mutex * m_interestPointsAccessMutexPtr
A pointer to a valid mutex to control the output interest points container access.
bool m_isInitialized
Tells if this instance is initialized.
float m_feature2
Interest point feature 2 value.
Abstract parameters base interface.
Method
Allowed interpolation methods.
Definition: Interpolator.h:61
const OutputParameters & operator=(const OutputParameters &params)
#define TERP_LOG_AND_RETURN_FALSE(message)
Logs a warning message will and return false.
Definition: Macros.h:236
InterestPointsSetT * m_interestPointsPtr
A pointer to a valid interest points container.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
UCharsMatrix const * m_maskRasterDataPtr
The loaded mask raster data pointer (or zero if no mask is avaliable).
void insert(const te::gm::Envelope &mbr, const DATATYPE &data)
It inserts an item into the tree.
Definition: Index.h:313
static bool executeMatchingByEuclideanDist(const FloatsMatrix &featuresSet1, const FloatsMatrix &featuresSet2, const InterestPointsSetT &interestPointsSet1, const InterestPointsSetT &interestPointsSet2, const unsigned int maxPt1ToPt2PixelDistance, const double maxEuclideanDist, const unsigned int enableMultiThread, MatchedInterestPointsSetT &matchedPoints)
Match each feature using eucliean distance.
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
float m_feature1
Interest point feature 1 value.
static const factory_type * find(const std::string &factoryKey)
A generic template matrix.
Definition: Matrix.h:51
static Raster * make()
It creates and returns an empty raster with default raster driver.
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 rescaleFactorX, const double rescaleFactorY, const te::rst::Interpolator::Method rasterInterpMethod, const unsigned char maxMemPercentUsage, std::vector< boost::shared_ptr< FloatsMatrix > > &loadedRasterData, UCharsMatrix &loadedMaskRasterData)
Load rasters data (normalized between 0 and 1).
unsigned int m_moravecWindowWidth
Thread return value pointer.
TemplateElementType ElementTypeT
Public matrix element type definition.
Definition: Matrix.h:57
TiePointsLocator locator.
Raster Processing algorithm input parameters base interface.
te::rst::Raster const * m_inMaskRaster2Ptr
Optional one band input mask raster 2 (tie-points will not be generated inside mask image areas marke...
2D Geometric transformation parameters.
Definition: GTParameters.h:50
#define ROUND(x)
Minimum of two values.
Definition: Macros.h:395
FloatsMatrix const * m_rasterDataPtr
The loaded raster data.
unsigned int m_maxR1ToR2Offset
The maximum offset (pixels units) between a raster 1 point end the respective raster 2 point (default...
TECOMMONEXPORT unsigned long int GetTotalPhysicalMemory()
Returns the amount of total physical memory (bytes).
double m_geometryFilterAssurance
Geometry assurance (the error-free selection percent assurance) - valid range (0-1) - default:0...
Near neighborhood interpolation method.
Definition: Interpolator.h:63
UCharsMatrix const * m_maskRasterDataPtr
The loaded mask raster data pointer (or zero if no mask is avaliable).
bool m_enableMultiThread
Enable/Disable the use of multi-threads (default:true).
#define TERP_DEBUG_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:356
Blue channel color interpretation.
Definition: Enums.h:61
unsigned int m_maxRasterLinesBlockMaxSize
The maximum lines number of each raster block to process.
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
bool isInitialized() const
Returns true if the algorithm instance is initialized and ready for execution.
Green channel color interpretation.
Definition: Enums.h:60
std::vector< unsigned int > m_inRaster1Bands
Bands to be used from the input raster 1.
unsigned int m_surfOctavesNumber
The number of octaves to generate, when applicable (default: 3, minimum:1).
unsigned int m_raster1TargetAreaHeight
The raster 1 target area height (default:0 - The entire raster will be considered).
static void roolUpBuffer(BufferElementT **bufferPtr, const unsigned int &bufferLinesNumber)
RoolUp a buffer of lines.
static bool applyGaussianFilter(const DoublesMatrix &inputData, DoublesMatrix &outputData, const unsigned int iterationsNumber)
Gaussian Filter.
unsigned int getLinesNumber() const
The number of current matrix lines.
Definition: Matrix.h:671
InteresPointsLocationStrategyType m_interesPointsLocationStrategy
The strategy used to locate interest points (default:SurfStrategyT).
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...
FloatsMatrix const * m_integralRasterDataPtr
The integral image raster data.
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.
unsigned int m_raster2TargetAreaHeight
The raster 2 target area height (default:0 - The entire raster will be considered).
The parameters passed to the surfLocatorThreadEntry method.
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.
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:149
te::rst::Raster const * m_inMaskRaster1Ptr
Optional one band input mask raster 1 (tie-points will not be generated inside mask image areas marke...
bool initialize(const AlgorithmInputParameters &inputParams)
Initialize the algorithm instance making it ready for execution.
static void printBuffer(double **buffer, const unsigned int nLines, const unsigned int nCols)
Print the given buffer to std::out.
TECOMMONEXPORT unsigned long int GetTotalVirtualMemory()
Returns the amount of total virtual memory (bytes) that can be claimed by the current process (physic...
AbstractParameters * clone() const
Create a clone copy of this instance.
The parameters passed to the moravecLocatorThreadEntry method.