All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SegmenterRegionGrowingStrategy.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/SegmenterRegionGrowingStrategy.cpp
22  \briefRaster region growing segmenter strategy.
23 */
24 
26 
27 #include "Macros.h"
28 
29 #include "../raster/Band.h"
30 #include "../raster/BandProperty.h"
31 #include "../raster/RasterFactory.h"
32 #include "../raster/Grid.h"
33 #include "../datatype/Enums.h"
34 #include "../common/StringUtils.h"
35 #include "../common/progress/TaskProgress.h"
36 
37 #include <algorithm>
38 #include <cfloat>
39 #include <cmath>
40 #include <cstring>
41 #include <limits>
42 
43 #include <boost/lexical_cast.hpp>
44 
45 // Baatz Edge Lengh
46 #define BAATZ_EL( featPtr ) featPtr[ 0 ]
47 
48 // Baatz Compactness
49 #define BAATZ_CO( featPtr ) featPtr[ 1 ]
50 
51 // Baatz Smoothness
52 #define BAATZ_SM( featPtr ) featPtr[ 2 ]
53 
54 // Baatz sums
55 #define BAATZ_SU( featPtr, band ) featPtr[ 3 + band ]
56 
57 // Baatz square sums
58 #define BAATZ_SS( featPtr, bandsNmb, band ) featPtr[ 3 + bandsNmb + band ]
59 
60 // Baatz stddev
61 #define BAATZ_ST( featPtr, bandsNmb, band ) featPtr[ 3 + bandsNmb + bandsNmb + band ]
62 
63 namespace
64 {
66  segmenterRegionGrowingStrategyFactoryInstance;
67 }
68 
69 namespace te
70 {
71  namespace rp
72  {
73  //-------------------------------------------------------------------------
74 
76  {
77  reset();
78  }
79 
81  {
82  }
83 
87  {
88  reset();
89 
90  m_minSegmentSize = params.m_minSegmentSize;
91  m_segmentsSimilarityThreshold = params.m_segmentsSimilarityThreshold;
92  m_segmentFeatures = params.m_segmentFeatures;
93  m_bandsWeights = params.m_bandsWeights;
94  m_colorWeight = params.m_colorWeight;
95  m_compactnessWeight = params.m_compactnessWeight;
96  m_segmentsSimIncreaseSteps = params.m_segmentsSimIncreaseSteps;
97 
98  return *this;
99  }
100 
102  throw( te::rp::Exception )
103  {
104  m_minSegmentSize = 100;
105  m_segmentsSimilarityThreshold = 0.1;
106  m_segmentFeatures = InvalidFeaturesType;
107  m_bandsWeights.clear();
108  m_colorWeight = 0.75;
109  m_compactnessWeight = 0.5;
110  m_segmentsSimIncreaseSteps = 10;
111  }
112 
114  {
116  }
117 
118  //-------------------------------------------------------------------------
119 
121  {
122  }
123 
125  {
126  }
127 
128  //-------------------------------------------------------------------------
129 
130  SegmenterRegionGrowingStrategy::MeanMerger::MeanMerger( const unsigned int featuresNumber )
131  : m_featuresNumber( featuresNumber )
132  {
133  }
134 
136  {
137  }
138 
140  SegmenterRegionGrowingSegment const * const segment1Ptr,
141  SegmenterRegionGrowingSegment const * const segment2Ptr,
142  SegmenterRegionGrowingSegment * const ) const
143  {
144  assert( segment1Ptr );
145  assert( segment1Ptr->m_features );
146  assert( segment2Ptr );
147  assert( segment2Ptr->m_features );
148 
149  m_getDissimilarity_dissValue = 0.0;
150 
151  for( m_getDissimilarity_meansIdx = 0 ; m_getDissimilarity_meansIdx < m_featuresNumber ;
152  ++m_getDissimilarity_meansIdx )
153  {
154  m_getDissimilarity_diffValue = segment1Ptr->m_features[ m_getDissimilarity_meansIdx ] -
155  segment2Ptr->m_features[ m_getDissimilarity_meansIdx ];
156 
157  m_getDissimilarity_dissValue += ( m_getDissimilarity_diffValue * m_getDissimilarity_diffValue );
158  }
159 
160  m_getDissimilarity_dissValue = std::sqrt( m_getDissimilarity_dissValue );
161 
162  return m_getDissimilarity_dissValue;
163  }
164 
166  SegmenterRegionGrowingSegment * const segment1Ptr,
167  SegmenterRegionGrowingSegment const * const segment2Ptr,
168  SegmenterRegionGrowingSegment const * const ) const
169  {
170  assert( segment1Ptr );
171  assert( segment1Ptr->m_features );
172  assert( segment2Ptr );
173  assert( segment2Ptr->m_features );
174 
175  // Merging basic features
176 
177  segment1Ptr->m_size += segment2Ptr->m_size;
178 
179  segment1Ptr->m_xStart = std::min(
180  segment1Ptr->m_xStart,
181  segment2Ptr->m_xStart );
182  segment1Ptr->m_xBound = std::max(
183  segment1Ptr->m_xBound,
184  segment2Ptr->m_xBound );
185 
186  segment1Ptr->m_yStart = std::min(
187  segment1Ptr->m_yStart,
188  segment2Ptr->m_yStart );
189  segment1Ptr->m_yBound = std::max(
190  segment1Ptr->m_yBound,
191  segment2Ptr->m_yBound );
192 
193  // Merging specific features
194 
195  for( unsigned int meansIdx = 0 ; meansIdx < m_featuresNumber ; ++meansIdx )
196  {
197  segment1Ptr->m_features[ meansIdx ] =
198  (
199  (
200  segment1Ptr->m_features[ meansIdx ]
201  *
203  )
204  +
205  (
206  segment2Ptr->m_features[ meansIdx ]
207  *
209  )
210  )
211  /
212  (
214  (
215  segment1Ptr->m_size
216  +
217  segment2Ptr->m_size
218  )
219  );
220  }
221  }
222 
223  //-------------------------------------------------------------------------
224 
226  const double& colorWeight, const double& compactnessWeight,
227  const std::vector< double >& bandsWeights,
228  const SegmentsIdsMatrixT& segmentsIds,
230  :
231  m_segmentsIds( segmentsIds ),
232  m_segmentsMatrix( segmentsMatrix ),
233  m_allSegsCompactnessOffset( 0 ),
234  m_allSegsCompactnessGain( 1.0 ),
235  m_allSegsSmoothnessOffset( 0 ),
236  m_allSegsSmoothnessGain( 0 ),
237  m_colorWeight( (SegmenterRegionGrowingSegment::FeatureType)colorWeight ),
238  m_compactnessWeight( (SegmenterRegionGrowingSegment::FeatureType)compactnessWeight )
239  {
240  m_bandsNumber = (unsigned int)bandsWeights.size();
241 
242  m_bandsWeights.resize( m_bandsNumber, 1 );
243 
244  for( unsigned int band = 0 ; band < m_bandsNumber ; ++band )
245  {
247  bandsWeights[ band ];
248  }
249  }
250 
252  {
253  }
254 
256  SegmenterRegionGrowingSegment const * const segment1Ptr,
257  SegmenterRegionGrowingSegment const * const segment2Ptr,
258  SegmenterRegionGrowingSegment * const mergePreviewSegPtr ) const
259  {
260  assert( segment1Ptr );
261  assert( segment1Ptr->m_features );
262  assert( segment2Ptr );
263  assert( segment2Ptr->m_features );
264  assert( mergePreviewSegPtr );
265 
266  // globals
267 
268  mergePreviewSegPtr->m_size = segment1Ptr->m_size +
269  segment2Ptr->m_size;
270  TERP_DEBUG_TRUE_OR_THROW( mergePreviewSegPtr->m_size,
271  "Internal error" );
274 
277 
280 
281  // Finding the form heterogeneity
282 
283  mergePreviewSegPtr->m_xStart = std::min( segment1Ptr->m_xStart,
284  segment2Ptr->m_xStart );
285  mergePreviewSegPtr->m_yStart = std::min( segment1Ptr->m_yStart,
286  segment2Ptr->m_yStart );
287  mergePreviewSegPtr->m_xBound = std::max( segment1Ptr->m_xBound,
288  segment2Ptr->m_xBound );
289  mergePreviewSegPtr->m_yBound = std::max( segment1Ptr->m_yBound,
290  segment2Ptr->m_yBound );
291 
292  assert( mergePreviewSegPtr->m_xBound > mergePreviewSegPtr->m_xStart );
293  assert( mergePreviewSegPtr->m_yBound > mergePreviewSegPtr->m_yStart );
294 
295  unsigned int touchingEdgeLength1 = 0;
296  unsigned int touchingEdgeLength2 = 0;
298  m_segmentsIds, mergePreviewSegPtr->m_xStart,
299  mergePreviewSegPtr->m_yStart,
300  mergePreviewSegPtr->m_xBound,
301  mergePreviewSegPtr->m_yBound,
302  segment1Ptr->m_id,
303  segment2Ptr->m_id,
304  touchingEdgeLength1,
305  touchingEdgeLength2 );
306 
307  BAATZ_EL( mergePreviewSegPtr->m_features ) =
308  BAATZ_EL( segment1Ptr->m_features ) - ( (SegmenterRegionGrowingSegment::FeatureType)touchingEdgeLength1 )
309  +
310  BAATZ_EL( segment2Ptr->m_features ) - ( (SegmenterRegionGrowingSegment::FeatureType)touchingEdgeLength2 );
311 
313  BAATZ_EL( mergePreviewSegPtr->m_features ) /
314  std::sqrt( sizeUnionD ) );
315 
316  BAATZ_SM( mergePreviewSegPtr->m_features ) =
317  BAATZ_EL( mergePreviewSegPtr->m_features )
318  /
320  (
321  2 * ( mergePreviewSegPtr->m_xBound - mergePreviewSegPtr->m_xStart )
322  )
323  +
324  (
325  2 * ( mergePreviewSegPtr->m_yBound - mergePreviewSegPtr->m_yStart )
326  )
327  );
328 
330  (
331  (
332  (
333  BAATZ_CO( mergePreviewSegPtr->m_features )
334  +
335  m_allSegsCompactnessOffset
336  )
337  *
338  m_allSegsCompactnessGain
339  )
340  -
341  (
342  (
343  (
344  (
345  (
346  BAATZ_CO( segment1Ptr->m_features )
347  +
348  m_allSegsCompactnessOffset
349  )
350  *
351  m_allSegsCompactnessGain
352  )
353  *
354  sizeSeg1D
355  )
356  +
357  (
358  (
359  (
360  BAATZ_CO( segment2Ptr->m_features )
361  +
362  m_allSegsCompactnessOffset
363  )
364  *
365  m_allSegsCompactnessGain
366  )
367  *
368  sizeSeg2D
369  )
370  )
371  /
372  sizeUnionD
373  )
374  );
375 
377  (
378  (
379  (
380  BAATZ_SM( mergePreviewSegPtr->m_features )
381  +
382  m_allSegsSmoothnessOffset
383  )
384  *
385  m_allSegsSmoothnessGain
386  )
387  -
388  (
389  (
390  (
391  (
392  (
393  BAATZ_SM( segment1Ptr->m_features )
394  +
395  m_allSegsSmoothnessOffset
396  )
397  *
398  m_allSegsSmoothnessGain
399  )
400  *
401  sizeSeg1D
402  )
403  +
404  (
405  (
406  (
407  BAATZ_SM( segment2Ptr->m_features )
408  +
409  m_allSegsSmoothnessOffset
410  )
411  *
412  m_allSegsSmoothnessGain
413  )
414  *
415  sizeSeg2D
416  )
417  )
418  /
419  sizeUnionD
420  )
421  );
422 
424  (
425  (
426  m_compactnessWeight
427  *
428  hCompact
429  )
430  +
431  (
432  ( 1.0f - m_compactnessWeight )
433  *
434  hSmooth
435  )
436  );
437 
438  // Finding the color heterogeneity
439 
442  SegmenterRegionGrowingSegment::FeatureType squaresSumUnion = 0;
445 
446  for( unsigned int sumsIdx = 0 ; sumsIdx < m_bandsNumber ; ++sumsIdx )
447  {
449  BAATZ_SU( segment1Ptr->m_features, sumsIdx );
450 
452  BAATZ_SU( segment2Ptr->m_features, sumsIdx );
453 
454  sumUnion = sum1 + sum2;
455  BAATZ_SU( mergePreviewSegPtr->m_features, sumsIdx ) = sumUnion;
456 
457  squaresSumUnion = BAATZ_SS( segment1Ptr->m_features, m_bandsNumber, sumsIdx ) +
458  BAATZ_SS( segment2Ptr->m_features, m_bandsNumber, sumsIdx );
459  BAATZ_SS( mergePreviewSegPtr->m_features, m_bandsNumber, sumsIdx ) = squaresSumUnion;
460 
461  meanUnion = sumUnion / sizeUnionD;
462 
463  stdDevUnion =
464  std::sqrt(
465  std::max(
467  ,
468  (
469  (
470  squaresSumUnion
471  -
472  (
473  ((SegmenterRegionGrowingSegment::FeatureType)2) * meanUnion * sumUnion
474  )
475  +
476  (
477  sizeUnionD * meanUnion * meanUnion
478  )
479  )
480  /
481  sizeUnionD
482  )
483  )
484  );
485  BAATZ_ST( mergePreviewSegPtr->m_features, m_bandsNumber, sumsIdx ) =
486  stdDevUnion;
487 
488  hColor +=
489  (
490  m_bandsWeights[ sumsIdx ]
491  *
492  (
493  stdDevUnion
494  -
495  (
496  (
497  (
498  BAATZ_ST( segment1Ptr->m_features, m_bandsNumber, sumsIdx )
499  *
500  sizeSeg1D
501  )
502  +
503  (
504  BAATZ_ST( segment2Ptr->m_features, m_bandsNumber, sumsIdx )
505  *
506  sizeSeg2D
507  )
508  )
509  /
510  sizeUnionD
511  )
512  )
513  );
514  }
515 
516  hColor =
517  (
518  (
519  hColor
520  *
521  m_colorWeight
522  )
523  +
524  (
525  ( 1.0f - m_colorWeight )
526  *
527  hForm
528  )
529  );
530 
531  return std::max( hColor, ((SegmenterRegionGrowingSegment::FeatureType)0) );
532  }
533 
535  SegmenterRegionGrowingSegment * const segment1Ptr,
536  SegmenterRegionGrowingSegment const * const segment2Ptr ,
537  SegmenterRegionGrowingSegment const * const mergePreviewSegPtr ) const
538  {
539  assert( segment1Ptr );
540  assert( segment1Ptr->m_features );
541  assert( segment2Ptr );
542  assert( segment2Ptr->m_features );
543  assert( mergePreviewSegPtr );
544 
545  // Merging basic features
546 
547  segment1Ptr->m_size = mergePreviewSegPtr->m_size;
548  segment1Ptr->m_xStart = mergePreviewSegPtr->m_xStart;
549  segment1Ptr->m_xBound = mergePreviewSegPtr->m_xBound;
550  segment1Ptr->m_yStart = mergePreviewSegPtr->m_yStart;
551  segment1Ptr->m_yBound = mergePreviewSegPtr->m_yBound;
552 
553  // Merging specific features
554 
555  memcpy( segment1Ptr->m_features, mergePreviewSegPtr->m_features, 3 + ( 3 *
556  sizeof( SegmenterRegionGrowingSegment::FeatureType ) * m_bandsNumber ) );
557  }
558 
560  {
562  std::numeric_limits< SegmenterRegionGrowingSegment::FeatureType >::max();
563  SegmenterRegionGrowingSegment::FeatureType compactnessMax = -1.0f *
564  std::numeric_limits< SegmenterRegionGrowingSegment::FeatureType >::max();
565 
567  std::numeric_limits< SegmenterRegionGrowingSegment::FeatureType >::max();
568  SegmenterRegionGrowingSegment::FeatureType smoothnessMax = -1.0f *
569  std::numeric_limits< SegmenterRegionGrowingSegment::FeatureType >::max();
570 
572 
573  const unsigned int nRows = m_segmentsMatrix.getLinesNumber();
574  const unsigned int nCols = m_segmentsMatrix.getColumnsNumber();
575  SegmenterRegionGrowingSegment* segsRowPtr = 0;
576 
577  unsigned int col = 0;
578  for( unsigned int row = 0 ; row < nRows ; ++row )
579  {
580  segsRowPtr = m_segmentsMatrix[ row ];
581 
582  for( col = 0 ; col < nCols ; ++col )
583  {
584  if( segsRowPtr[ col ].m_status )
585  {
586  featuresPtr = segsRowPtr[ col ].m_features;
587 
588  if( compactnessMin > BAATZ_CO( featuresPtr ) )
589  {
590  compactnessMin = BAATZ_CO( featuresPtr );
591  }
592  if( compactnessMax < BAATZ_CO( featuresPtr ) )
593  {
594  compactnessMax = BAATZ_CO( featuresPtr );
595  }
596 
597  if( smoothnessMin > BAATZ_SM( featuresPtr ) )
598  {
599  smoothnessMin = BAATZ_SM( featuresPtr );
600  }
601  if( smoothnessMax < BAATZ_SM( featuresPtr ) )
602  {
603  smoothnessMax = BAATZ_SM( featuresPtr );
604  }
605  }
606  }
607  }
608 
609  if( compactnessMax == compactnessMin )
610  {
611  m_allSegsCompactnessOffset = 0.0;
612 
613  if( compactnessMax == 0.0 )
614  m_allSegsCompactnessGain = 1.0;
615  else
616  m_allSegsCompactnessGain = 1.0f / compactnessMax;
617  }
618  else
619  {
620  m_allSegsCompactnessOffset = -1.0f * compactnessMin;
621  m_allSegsCompactnessGain = 1.0f / ( compactnessMax - compactnessMin );
622  }
623 
624  if( smoothnessMax == smoothnessMin )
625  {
626  m_allSegsSmoothnessOffset = 0.0;
627 
628  if( smoothnessMax == 0.0 )
629  m_allSegsSmoothnessGain = 1.0;
630  else
631  m_allSegsSmoothnessGain = 1.0f / smoothnessMax;
632  }
633  else
634  {
635  m_allSegsSmoothnessOffset = -1.0f * smoothnessMin;
636  m_allSegsSmoothnessGain = 1.0f / ( smoothnessMax - smoothnessMin );
637  }
638  }
639 
640  //-------------------------------------------------------------------------
641 
643  {
644  m_isInitialized = false;
645  }
646 
648  {
649  reset();
650  }
651 
653  SegmenterStrategyParameters const* const strategyParams )
654  throw( te::rp::Exception )
655  {
656  m_isInitialized = false;
657  reset();
658 
660  dynamic_cast< SegmenterRegionGrowingStrategy::Parameters const* >( strategyParams );
661 
662  if( paramsPtr )
663  {
664  m_parameters = *( paramsPtr );
665 
667  "Invalid segmenter strategy parameter m_minSegmentSize" )
668 
671  "Invalid segmenter strategy parameter m_segmentsSimilarityThreshold" )
672 
675  "Invalid segmenter strategy parameter m_segmentFeatures" )
676 
678  {
680  "Invalid segmenter strategy parameter m_bandsWeights" );
681 
682  double bandsWeightsSum = 0;
683  unsigned int bandsWeightsIdx = 0 ;
684  for( bandsWeightsIdx = 0 ; bandsWeightsIdx <
685  m_parameters.m_bandsWeights.size() ; ++bandsWeightsIdx )
686  {
688  m_parameters.m_bandsWeights[ bandsWeightsIdx ] >= 0.0,
689  "Invalid segmenter strategy parameter m_bandsWeights" );
690  bandsWeightsSum += m_parameters.m_bandsWeights[ bandsWeightsIdx ];
691  }
692  TERP_TRUE_OR_RETURN_FALSE( bandsWeightsSum != 0.0,
693  "Invalid segmenter strategy parameter m_bandsWeights" );
694  for( bandsWeightsIdx = 0 ; bandsWeightsIdx <
695  m_parameters.m_bandsWeights.size() ; ++bandsWeightsIdx )
696  {
697  m_parameters.m_bandsWeights[ bandsWeightsIdx ] /= bandsWeightsSum;
698  }
699 
700  }
701 
702  m_isInitialized = true;
703 
704  return true;
705  }
706  else
707  {
708  return false;
709  }
710  }
711 
713  {
714  m_isInitialized = false;
718  }
719 
721  SegmenterIdsManager& segmenterIdsManager,
722  const te::rst::Raster& inputRaster,
723  const std::vector< unsigned int >& inputRasterBands,
724  const std::vector< double >& inputRasterGains,
725  const std::vector< double >& inputRasterOffsets,
726  te::rst::Raster& outputRaster,
727  const unsigned int outputRasterBand,
728  const bool enableProgressInterface )
729  throw( te::rp::Exception )
730  {
732  "Instance not initialized" )
733 
734  // Updating the bands weights info, if needed
735 
736  if( m_parameters.m_bandsWeights.empty() )
737  m_parameters.m_bandsWeights.resize( inputRasterBands.size(), 1.0 /
738  ((double)inputRasterBands.size()) );
739 
740  // Initiating the segments pool
741 
742  unsigned int segmentFeaturesSize = 0;
744  {
746  {
747  segmentFeaturesSize = inputRasterBands.size();
748  break;
749  }
751  {
752  segmentFeaturesSize = 3 + ( 3 * inputRasterBands.size() );
753  break;
754  }
755  default :
756  {
757  TERP_LOG_AND_THROW( "Invalid segment features type" );
758  break;
759  }
760  }
761  // The number of segments plus 3 (due 3 auxiliary segments
762  TERP_TRUE_OR_RETURN_FALSE( m_segmentsPool.initialize( 3 + ( inputRaster.getNumberOfRows() *
763  inputRaster.getNumberOfColumns() ),
764  segmentFeaturesSize ), "Segments pool initiation error" );
765 
766 // {
767 // // checking alignment
768 // SegmenterRegionGrowingSegment* auxSegPtr = 0;
769 // unsigned int counter = 0;
770 // while( auxSegPtr = m_segmentsPool.getNextSegment() )
771 // {
772 // for( unsigned int featureIdx = 0 ; featureIdx < auxSegPtr->m_featuresSize ;
773 // ++featureIdx )
774 // {
775 // auxSegPtr->m_features[ featureIdx ] = (SegmenterRegionGrowingSegment::FeatureType)
776 // counter;
777 // }
778 // }
779 // m_segmentsPool.resetUseCounter();
780 // counter = 0;
781 // while( auxSegPtr = m_segmentsPool.getNextSegment() )
782 // {
783 // for( unsigned int featureIdx = 0 ; featureIdx < auxSegPtr->m_featuresSize ;
784 // ++featureIdx )
785 // {
786 // if( auxSegPtr->m_features[ featureIdx ] != (SegmenterRegionGrowingSegment::FeatureType)
787 // counter ) throw;
788 // }
789 // }
790 // }
791 
793  auxSeg1Ptr->m_status = false;
795  auxSeg2Ptr->m_status = false;
797  auxSeg3Ptr->m_status = false;
798 
799  // Allocating the ids matrix
800 
801  if( ( m_segmentsIdsMatrix.getLinesNumber() != inputRaster.getNumberOfRows() ) ||
802  ( m_segmentsIdsMatrix.getColumnsNumber() != inputRaster.getNumberOfColumns() ) )
803  {
804  TERP_TRUE_OR_RETURN_FALSE( m_segmentsIdsMatrix.reset( inputRaster.getNumberOfRows(),
805  inputRaster.getNumberOfColumns(),
807  "Error allocating segments Ids matrix" );
808  }
809 
810  // Initializing segments
811 
812  TERP_TRUE_OR_RETURN_FALSE( initializeSegments( segmenterIdsManager,
813  inputRaster, inputRasterBands, inputRasterGains,
814  inputRasterOffsets ),
815  "Segments initalization error" );
816 
817  // Creating the merger instance
818 
819  std::auto_ptr< Merger > mergerPtr;
820  bool enablelocalMutualBestFitting = false;
821 
823  {
825  {
826  mergerPtr.reset( new MeanMerger( inputRasterBands.size() ) );
827  enablelocalMutualBestFitting = true;
828  break;
829  }
831  {
832  mergerPtr.reset( new BaatzMerger( m_parameters.m_colorWeight,
835  enablelocalMutualBestFitting = true;
836  break;
837  }
838  default :
839  {
840  TERP_LOG_AND_THROW( "Invalid segment features type" );
841  break;
842  }
843  }
844 
845  // Progress interface
846 
847  std::auto_ptr< te::common::TaskProgress > progressPtr;
848  if( enableProgressInterface )
849  {
850  progressPtr.reset( new te::common::TaskProgress );
851  progressPtr->setTotalSteps( 100 );
852  progressPtr->setMessage( "Segmentation" );
853  }
854 
855  // Segmentation loop
856 
857  SegmenterRegionGrowingSegment::FeatureType disimilarityThreshold = 0;
858  const SegmenterRegionGrowingSegment::FeatureType disimilarityThresholdStep =
859  (
861  /
863  );
864  unsigned int mergedSegments = 0;
865  unsigned int maxMergedSegments = 0;
866  int currStep = 0;
867 
868 // unsigned int mergetIterations = 0;
869 // exportSegs2Tif( m_segmentsIdsMatrix, true, "merging" +
870 // te::common::Convert2String( mergetIterations ) + ".tif" );
871 
872  while ( true )
873  {
874  mergedSegments = mergeSegments( disimilarityThreshold, segmenterIdsManager,
875  *mergerPtr, enablelocalMutualBestFitting,
876  auxSeg1Ptr, auxSeg2Ptr, auxSeg3Ptr);
877 // exportSegs2Tif( m_segmentsIdsMatrix, true, "merging" +
878 // te::common::Convert2String( ++mergetIterations ) + ".tif" );
879 
880  if( enableProgressInterface )
881  {
882  if( maxMergedSegments )
883  {
884  currStep = (int)
885  (
886  (
887  (
888  ( (double)( maxMergedSegments - mergedSegments ) )
889  /
890  ((double)maxMergedSegments )
891  )
892  )
893  *
894  50.0
895  );
896 
897  if( currStep > progressPtr->getCurrentStep() )
898  {
899  progressPtr->setCurrentStep( currStep );
900  }
901  }
902 
903  if( ! progressPtr->isActive() )
904  {
905  return false;
906  }
907 
908  if( maxMergedSegments < mergedSegments )
909  {
910  maxMergedSegments = mergedSegments;
911  }
912  }
913 
914  if( mergedSegments == 0 )
915  {
917  {
918  break;
919  }
920  else
921  {
922  disimilarityThreshold += disimilarityThresholdStep;
923  disimilarityThreshold = std::min( disimilarityThreshold,
925  }
926  }
927  }
928 
929  if( enableProgressInterface )
930  {
931  progressPtr->setCurrentStep( 50 );
932  if( ! progressPtr->isActive() )
933  {
934  return false;
935  }
936  }
937 
939  {
940  maxMergedSegments = 0;
941 
942  while( true )
943  {
945  segmenterIdsManager, *mergerPtr, auxSeg1Ptr, auxSeg2Ptr );
946 // exportSegs2Tif( segmentsIds, true, "mergingSmall" +
947 // te::common::Convert2String( mergetIterations ) + ".tif" );
948 
949  if( enableProgressInterface )
950  {
951  if( maxMergedSegments )
952  {
953  currStep = 50 + (int)
954  (
955  (
956  (
957  ( (double)( maxMergedSegments - mergedSegments ) )
958  /
959  ((double)maxMergedSegments )
960  )
961  )
962  *
963  50.0
964  );
965 
966  if( currStep > progressPtr->getCurrentStep() )
967  {
968  progressPtr->setCurrentStep( currStep );
969  }
970  }
971 
972  if( ! progressPtr->isActive() )
973  {
974  return false;
975  }
976 
977  if( maxMergedSegments < mergedSegments )
978  {
979  maxMergedSegments = mergedSegments;
980  }
981  }
982 
983  if( mergedSegments == 0 )
984  {
985  break;
986  }
987  }
988  }
989 
990  if( enableProgressInterface )
991  {
992  progressPtr->setCurrentStep( 100 );
993  if( ! progressPtr->isActive() )
994  {
995  return false;
996  }
997  }
998 
999  // Flush result to the output raster
1000 
1001  {
1002  const unsigned int nLines = inputRaster.getNumberOfRows();
1003  const unsigned int nCols = inputRaster.getNumberOfColumns();
1004  unsigned int col = 0;
1005  SegmenterSegmentsBlock::SegmentIdDataType* segmentsIdsLinePtr = 0;
1006 
1007  for( unsigned int line = 0 ; line < nLines ; ++line )
1008  {
1009  segmentsIdsLinePtr = m_segmentsIdsMatrix[ line ];
1010 
1011  for( col = 0 ; col < nCols ; ++col )
1012  {
1013  outputRaster.setValue( col, line, segmentsIdsLinePtr[ col ], outputRasterBand );
1014  }
1015  }
1016  }
1017 
1018  return true;
1019  }
1020 
1022  const unsigned int bandsToProcess,
1023  const unsigned int pixelsNumber ) const
1024  {
1025  TERP_TRUE_OR_THROW( m_isInitialized, "Instance not initialized" );
1026 
1027  // The features matrix inside the pool
1028  double featuresSizeBytes = 0.0;
1030  {
1032  {
1033  featuresSizeBytes = (double)
1034  (
1035  pixelsNumber
1036  *
1037  bandsToProcess
1038  *
1040  );
1041  break;
1042  }
1044  {
1045  featuresSizeBytes = (double)
1046  (
1047  pixelsNumber
1048  *
1049  (
1050  (
1051  3
1052  *
1054  )
1055  +
1056  (
1057  3
1058  *
1059  bandsToProcess
1060  *
1062  )
1063  )
1064  );
1065  break;
1066  }
1067  default :
1068  {
1069  TERP_LOG_AND_THROW( "Invalid segment features type" );
1070  break;
1071  }
1072  }
1073 
1074  return (double)
1075  (
1076  featuresSizeBytes
1077  +
1078  ( // The segments matrix inside the pool
1079  pixelsNumber
1080  *
1081  (
1083  +
1084  ( // An initial vector of pointers to 8 neighbors
1085  6
1086  *
1088  )
1089  )
1090  )
1091  +
1092  ( // The segments IDs matrix inside the strategy
1093  pixelsNumber
1094  *
1096  )
1097  );
1098  }
1099 
1101  {
1102  TERP_TRUE_OR_THROW( m_isInitialized, "Instance not initialized" );
1103  return (unsigned int)( std::sqrt( (double)m_parameters.m_minSegmentSize) );
1104  }
1105 
1107  SegmenterIdsManager& segmenterIdsManager,
1108  const te::rst::Raster& inputRaster,
1109  const std::vector< unsigned int >& inputRasterBands,
1110  const std::vector< double >& inputRasterGains,
1111  const std::vector< double >& inputRasterOffsets )
1112  {
1113  const unsigned int nLines = inputRaster.getNumberOfRows();
1114  const unsigned int nCols = inputRaster.getNumberOfColumns();
1115  const unsigned int inputRasterBandsSize = (unsigned int)
1116  inputRasterBands.size();
1117 
1118  // fiding band dummy values
1119 
1120  std::vector< double > bandDummyValues;
1121 
1122  {
1123  for( unsigned int inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
1124  inputRasterBandsSize ; ++inputRasterBandsIdx )
1125  {
1126  bandDummyValues.push_back( inputRaster.getBand(
1127  inputRasterBands[ inputRasterBandsIdx ] )->getProperty()->m_noDataValue );
1128  }
1129  }
1130 
1131  // Initializing each segment
1132 
1133  unsigned int line = 0;
1134  unsigned int col = 0;
1135  SegmenterRegionGrowingSegment* segmentPtr = 0;
1136  SegmenterRegionGrowingSegment* neighborSegmentPtr = 0;
1137  bool rasterValuesAreValid = true;
1138  unsigned int inputRasterBandsIdx = 0;
1139  double value = 0;
1140  const std::vector< double > dummyZeroesVector( inputRasterBandsSize, 0 );
1141 
1142  std::list< SegmenterSegmentsBlock::SegmentIdDataType >
1143  unusedLineSegmentIds;
1144 
1145  std::vector< SegmenterSegmentsBlock::SegmentIdDataType >
1146  lineSegmentIds;
1147  lineSegmentIds.reserve( nCols );
1148 
1149  std::vector< SegmenterRegionGrowingSegment::FeatureType > rasterValues;
1150  std::vector< SegmenterRegionGrowingSegment::FeatureType > rasterSquareValues;
1151  rasterValues.resize( inputRasterBandsSize, 0 );
1152  rasterSquareValues.resize( inputRasterBandsSize, 0 );
1153  std::vector< SegmenterRegionGrowingSegment* > usedSegPointers1( nCols, 0 );
1154  std::vector< SegmenterRegionGrowingSegment* > usedSegPointers2( nCols, 0 );
1155  std::vector< SegmenterRegionGrowingSegment* >* lastLineSegsPtrs = &usedSegPointers1;
1156  std::vector< SegmenterRegionGrowingSegment* >* currLineSegsPtrs = &usedSegPointers2;
1157 
1158  unsigned int rasterValuesIdx = 0;
1159 
1160  for( line = 0 ; line < nLines ; ++line )
1161  {
1162  segmenterIdsManager.getNewIDs( nCols, lineSegmentIds );
1163 
1164  for( col = 0 ; col < nCols ; ++col )
1165  {
1166  rasterValuesAreValid = true;
1167 
1168  for( inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
1169  inputRasterBandsSize ; ++inputRasterBandsIdx )
1170  {
1171  inputRaster.getValue( col, line, value,
1172  inputRasterBands[ inputRasterBandsIdx ] );
1173 
1174  if( value == bandDummyValues[ inputRasterBandsIdx ] )
1175  {
1176  rasterValuesAreValid = false;
1177  break;
1178  }
1179  else
1180  {
1181  value += inputRasterOffsets[ inputRasterBandsIdx ];
1182  value *= inputRasterGains[ inputRasterBandsIdx ];
1183 
1184  rasterValues[ inputRasterBandsIdx ] =
1186  rasterSquareValues[ inputRasterBandsIdx ] =
1187  (SegmenterRegionGrowingSegment::FeatureType)( value * value );
1188  }
1189  }
1190 
1191  // assotiating a segment object
1192 
1193  if( rasterValuesAreValid )
1194  {
1196  {
1198  {
1199  segmentPtr = m_segmentsPool.getNextSegment();
1200  assert( segmentPtr );
1201 
1202  for( rasterValuesIdx = 0 ; rasterValuesIdx < inputRasterBandsSize ;
1203  ++rasterValuesIdx )
1204  {
1205  segmentPtr->m_features[ rasterValuesIdx ] = rasterValues[
1206  rasterValuesIdx ];
1207  }
1208 
1209  break;
1210  }
1212  {
1213  segmentPtr = m_segmentsPool.getNextSegment();
1214  assert( segmentPtr );
1215 
1216  for( rasterValuesIdx = 0 ; rasterValuesIdx < inputRasterBandsSize ;
1217  ++rasterValuesIdx )
1218  {
1219  BAATZ_SU( segmentPtr->m_features, rasterValuesIdx ) =
1220  rasterValues[ rasterValuesIdx ];
1221  BAATZ_SS( segmentPtr->m_features, inputRasterBandsSize, rasterValuesIdx ) =
1222  rasterSquareValues[ rasterValuesIdx ];
1223  BAATZ_ST( segmentPtr->m_features, inputRasterBandsSize, rasterValuesIdx ) =
1224  0.0;
1225  BAATZ_EL( segmentPtr->m_features ) = 4;
1226  BAATZ_CO( segmentPtr->m_features ) = 4;
1227  BAATZ_SM( segmentPtr->m_features ) = 1;
1228  }
1229 
1230  break;
1231  }
1232  default :
1233  {
1234  TERP_LOG_AND_THROW( "Invalid segment features type" );
1235  break;
1236  }
1237  }
1238 
1239  currLineSegsPtrs->operator[]( col ) = segmentPtr;
1240 
1241  segmentPtr->m_id = lineSegmentIds[ col ];
1242  segmentPtr->m_status = true;
1243  segmentPtr->m_size = 1;
1244  segmentPtr->m_xStart = col;
1245  segmentPtr->m_xBound = col + 1;
1246  segmentPtr->m_yStart = line;
1247  segmentPtr->m_yBound = line + 1;
1248 
1249  m_segmentsIdsMatrix( line, col ) = segmentPtr->m_id;
1250 
1251  // updating the neighboorhood info
1252 
1253  segmentPtr->clearNeighborSegments();
1254 
1255  if( line )
1256  {
1257  neighborSegmentPtr = lastLineSegsPtrs->operator[]( col );
1258 
1259  if( neighborSegmentPtr )
1260  {
1261  segmentPtr->addNeighborSegment( neighborSegmentPtr );
1262 
1263  neighborSegmentPtr->addNeighborSegment( segmentPtr );
1264  }
1265  }
1266 
1267  if( col )
1268  {
1269  neighborSegmentPtr = currLineSegsPtrs->operator[]( col - 1 );
1270 
1271  if( neighborSegmentPtr )
1272  {
1273  segmentPtr->addNeighborSegment( neighborSegmentPtr );
1274 
1275  neighborSegmentPtr->addNeighborSegment( segmentPtr );
1276  }
1277  }
1278  }
1279  else // !rasterValueIsValid
1280  {
1281  m_segmentsIdsMatrix( line, col ) = 0;
1282  unusedLineSegmentIds.push_back( lineSegmentIds[ col ] );
1283  currLineSegsPtrs->operator[]( col ) = 0;
1284  }
1285  }
1286 
1287  // Free unused IDs
1288 
1289  if( ! unusedLineSegmentIds.empty() )
1290  {
1291  segmenterIdsManager.addFreeIDs( unusedLineSegmentIds );
1292  unusedLineSegmentIds.clear();
1293  }
1294 
1295  // Swapping the pointers to the vectors of used segment pointers
1296 
1297  if( lastLineSegsPtrs == ( &usedSegPointers1 ) )
1298  {
1299  lastLineSegsPtrs = &usedSegPointers2;
1300  currLineSegsPtrs = &usedSegPointers1;
1301  }
1302  else
1303  {
1304  lastLineSegsPtrs = &usedSegPointers1;
1305  currLineSegsPtrs = &usedSegPointers2;
1306  }
1307  }
1308 
1309  return true;
1310  }
1311 
1313  const SegmenterRegionGrowingSegment::FeatureType disimilarityThreshold,
1314  SegmenterIdsManager& segmenterIdsManager,
1315  Merger& merger,
1316  const bool enablelocalMutualBestFitting,
1317  SegmenterRegionGrowingSegment* auxSeg1Ptr,
1318  SegmenterRegionGrowingSegment* auxSeg2Ptr,
1319  SegmenterRegionGrowingSegment* auxSeg3Ptr)
1320  {
1321  unsigned int mergedSegmentsNumber = 0;
1322  unsigned int segmentsLine = 0;
1323  unsigned int segmentsLineBound = 0;
1324  unsigned int segmentCol = 0;
1325  unsigned int segmentColStart = 0;
1326  unsigned int segmentColBound = 0;
1327  SegmenterRegionGrowingSegment* minForwardDissimilaritySegmentPtr = 0;
1328  SegmenterRegionGrowingSegment::FeatureType forwardDissimilarityValue = 0;
1329  SegmenterRegionGrowingSegment::FeatureType minForwardDissimilarityValue = 0;
1330  SegmenterRegionGrowingSegment* minBackwardDissimilaritySegmentPtr = 0;
1331  SegmenterRegionGrowingSegment::FeatureType backwardDissimilarityValue = 0;
1332  SegmenterRegionGrowingSegment::FeatureType minBackwardDissimilarityValue = 0;
1333  SegmenterSegmentsBlock::SegmentIdDataType* segmentsIdsLinePtr = 0;
1334  SegmenterSegmentsBlock::SegmentIdDataType currentSegmentId = 0;
1335  std::list< SegmenterSegmentsBlock::SegmentIdDataType > freeSegmentIds;
1336  unsigned int neighborSegIdx = 0;
1338  const unsigned int segmentsMatrixNRows = segmentsMatrix.getLinesNumber();
1339  const unsigned int segmentsMatrixNCols = segmentsMatrix.getColumnsNumber();
1340  SegmenterRegionGrowingSegment* segmentsMatrixLinePtr = 0;
1341  unsigned int col = 0;
1342  SegmenterRegionGrowingSegment* currSegPtr = 0;
1343 
1344  // Updating the merger state
1345 
1346  merger.update();
1347 
1348  // iterating over each segment
1349 
1350  for( unsigned int row = 0 ; row < segmentsMatrixNRows ; ++row )
1351  {
1352  segmentsMatrixLinePtr = segmentsMatrix[ row ];
1353 
1354  for( col = 0 ; col < segmentsMatrixNCols ; ++col )
1355  {
1356  currSegPtr = segmentsMatrixLinePtr + col;
1357 
1358  if( currSegPtr->m_status )
1359  {
1360  // finding the neighbor segment with minimum dissimilary value
1361  // related to the current sement
1362 
1363  minForwardDissimilaritySegmentPtr = 0;
1364  minForwardDissimilarityValue =
1365  std::numeric_limits< SegmenterRegionGrowingSegment::FeatureType >::max();
1366 
1367  for( neighborSegIdx = 0 ; neighborSegIdx < currSegPtr->m_neighborSegmentsSize ;
1368  ++neighborSegIdx )
1369  {
1370  if( currSegPtr->m_neighborSegments[ neighborSegIdx ] )
1371  {
1372  forwardDissimilarityValue = merger.getDissimilarity( currSegPtr,
1373  currSegPtr->m_neighborSegments[ neighborSegIdx ], auxSeg1Ptr );
1374 
1375  if( ( forwardDissimilarityValue <= disimilarityThreshold ) &&
1376  ( forwardDissimilarityValue < minForwardDissimilarityValue ) )
1377  {
1378  minForwardDissimilarityValue = forwardDissimilarityValue;
1379  minForwardDissimilaritySegmentPtr = currSegPtr->m_neighborSegments[ neighborSegIdx ];
1380  auxSeg3Ptr->operator=( *auxSeg1Ptr );
1381  }
1382  }
1383  }
1384 
1385  // does the neighbor wants to merge back ?
1386 
1387  if( enablelocalMutualBestFitting && ( minForwardDissimilaritySegmentPtr != 0 ) )
1388  {
1389  // Calculating all neighbor neighbor segments dissimilarity
1390 
1391  minBackwardDissimilaritySegmentPtr = 0;
1392  backwardDissimilarityValue = 0;
1393  minBackwardDissimilarityValue =
1394  std::numeric_limits< SegmenterRegionGrowingSegment::FeatureType >::max();
1395 
1396  for( neighborSegIdx = 0 ; neighborSegIdx < minForwardDissimilaritySegmentPtr->m_neighborSegmentsSize ;
1397  ++neighborSegIdx )
1398  {
1399  if( minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] )
1400  {
1401  backwardDissimilarityValue =
1402  merger.getDissimilarity( minForwardDissimilaritySegmentPtr,
1403  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ], auxSeg2Ptr );
1404 
1405  if( backwardDissimilarityValue < minBackwardDissimilarityValue )
1406  {
1407  minBackwardDissimilarityValue = backwardDissimilarityValue;
1408  minBackwardDissimilaritySegmentPtr =
1409  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ];
1410  }
1411  }
1412  }
1413 
1414  if( minBackwardDissimilaritySegmentPtr != currSegPtr )
1415  {
1416  minForwardDissimilaritySegmentPtr = 0;
1417  }
1418  }
1419 
1420  // If the maximum similary neighbor was found it will be merged
1421 
1422  if( minForwardDissimilaritySegmentPtr )
1423  {
1424  // merging segment data
1425 
1426  merger.mergeFeatures( currSegPtr, minForwardDissimilaritySegmentPtr,
1427  auxSeg3Ptr );
1428 
1429  currSegPtr->removeNeighborSegment( minForwardDissimilaritySegmentPtr );
1430 
1431  // updating the max similarity segment neighborhood segments
1432  // with the current segment
1433 
1434  for( neighborSegIdx = 0 ; neighborSegIdx < minForwardDissimilaritySegmentPtr->m_neighborSegmentsSize ;
1435  ++neighborSegIdx )
1436  {
1437  if(
1438  ( minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] != 0 )
1439  &&
1440  ( minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] != currSegPtr )
1441  )
1442  {
1443  // adding the max similarity neighborhood segments to the
1444  // current one, if it is not already there
1445 
1446  currSegPtr->addNeighborSegment(
1447  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] );
1448 
1449  // adding the current segment into the max similarity
1450  // neighborhood segments list, if it is not already there
1451 
1452  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ]->addNeighborSegment(
1453  currSegPtr );
1454 
1455  // removing the merged segment reference from its neighbor
1456  // list
1457 
1458  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ]->removeNeighborSegment(
1459  minForwardDissimilaritySegmentPtr );
1460  }
1461  }
1462 
1463  // updating the segments Ids container matrix
1464 
1465  segmentsLineBound = minForwardDissimilaritySegmentPtr->m_yBound;
1466  segmentColStart = minForwardDissimilaritySegmentPtr->m_xStart;
1467  segmentColBound = minForwardDissimilaritySegmentPtr->m_xBound;
1468  currentSegmentId = currSegPtr->m_id;
1469 
1470  for( segmentsLine = minForwardDissimilaritySegmentPtr->m_yStart ;
1471  segmentsLine < segmentsLineBound ; ++segmentsLine )
1472  {
1473  segmentsIdsLinePtr = m_segmentsIdsMatrix[ segmentsLine ];
1474 
1475  for( segmentCol = segmentColStart ; segmentCol <
1476  segmentColBound ; ++segmentCol )
1477  {
1478  if( segmentsIdsLinePtr[ segmentCol ] ==
1479  minForwardDissimilaritySegmentPtr->m_id )
1480  {
1481  segmentsIdsLinePtr[ segmentCol ] = currentSegmentId;
1482  }
1483  }
1484  }
1485 
1486  // disabling the merged segment
1487  // The merged segment id will be given back to ids manager
1488 
1489  minForwardDissimilaritySegmentPtr->m_status = false;
1490 
1491  minForwardDissimilaritySegmentPtr->clearNeighborSegments();
1492 
1493  freeSegmentIds.push_back( minForwardDissimilaritySegmentPtr->m_id );
1494 
1495  ++mergedSegmentsNumber;
1496  }
1497  }
1498  }
1499  }
1500 
1501  // give back the free unused sement ids
1502 
1503  if( ! freeSegmentIds.empty() )
1504  {
1505  segmenterIdsManager.addFreeIDs( freeSegmentIds );
1506  }
1507 
1508  return mergedSegmentsNumber;
1509  }
1510 
1512  const unsigned int minSegmentSize,
1513  SegmenterIdsManager& segmenterIdsManager,
1514  Merger& merger,
1515  SegmenterRegionGrowingSegment* auxSeg1Ptr,
1516  SegmenterRegionGrowingSegment* auxSeg2Ptr )
1517  {
1518  unsigned int mergedSegmentsNumber = 0;
1519  SegmenterRegionGrowingSegment* currSmallSegPtr = 0;
1520  SegmenterRegionGrowingSegment* minForwardDissimilaritySegmentPtr = 0;
1521  SegmenterRegionGrowingSegment::FeatureType forwardDissimilarityValue = 0;
1522  SegmenterRegionGrowingSegment::FeatureType minForwardDissimilarityValue = 0;
1523  unsigned int segmentsLine = 0;
1524  unsigned int segmentsLineBound = 0;
1525  unsigned int segmentCol = 0;
1526  unsigned int segmentColStart = 0;
1527  unsigned int segmentColBound = 0;
1528  SegmenterSegmentsBlock::SegmentIdDataType* segmentsIdsLinePtr = 0;
1529  SegmenterSegmentsBlock::SegmentIdDataType currentSegmentId = 0;
1530  std::list< SegmenterSegmentsBlock::SegmentIdDataType > freeSegmentIds;
1531  unsigned int neighborSegIdx = 0;
1533  const unsigned int segmentsMatrixNRows = segmentsMatrix.getLinesNumber();
1534  const unsigned int segmentsMatrixNCols = segmentsMatrix.getColumnsNumber();
1535  SegmenterRegionGrowingSegment* segmentsMatrixLinePtr = 0;
1536  unsigned int col = 0;
1537 
1538  // Updating the merger state
1539 
1540  merger.update();
1541 
1542  // iterating over each segment
1543 
1544  for( unsigned int row = 0 ; row < segmentsMatrixNRows ; ++row )
1545  {
1546  segmentsMatrixLinePtr = segmentsMatrix[ row ];
1547 
1548  for( col = 0 ; col < segmentsMatrixNCols ; ++col )
1549  {
1550  currSmallSegPtr = segmentsMatrixLinePtr + col;
1551 
1552  if( currSmallSegPtr->m_status )
1553  {
1554  // is this a small segment ?
1555 
1556  if( currSmallSegPtr->m_size < minSegmentSize )
1557  {
1558  // Looking for the closest neighboorhood segment
1559 
1560  minForwardDissimilaritySegmentPtr = 0;
1561  minForwardDissimilarityValue =
1562  std::numeric_limits< SegmenterRegionGrowingSegment::FeatureType >::max();
1563 
1564  for( neighborSegIdx = 0 ; neighborSegIdx < currSmallSegPtr->m_neighborSegmentsSize ;
1565  ++neighborSegIdx )
1566  {
1567  if( currSmallSegPtr->m_neighborSegments[ neighborSegIdx ] )
1568  {
1569  forwardDissimilarityValue = merger.getDissimilarity( currSmallSegPtr,
1570  currSmallSegPtr->m_neighborSegments[ neighborSegIdx ], auxSeg1Ptr );
1571 
1572  if( forwardDissimilarityValue < minForwardDissimilarityValue )
1573  {
1574  minForwardDissimilarityValue = forwardDissimilarityValue;
1575  minForwardDissimilaritySegmentPtr = currSmallSegPtr->m_neighborSegments[ neighborSegIdx ];
1576  auxSeg2Ptr->operator=( *auxSeg1Ptr );
1577  }
1578  }
1579  }
1580 
1581  // If the minimum dissimilary neighbor was found it will be merged
1582 
1583  if( minForwardDissimilaritySegmentPtr )
1584  {
1585  // merging the small segment data into there
1586  // closes segment data
1587 
1588  merger.mergeFeatures( minForwardDissimilaritySegmentPtr,
1589  currSmallSegPtr, auxSeg2Ptr );
1590 
1591  minForwardDissimilaritySegmentPtr->removeNeighborSegment( currSmallSegPtr );
1592 
1593  // updating the the small segment neighborhood segments
1594  // with the current segment
1595 
1596  for( neighborSegIdx = 0 ; neighborSegIdx < currSmallSegPtr->m_neighborSegmentsSize ;
1597  ++neighborSegIdx )
1598  {
1599  if(
1600  ( currSmallSegPtr->m_neighborSegments[ neighborSegIdx ] != 0 )
1601  &&
1602  ( currSmallSegPtr->m_neighborSegments[ neighborSegIdx ] != minForwardDissimilaritySegmentPtr )
1603  )
1604  {
1605  // adding the small segment neighborhood segments to the
1606  // closest segment, if it is not already there
1607 
1608  minForwardDissimilaritySegmentPtr->addNeighborSegment(
1609  currSmallSegPtr->m_neighborSegments[ neighborSegIdx ] );
1610 
1611  // adding the closest segment into the small segment
1612  // neighborhood segments list, if it is not already there
1613 
1614  currSmallSegPtr->m_neighborSegments[ neighborSegIdx ]->addNeighborSegment(
1615  minForwardDissimilaritySegmentPtr );
1616 
1617  // removing the small segment reference from its neighbor
1618  // list
1619 
1620  currSmallSegPtr->m_neighborSegments[ neighborSegIdx ]->removeNeighborSegment(
1621  currSmallSegPtr );
1622  }
1623  }
1624 
1625  // updating the segments Ids container matrix
1626 
1627  segmentsLineBound = currSmallSegPtr->m_yBound;
1628  segmentColStart = currSmallSegPtr->m_xStart;
1629  segmentColBound = currSmallSegPtr->m_xBound;
1630  currentSegmentId = currSmallSegPtr->m_id;
1631 
1632  for( segmentsLine = currSmallSegPtr->m_yStart ;
1633  segmentsLine < segmentsLineBound ; ++segmentsLine )
1634  {
1635  segmentsIdsLinePtr = m_segmentsIdsMatrix[ segmentsLine ];
1636 
1637  for( segmentCol = segmentColStart ; segmentCol <
1638  segmentColBound ; ++segmentCol )
1639  {
1640  if( segmentsIdsLinePtr[ segmentCol ] ==
1641  currentSegmentId )
1642  {
1643  segmentsIdsLinePtr[ segmentCol ] =
1644  minForwardDissimilaritySegmentPtr->m_id;
1645  }
1646  }
1647  }
1648 
1649  // disabling the small segment
1650  // The merged segment id will be given back to ids manager
1651 
1652  currSmallSegPtr->clearNeighborSegments();
1653 
1654  currSmallSegPtr->m_status = false;
1655 
1656  freeSegmentIds.push_back( currentSegmentId );
1657 
1658  ++mergedSegmentsNumber;
1659  }
1660  }
1661  }
1662  }
1663  }
1664 
1665  // give back the free unused sement ids
1666 
1667  if( ! freeSegmentIds.empty() )
1668  {
1669  segmenterIdsManager.addFreeIDs( freeSegmentIds );
1670  }
1671 
1672  return mergedSegmentsNumber;
1673  }
1674 
1676  const SegmentsIdsMatrixT& segmentsIds, bool normto8bits,
1677  const std::string& fileName )
1678  {
1679  std::map<std::string, std::string> rinfo;
1680  rinfo["SOURCE"] = fileName;
1681 
1682  const unsigned int linesNmb = segmentsIds.getLinesNumber();
1683  const unsigned int colsNmb = segmentsIds.getColumnsNumber();
1684 
1685  te::rst::Grid* gridPtr = new te::rst::Grid( colsNmb, linesNmb );
1686 
1687  std::vector< te::rst::BandProperty* > bandsProps;
1688  bandsProps.push_back( new te::rst::BandProperty( 0,
1689  (normto8bits ? te::dt::UCHAR_TYPE : te::dt::UINT32_TYPE) ) );
1690 
1691  te::rst::Raster* rasterPtr = te::rst::RasterFactory::make( "GDAL",
1692  gridPtr, bandsProps, rinfo );
1693  TERP_TRUE_OR_THROW( rasterPtr, "Invalid pointer" )
1694 
1695  unsigned int col = 0;
1696  unsigned int line = 0 ;
1697 
1698  double offset = 0.0;
1699  double scale = 1.0;
1700 
1701  if( normto8bits )
1702  {
1703  double minValue = DBL_MAX;
1704  double maxValue = -1.0 * DBL_MAX;
1705  double value = 0;
1706 
1707  for( line = 0 ; line < linesNmb ; ++line )
1708  {
1709  for( col = 0 ; col < colsNmb ; ++col )
1710  {
1711  value = (double)segmentsIds( line, col );
1712 
1713  if( value > maxValue ) maxValue = value;
1714  if( value < minValue ) minValue = value;
1715  }
1716  }
1717 
1718  offset = minValue;
1719  scale = 254.0 / ( maxValue - minValue );
1720  }
1721 
1722  double value = 0;
1723 
1724  for( line = 0 ; line < linesNmb ; ++line )
1725  {
1726  for( col = 0 ; col < colsNmb ; ++col )
1727  {
1728  value = ( ((double)segmentsIds( line, col )) - offset ) * scale;
1729  TERP_TRUE_OR_THROW( value <= 255.0, "Invalid value:" +
1730  boost::lexical_cast< std::string >( value ) )
1731 
1732  rasterPtr->setValue( col, line, value , 0 );
1733  }
1734  }
1735 
1736  delete rasterPtr;
1737  }
1738 
1740  const SegmentsIdsMatrixT& segsIds,
1741  const unsigned int& xStart, const unsigned int& yStart,
1742  const unsigned int& xBound, const unsigned int& yBound,
1745  unsigned int& edgeLength1,
1746  unsigned int& edgeLength2 )
1747  {
1748  const unsigned int colsNumber = segsIds.getColumnsNumber();
1749  const unsigned int linesNumber = segsIds.getLinesNumber();
1750 
1751  TERP_DEBUG_TRUE_OR_THROW( xStart < colsNumber,
1752  "Internal Error" )
1753  TERP_DEBUG_TRUE_OR_THROW( xBound <= colsNumber,
1754  "Internal Error" )
1755  TERP_DEBUG_TRUE_OR_THROW( yStart < linesNumber,
1756  "Internal Error" )
1757  TERP_DEBUG_TRUE_OR_THROW( yBound <= linesNumber,
1758  "Internal Error" )
1759  TERP_DEBUG_TRUE_OR_THROW( xStart < xBound, "Internal Error" )
1760  TERP_DEBUG_TRUE_OR_THROW( yStart < yBound, "Internal Error" )
1761 
1762  // finding the touching pixels
1763 
1764  edgeLength1 = 0;
1765  edgeLength2 = 0;
1766 
1767  unsigned int xIdx = 0;
1768  const unsigned int lastColIdx = colsNumber - 1;
1769  const unsigned int lastLineIdx = linesNumber - 1;
1770 
1771  for( unsigned int yIdx = yStart ; yIdx < yBound ; ++yIdx )
1772  {
1773  for( xIdx = xStart; xIdx < xBound ; ++xIdx )
1774  {
1775  if( segsIds[ yIdx ][ xIdx ] == id1 )
1776  {
1777  if( yIdx )
1778  if( segsIds[ yIdx - 1 ][ xIdx ] == id2 )
1779  {
1780  ++edgeLength1;
1781  continue;
1782  }
1783  if( xIdx )
1784  if( segsIds[ yIdx ][ xIdx - 1 ] == id2 )
1785  {
1786  ++edgeLength1;
1787  continue;
1788  }
1789  if( yIdx < lastLineIdx)
1790  if( segsIds[ yIdx + 1 ][ xIdx ] == id2 )
1791  {
1792  ++edgeLength1;
1793  continue;
1794  }
1795  if( xIdx < lastColIdx )
1796  if( segsIds[ yIdx ][ xIdx + 1 ] == id2 )
1797  {
1798  ++edgeLength1;
1799  continue;
1800  }
1801  }
1802  else if( segsIds[ yIdx ][ xIdx ] == id2 )
1803  {
1804  if( yIdx )
1805  if( segsIds[ yIdx - 1 ][ xIdx ] == id1 )
1806  {
1807  ++edgeLength2;
1808  continue;
1809  }
1810  if( xIdx )
1811  if( segsIds[ yIdx ][ xIdx - 1 ] == id1 )
1812  {
1813  ++edgeLength2;
1814  continue;
1815  }
1816  if( yIdx < lastLineIdx)
1817  if( segsIds[ yIdx + 1 ][ xIdx ] == id1 )
1818  {
1819  ++edgeLength2;
1820  continue;
1821  }
1822  if( xIdx < lastColIdx )
1823  if( segsIds[ yIdx ][ xIdx + 1 ] == id1 )
1824  {
1825  ++edgeLength2;
1826  continue;
1827  }
1828  }
1829  }
1830  }
1831  }
1832 
1833  //-------------------------------------------------------------------------
1834 
1836  : te::rp::SegmenterStrategyFactory( "RegionGrowing" )
1837  {
1838  }
1839 
1841  {
1842  }
1843 
1845  {
1847  }
1848 
1849  } // end namespace rp
1850 } // end namespace te
1851 
Matrix< SegmenterRegionGrowingSegment > & getSegsMatrix()
Return a reference to the internal segments matrix.
SegmenterRegionGrowingSegment::FeatureType getDissimilarity(SegmenterRegionGrowingSegment const *const segment1Ptr, SegmenterRegionGrowingSegment const *const segment2Ptr, SegmenterRegionGrowingSegment *const mergePreviewSegPtr) const
Returns a dimilarity index between this and the other segment.
Segmenter segments IDs manager.
virtual void setValue(unsigned int c, unsigned int r, const double value, std::size_t b=0)
Sets the attribute value in a band of a cell.
Definition: Raster.cpp:233
unsigned int mergeSmallSegments(const unsigned int minSegmentSize, SegmenterIdsManager &segmenterIdsManager, Merger &merger, SegmenterRegionGrowingSegment *auxSeg1Ptr, SegmenterRegionGrowingSegment *auxSeg2Ptr)
Merge only small segments to their closest segment.
void mergeFeatures(SegmenterRegionGrowingSegment *const segment1Ptr, SegmenterRegionGrowingSegment const *const segment2Ptr, SegmenterRegionGrowingSegment const *const mergePreviewSegPtr) const
Merge specific segment features from both segments into the first segment.
The Baatz based features will be used - Reference: Baatz, M.; Schape, A. Multiresolution segmentation...
#define BAATZ_SM(featPtr)
bool m_isInitialized
true if this instance is initialized.
Raster region growing segmenter strategy.
unsigned int m_neighborSegmentsSize
The current size of m_neighborSegments.
std::vector< SegmenterRegionGrowingSegment::FeatureType > m_bandsWeights
A vector where each bands weight are stored.
A raster band description.
Definition: BandProperty.h:61
bool initializeSegments(SegmenterIdsManager &segmenterIdsManager, const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, const std::vector< double > &inputRasterGains, const std::vector< double > &inputRasterOffsets)
Initialize the segment objects container and the segment IDs container.
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
#define BAATZ_SS(featPtr, bandsNmb, band)
SegmenterRegionGrowingStrategy::Parameters m_parameters
Internal execution parameters.
#define BAATZ_CO(featPtr)
unsigned int m_yBound
Segment lower bound Y coordinate box over the label image.
unsigned int m_xStart
Segment left X coordinate box over the label image.
SegmentsIdsMatrixT m_segmentsIdsMatrix
A internal segments IDs matrix that can be reused on each strategy execution.
SegmenterRegionGrowingSegment::FeatureType getDissimilarity(SegmenterRegionGrowingSegment const *const segment1Ptr, SegmenterRegionGrowingSegment const *const segment2Ptr, SegmenterRegionGrowingSegment *const mergePreviewSegPtr) const
Returns a dimilarity index between this and the other segment.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
void mergeFeatures(SegmenterRegionGrowingSegment *const segment1Ptr, SegmenterRegionGrowingSegment const *const segment2Ptr, SegmenterRegionGrowingSegment const *const mergePreviewSegPtr) const
Merge specific segment features from both segments into the first segment.
BaatzMerger(const double &colorWeight, const double &compactnessWeight, const std::vector< double > &bandsWeights, const SegmentsIdsMatrixT &segmentsIds, Matrix< SegmenterRegionGrowingSegment > &segmentsMatrix)
Default constructor.
virtual SegmenterRegionGrowingSegment::FeatureType getDissimilarity(SegmenterRegionGrowingSegment const *const segment1Ptr, SegmenterRegionGrowingSegment const *const segment2Ptr, SegmenterRegionGrowingSegment *const mergePreviewSegPtr) const =0
Returns a dimilarity index between this and the other segment.
unsigned int m_xBound
Segment lower bound X coordinate box over the label image.
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits::max().
Definition: BandProperty.h:136
Raster region growing segmenter strategy factory.
void addNeighborSegment(SegmenterRegionGrowingSegment *const nSegPtr)
Add a pointer of a neighbor segment (if it is not already there).
#define BAATZ_ST(featPtr, bandsNmb, band)
#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
Raster segmenter strategy factory base class.
std::vector< double > m_bandsWeights
The weight given to each band, when applicable (note: the bands weights sum must always be 1) or an e...
SegmenterRegionGrowingSegmentsPool m_segmentsPool
A pool of segments that can be reused on each strategy execution.
The mean of segments pixel values will be used - Reference: S. A. Bins, L. M. G. Fonseca, G. J. Erthal e F. M. Ii, "Satellite Imagery segmentation: a region growing approach", VIII Simposio Brasileiro de Sensoriamento Remoto, Salvador, BA, 14-19 abril 1996.
An abstract class for raster data strucutures.
Definition: Raster.h:71
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
unsigned int getColumnsNumber() const
The number of current matrix columns.
Definition: Matrix.h:678
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:370
Raster segmenter strategy base class.
SegmentFeaturesType m_segmentFeatures
What segment features will be used on the segmentation process (default:InvalidFeaturesType).
double getMemUsageEstimation(const unsigned int bandsToProcess, const unsigned int pixelsNumber) const
Returns a memory estimation (bytes).
unsigned int mergeSegments(const SegmenterRegionGrowingSegment::FeatureType disimilarityThreshold, SegmenterIdsManager &segmenterIdsManager, Merger &merger, const bool enablelocalMutualBestFitting, SegmenterRegionGrowingSegment *auxSeg1Ptr, SegmenterRegionGrowingSegment *auxSeg2Ptr, SegmenterRegionGrowingSegment *auxSeg3Ptr)
Merge closest segments.
void reset()
Clear all internal allocated resources and go back to the initial not-initialized state...
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
SegmenterRegionGrowingSegment * getNextSegment()
Retrive a stored segment.
bool initialize(const SegmenterSegmentsBlock::SegmentIdDataType segsNumber, const unsigned int featuresNumber)
Pool initialization.
te::rp::SegmenterStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
unsigned int getOptimalBlocksOverlapSize() const
Returns a optimal blocks overlap size (number of border pixels overlapped between blocks...
FeatureType * m_features
A pionter to a fixed size vector of segment features.
SegmenterRegionGrowingSegment ** m_neighborSegments
Neighborhood segments pointers (some pointers can be null) or a null pointer if there is no neighborh...
unsigned int m_size
Segment area (pixels number).
bool initialize(SegmenterStrategyParameters const *const strategyParams)
Initialize the segmentation strategy.
unsigned int m_minSegmentSize
A positive minimum segment size (pixels number - default: 100).
double m_segmentsSimilarityThreshold
Segments similarity treshold - Use lower values to merge only those segments that are more similar - ...
void reset()
Reset (clear) the active instance data.
Definition: Matrix.h:480
virtual void getValue(unsigned int c, unsigned int r, double &value, std::size_t b=0) const
Returns the attribute value of a band of a cell.
Definition: Raster.cpp:228
bool execute(SegmenterIdsManager &segmenterIdsManager, const te::rst::Raster &inputRaster, const std::vector< unsigned int > &inputRasterBands, const std::vector< double > &inputRasterGains, const std::vector< double > &inputRasterOffsets, te::rst::Raster &outputRaster, const unsigned int outputRasterBand, const bool enableProgressInterface)
Executes the segmentation strategy.
Abstract parameters base interface.
#define BAATZ_EL(featPtr)
unsigned int m_yStart
Segment upper Y coordinate box over the label image.
unsigned int m_bandsNumber
The number of features (bands).
A generic template matrix.
Definition: Matrix.h:51
static Raster * make()
It creates and returns an empty raster with default raster driver.
double m_colorWeight
The weight given to the color component, deafult:0.75, valid range: [0,1].
unsigned int m_segmentsSimIncreaseSteps
The maximum number of steps to increment the similarity threshold value for the cases where no segmen...
const Parameters & operator=(const Parameters &params)
virtual void mergeFeatures(SegmenterRegionGrowingSegment *const segment1Ptr, SegmenterRegionGrowingSegment const *const segment2Ptr, SegmenterRegionGrowingSegment const *const mergePreviewSegPtr) const =0
Merge specific segment features from both segments into the first segment.
void exportSegs2Tif(const SegmentsIdsMatrixT &segmentsIds, bool normto8bits, const std::string &fileName)
Export the segments IDs to a tif file.
double m_compactnessWeight
The weight given to the compactness component, deafult:0.5, valid range: [0,1].
AbstractParameters * clone() const
Create a clone copy of this instance.
void removeNeighborSegment(SegmenterRegionGrowingSegment *const nSegPtr)
Remove all occurrences of a neighbor segment.
#define TERP_DEBUG_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:356
static void getTouchingEdgeLength(const SegmentsIdsMatrixT &segsIds, const unsigned int &xStart, const unsigned int &yStart, const unsigned int &xBound, const unsigned int &yBound, const SegmenterSegmentsBlock::SegmentIdDataType &id1, const SegmenterSegmentsBlock::SegmentIdDataType &id2, unsigned int &edgeLength1, unsigned int &edgeLength2)
Returns the count of points from region 1 (with ID1) touching the region 2 (with ID2).
bool m_status
Segment status (active=true).
void addFreeIDs(const std::vector< SegmenterSegmentsBlock::SegmentIdDataType > &ids)
Stores free unique IDs for later use.
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
virtual void update()=0
Update the internal state.
unsigned int getLinesNumber() const
The number of current matrix lines.
Definition: Matrix.h:671
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:149
Raster region growing segmenter strategy.
void clearNeighborSegments()
Remove all neighbor segments.
bool getNewIDs(const unsigned int &idsNumber, std::vector< SegmenterSegmentsBlock::SegmentIdDataType > &ids)
Returns new segment unique IDs.
SegmenterSegmentsBlock::SegmentIdDataType m_id
Segment ID.
#define BAATZ_SU(featPtr, band)