All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator 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 
41 #include <boost/lexical_cast.hpp>
42 
43 namespace
44 {
46  segmenterRegionGrowingStrategyFactoryInstance;
47 }
48 
49 namespace te
50 {
51  namespace rp
52  {
53  //-------------------------------------------------------------------------
54 
56  {
57  reset();
58  }
59 
61  {
62  }
63 
67  {
68  reset();
69 
70  m_minSegmentSize = params.m_minSegmentSize;
71  m_segmentsSimilarityThreshold = params.m_segmentsSimilarityThreshold;
72  m_segmentFeatures = params.m_segmentFeatures;
73  m_bandsWeights = params.m_bandsWeights;
74  m_colorWeight = params.m_colorWeight;
75  m_compactnessWeight = params.m_compactnessWeight;
76  m_segmentsSimIncreaseSteps = params.m_segmentsSimIncreaseSteps;
77 
78  return *this;
79  }
80 
82  throw( te::rp::Exception )
83  {
84  m_minSegmentSize = 100;
85  m_segmentsSimilarityThreshold = 0.1;
86  m_segmentFeatures = InvalidFeaturesType;
87  m_bandsWeights.clear();
88  m_colorWeight = 0.5;
89  m_compactnessWeight = 0.5;
90  m_segmentsSimIncreaseSteps = 10;
91  }
92 
94  {
96  }
97 
98  //-------------------------------------------------------------------------
99 
101  {
102  }
103 
105  {
106  }
107 
111  {
112  m_id = other.m_id;
113  m_size = other.m_size;
114  m_xStart = other.m_xStart;
115  m_xBound = other.m_xBound;
116  m_yStart = other.m_yStart;
117  m_yBound = other.m_yBound;
118 
119  return other;
120  }
121 
122  //-------------------------------------------------------------------------
123 
125  {
126  }
127 
129  {
130  }
131 
132  //-------------------------------------------------------------------------
133 
135  SegmenterSegmentsPool& segmentsPool )
136  : std::map< SegmenterSegmentsBlock::SegmentIdDataType, Segment* >(),
137  m_segmentsPool( segmentsPool )
138  {
139  }
140 
142  {
143  clear();
144  }
145 
147  {
148  iterator segmentsIt = begin();
149  iterator segmentsItEnd = end();
150 
151  while( segmentsIt != segmentsItEnd )
152  {
153  m_segmentsPool.store(segmentsIt->second);
154 
155  ++segmentsIt;
156  }
157 
158  std::map< SegmenterSegmentsBlock::SegmentIdDataType, Segment* >::clear();
159  }
160 
161  //-------------------------------------------------------------------------
162 
164  {
165  }
166 
168  {
169  }
170 
173  const
174  {
176  newInstancePtr = new
178 
179  newInstancePtr->copy( this );
180 
181  return newInstancePtr;
182  }
183 
185  SegmenterRegionGrowingStrategy::SegmentFeatures const * const otherPtr )
186  {
188  otherCastPtr = dynamic_cast<
190  otherPtr );
191  TERP_DEBUG_TRUE_OR_THROW( otherCastPtr, "Invalid segment feature type" );
192 
193  m_means = otherCastPtr->m_means;
194 
196  };
197 
198  //-------------------------------------------------------------------------
199 
201  {
202  }
203 
205  {
206  }
207 
208  //-------------------------------------------------------------------------
209 
211  {
212  }
213 
215  {
216  }
217 
220  const
221  {
223  newInstancePtr = new
225 
226  newInstancePtr->copy( this );
227 
228  return newInstancePtr;
229  }
230 
232  SegmenterRegionGrowingStrategy::SegmentFeatures const * const otherPtr )
233  {
235  otherCastPtr = dynamic_cast<
237  otherPtr );
238  TERP_DEBUG_TRUE_OR_THROW( otherCastPtr, "Invalid segment feature type" );
239 
240  m_sums = otherCastPtr->m_sums;
241  m_squaresSum = otherCastPtr->m_squaresSum;
242  m_stdDev = otherCastPtr->m_stdDev;
243  m_edgeLength = otherCastPtr->m_edgeLength;
244  m_compactness = otherCastPtr->m_compactness;
245  m_smoothness = otherCastPtr->m_smoothness;
246 
248  };
249 
250  //-------------------------------------------------------------------------
251 
253  {
254  }
255 
257  {
258  }
259 
260  //-------------------------------------------------------------------------
261 
263  {
264  }
265 
267  {
268  }
269 
270  //-------------------------------------------------------------------------
271 
273  {
274  }
275 
277  {
278  }
279 
281  SegmenterRegionGrowingStrategy::Segment const * const segment1Ptr,
282  SegmenterRegionGrowingStrategy::Segment const * const segment2Ptr,
284  {
285  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< MeanBasedSegment const * const >(
286  segment1Ptr ), "Invalid segment type" );
287  MeanBasedSegment const * const segment1CastPtr =
288  (MeanBasedSegment*)(segment1Ptr);
289 
290  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< MeanBasedSegment const * const >(
291  segment2Ptr ), "Invalid segment type" );
292  MeanBasedSegment const * const segment2CastPtr =
293  (MeanBasedSegment*)(segment2Ptr);
294 
295  std::vector< double >::size_type meansSize =
296  segment1CastPtr->m_features.m_means.size();
297  TERP_DEBUG_TRUE_OR_THROW( meansSize ==
298  segment2CastPtr->m_features.m_means.size(),
299  "Internal error" );
300 
301  double dissValue = 0.0;
302  double diffValue = 0.0;
303 
304  for( std::vector< double >::size_type meansIdx = 0 ; meansIdx <
305  meansSize ; ++meansIdx )
306  {
307  diffValue = segment1CastPtr->m_features.m_means[ meansIdx ] -
308  segment2CastPtr->m_features.m_means[ meansIdx ];
309 
310  dissValue += ( diffValue * diffValue );
311  }
312 
313  return sqrt( dissValue );
314  }
315 
317  SegmenterRegionGrowingStrategy::Segment * const segment1Ptr,
318  Segment const * const segment2Ptr,
320  {
321  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< MeanBasedSegment * const >(
322  segment1Ptr ), "Invalid segment type" );
323  MeanBasedSegment * const segment1CastPtr =
324  (MeanBasedSegment*)(segment1Ptr);
325 
326  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< MeanBasedSegment const * const >(
327  segment2Ptr ), "Invalid segment type" );
328  MeanBasedSegment const * const segment2CastPtr =
329  (MeanBasedSegment*)(segment2Ptr);
330 
331  // Merging basic features
332 
333  segment1CastPtr->m_features.m_size += segment2CastPtr->m_features.m_size;
334 
335  segment1CastPtr->m_features.m_xStart = std::min(
336  segment1CastPtr->m_features.m_xStart,
337  segment2CastPtr->m_features.m_xStart );
338  segment1CastPtr->m_features.m_xBound = std::max(
339  segment1CastPtr->m_features.m_xBound,
340  segment2CastPtr->m_features.m_xBound );
341 
342  segment1CastPtr->m_features.m_yStart = std::min(
343  segment1CastPtr->m_features.m_yStart,
344  segment2CastPtr->m_features.m_yStart );
345  segment1CastPtr->m_features.m_yBound = std::max(
346  segment1CastPtr->m_features.m_yBound,
347  segment2CastPtr->m_features.m_yBound );
348 
349  // Merging specific features
350 
351  const std::vector< double >::size_type meansSize =
352  segment1CastPtr->m_features.m_means.size();
353  TERP_DEBUG_TRUE_OR_THROW( meansSize ==
354  segment2CastPtr->m_features.m_means.size(),
355  "Internal error" );
356 
357  for( std::vector< double >::size_type meansIdx = 0 ; meansIdx <
358  meansSize ; ++meansIdx )
359  {
360  segment1CastPtr->m_features.m_means[ meansIdx ] =
361  (
362  (
363  segment1CastPtr->m_features.m_means[ meansIdx ]
364  *
365  ((double)segment1CastPtr->m_features.m_size )
366  )
367  +
368  (
369  segment2CastPtr->m_features.m_means[ meansIdx ]
370  *
371  ( (double)segment2CastPtr->m_features.m_size)
372  )
373  )
374  /
375  (
376  (double)
377  ( segment1CastPtr->m_features.m_size
378  +
379  segment2CastPtr->m_features.m_size
380  )
381  );
382  }
383  }
384 
385  //-------------------------------------------------------------------------
386 
388  const double& colorWeight, const double& compactnessWeight,
389  const std::vector< double >& bandsWeights,
390  const SegmentsIdsMatrixT& segmentsIds,
392  :
393  m_allSegsCompactnessOffset( 0 ),
394  m_allSegsCompactnessGain( 1.0 ),
395  m_allSegsSmoothnessOffset( 0 ),
396  m_allSegsSmoothnessGain( 0 ),
397  m_colorWeight( colorWeight ),
398  m_compactnessWeight( compactnessWeight ),
399  m_bandsWeights( bandsWeights ),
400  m_segmentsIds( segmentsIds ),
401  m_segments( segments )
402  {
403  m_allSegsStdDevOffsets.resize( bandsWeights.size(), 0 );
404  m_allSegsStdDevGain.resize( bandsWeights.size(), 1 );
405  }
406 
408  {
409  }
410 
412  SegmenterRegionGrowingStrategy::Segment const * const segment1Ptr,
413  SegmenterRegionGrowingStrategy::Segment const * const segment2Ptr,
415  {
416  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< BaatzBasedSegment const * const >(
417  segment1Ptr ), "Invalid segment type" );
418  BaatzBasedSegment const * const segment1CastPtr =
419  (BaatzBasedSegment*)(segment1Ptr);
420 
421  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< BaatzBasedSegment const * const >(
422  segment2Ptr ), "Invalid segment type" );
423  BaatzBasedSegment const * const segment2CastPtr =
424  (BaatzBasedSegment*)(segment2Ptr);
425 
426  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< BaatzBasedSegment::SegmentFeatures* >(
427  mergedFeatures ), "Invalid features type" );
428  BaatzBasedSegment::SegmentFeatures* mergedFeaturesCastPtr =
429  (BaatzBasedSegment::SegmentFeatures*)(mergedFeatures);
430 
431  TERP_DEBUG_TRUE_OR_THROW( m_bandsWeights.size() ==
432  segment1CastPtr->m_features.m_sums.size(),
433  "Internal error" );
434 
435  const unsigned int sumsSize = segment1CastPtr->m_features.m_sums.size();
436  TERP_DEBUG_TRUE_OR_THROW( sumsSize ==
437  segment1CastPtr->m_features.m_stdDev.size(),
438  "Internal error" );
439  TERP_DEBUG_TRUE_OR_THROW( sumsSize ==
440  segment2CastPtr->m_features.m_sums.size(),
441  "Internal error" );
442  TERP_DEBUG_TRUE_OR_THROW( sumsSize ==
443  segment2CastPtr->m_features.m_stdDev.size(),
444  "Internal error" );
445 
446  mergedFeaturesCastPtr->m_sums.resize( sumsSize );
447  mergedFeaturesCastPtr->m_squaresSum.resize( sumsSize );
448  mergedFeaturesCastPtr->m_stdDev.resize( sumsSize );
449 
450  // globals
451 
452  mergedFeaturesCastPtr->m_size = segment1CastPtr->m_features.m_size +
453  segment2CastPtr->m_features.m_size;
454  TERP_DEBUG_TRUE_OR_THROW( mergedFeaturesCastPtr->m_size,
455  "Internal error" );
456  const double sizeUnionD = (double)mergedFeaturesCastPtr->m_size;
457 
458  const double sizeSeg1D = (double)segment1CastPtr->m_features.m_size;
459 
460  const double sizeSeg2D = (double)segment2CastPtr->m_features.m_size;
461 
462  // Finding the form heterogeneity
463 
464  mergedFeaturesCastPtr->m_xStart = std::min( segment1CastPtr->m_features.m_xStart,
465  segment2CastPtr->m_features.m_xStart );
466  mergedFeaturesCastPtr->m_yStart = std::min( segment1CastPtr->m_features.m_yStart,
467  segment2CastPtr->m_features.m_yStart );
468  mergedFeaturesCastPtr->m_xBound = std::max( segment1CastPtr->m_features.m_xBound,
469  segment2CastPtr->m_features.m_xBound );
470  mergedFeaturesCastPtr->m_yBound = std::max( segment1CastPtr->m_features.m_yBound,
471  segment2CastPtr->m_features.m_yBound );
472 
474  ( mergedFeaturesCastPtr->m_xBound > mergedFeaturesCastPtr->m_xStart ),
475  "Internal error" )
477  ( mergedFeaturesCastPtr->m_yBound > mergedFeaturesCastPtr->m_yStart ),
478  "Internal error" )
479 
480  unsigned int touchingEdgeLength1 = 0;
481  unsigned int touchingEdgeLength2 = 0;
483  m_segmentsIds, mergedFeaturesCastPtr->m_xStart,
484  mergedFeaturesCastPtr->m_yStart,
485  mergedFeaturesCastPtr->m_xBound,
486  mergedFeaturesCastPtr->m_yBound,
487  segment1CastPtr->m_features.m_id,
488  segment2CastPtr->m_features.m_id,
489  touchingEdgeLength1,
490  touchingEdgeLength2 );
491 
492  mergedFeaturesCastPtr->m_edgeLength =
493  segment1CastPtr->m_features.m_edgeLength - touchingEdgeLength1
494  +
495  segment2CastPtr->m_features.m_edgeLength - touchingEdgeLength2;
496 
497  mergedFeaturesCastPtr->m_compactness =
498  ((double)mergedFeaturesCastPtr->m_edgeLength) /
499  std::sqrt( sizeUnionD );
500 
501  mergedFeaturesCastPtr->m_smoothness =
502  ((double)mergedFeaturesCastPtr->m_edgeLength)
503  /
504  (double)(
505  (
506  2 * ( mergedFeaturesCastPtr->m_xBound - mergedFeaturesCastPtr->m_xStart )
507  )
508  +
509  (
510  2 * ( mergedFeaturesCastPtr->m_yBound - mergedFeaturesCastPtr->m_yStart )
511  )
512  );
513 
514  const double hCompact =
515  (
516  std::abs(
517  mergedFeaturesCastPtr->m_compactness
518  -
519  (
520  (
521  (
522  segment1CastPtr->m_features.m_compactness
523  *
524  sizeSeg1D
525  )
526  +
527  (
528  segment2CastPtr->m_features.m_compactness
529  *
530  sizeSeg2D
531  )
532  )
533  /
534  sizeUnionD
535  )
536  )
537  +
538  m_allSegsCompactnessOffset
539  )
540  *
541  m_allSegsCompactnessGain;
542 
543  const double hSmooth =
544  (
545  std::abs(
546  mergedFeaturesCastPtr->m_smoothness
547  -
548  (
549  (
550  (
551  segment1CastPtr->m_features.m_smoothness
552  *
553  sizeSeg1D
554  )
555  +
556  (
557  segment2CastPtr->m_features.m_smoothness
558  *
559  sizeSeg2D
560  )
561  )
562  /
563  sizeUnionD
564  )
565  )
566  +
567  m_allSegsSmoothnessOffset
568  )
569  *
570  m_allSegsSmoothnessGain;
571 
572  const double hForm =
573  (
574  (
575  m_compactnessWeight
576  *
577  hCompact
578  )
579  +
580  (
581  ( 1.0 - m_compactnessWeight )
582  *
583  hSmooth
584  )
585  );
586 
587  // Finding the color heterogeneity
588 
589  double hColor = 0;
590  double sumUnion = 0;
591  double squaresSumUnion = 0;
592  double meanUnion = 0;
593  double stdDevUnion = 0.0;
594 
595  for( unsigned int sumsIdx = 0 ; sumsIdx < sumsSize ; ++sumsIdx )
596  {
597  const double& sum1 = segment1CastPtr->m_features.m_sums[ sumsIdx ];
598 
599  const double& sum2 = segment2CastPtr->m_features.m_sums[ sumsIdx ];
600 
601  sumUnion = sum1 + sum2;
602  mergedFeaturesCastPtr->m_sums[ sumsIdx ] = sumUnion;
603 
604  squaresSumUnion = segment1CastPtr->m_features.m_squaresSum[ sumsIdx ] +
605  segment2CastPtr->m_features.m_squaresSum[ sumsIdx ];
606  mergedFeaturesCastPtr->m_squaresSum[ sumsIdx ] = squaresSumUnion;
607 
608  meanUnion = ( sum1 + sum2 ) / sizeUnionD;
609 
610  stdDevUnion =
611  (
612  (
613  squaresSumUnion
614  -
615  (
616  2.0 * meanUnion * sumUnion
617  )
618  +
619  (
620  sizeUnionD * meanUnion * meanUnion
621  )
622  )
623  /
624  sizeUnionD
625  );
626  mergedFeaturesCastPtr->m_stdDev[ sumsIdx ] = stdDevUnion;
627 
628  hColor +=
629  (
630  m_bandsWeights[ sumsIdx ]
631  *
632  (
633  (
634  std::abs(
635  stdDevUnion
636  -
637  (
638  (
639  (
640  segment1CastPtr->m_features.m_stdDev[ sumsIdx ]
641  *
642  sizeSeg1D
643  )
644  +
645  (
646  segment2CastPtr->m_features.m_stdDev[ sumsIdx ]
647  *
648  sizeSeg2D
649  )
650  )
651  /
652  sizeUnionD
653  )
654  )
655  +
656  m_allSegsStdDevOffsets[ sumsIdx ]
657  )
658  *
659  m_allSegsStdDevGain[ sumsIdx ]
660  )
661  );
662  }
663 
664  return
665  (
666  (
667  hColor
668  *
669  m_colorWeight
670  )
671  +
672  (
673  ( 1.0 - m_colorWeight )
674  *
675  hForm
676  )
677  );
678  }
679 
681  SegmenterRegionGrowingStrategy::Segment * const segment1Ptr,
682  Segment const * const ,
683  SegmenterRegionGrowingStrategy::SegmentFeatures const * const mergedFeatures ) const
684  {
685  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< BaatzBasedSegment * const >(
686  segment1Ptr ), "Invalid segment type" );
687  BaatzBasedSegment * const segment1CastPtr =
688  (BaatzBasedSegment*)(segment1Ptr);
689 
690  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< BaatzBasedSegment::SegmentFeatures const * const>(
691  mergedFeatures ), "Invalid features type" );
692  BaatzBasedSegment::SegmentFeatures const * const mergedFeaturesCastPtr =
693  (BaatzBasedSegment::SegmentFeatures const * const)(mergedFeatures);
694 
695  // Merging basic features
696 
697  segment1CastPtr->m_features.m_size = mergedFeaturesCastPtr->m_size;
698  segment1CastPtr->m_features.m_xStart = mergedFeaturesCastPtr->m_xStart;
699  segment1CastPtr->m_features.m_xBound = mergedFeaturesCastPtr->m_xBound;
700  segment1CastPtr->m_features.m_yStart = mergedFeaturesCastPtr->m_yStart;
701  segment1CastPtr->m_features.m_yBound = mergedFeaturesCastPtr->m_yBound;
702 
703  // Merging specific features
704 
705  segment1CastPtr->m_features.m_sums = mergedFeaturesCastPtr->m_sums;
706  segment1CastPtr->m_features.m_squaresSum = mergedFeaturesCastPtr->m_squaresSum;
707  segment1CastPtr->m_features.m_stdDev = mergedFeaturesCastPtr->m_stdDev;
708  segment1CastPtr->m_features.m_edgeLength = mergedFeaturesCastPtr->m_edgeLength;
709  segment1CastPtr->m_features.m_compactness = mergedFeaturesCastPtr->m_compactness;
710  segment1CastPtr->m_features.m_smoothness = mergedFeaturesCastPtr->m_smoothness;
711  }
712 
714  {
715  SegmenterRegionGrowingStrategy::SegmentsIndexer::const_iterator itB =
716  m_segments.begin();
717  const SegmenterRegionGrowingStrategy::SegmentsIndexer::const_iterator itE =
718  m_segments.end();
719  std::vector< double >::size_type dimIdx = 0;
720  std::vector< double >::size_type dimsNumber = m_bandsWeights.size();
721 
722  std::vector< double > stdDevMin( dimsNumber, DBL_MAX );
723  std::vector< double > stdDevMax( dimsNumber, -1.0 * DBL_MAX );
724 
725  double compactnessMin = DBL_MAX;
726  double compactnessMax = -1.0 * DBL_MAX;
727 
728  double smoothnessMin = DBL_MAX;
729  double smoothnessMax = -1.0 * DBL_MAX;
730 
731  SegmenterRegionGrowingStrategy::BaatzBasedSegment const * segmentCastPtr = 0;
732 
733  while( itB != itE )
734  {
735  TERP_DEBUG_TRUE_OR_THROW( dynamic_cast< BaatzBasedSegment const * >(
736  itB->second ), "Invalid segment type" );
737  segmentCastPtr = (BaatzBasedSegment const*)(itB->second);
738  TERP_DEBUG_TRUE_OR_THROW( segmentCastPtr->m_features.m_stdDev.size()
739  == dimsNumber, "Invalid dims number" )
740 
741  for( dimIdx = 0; dimIdx < dimsNumber ; ++dimIdx )
742  {
743  if( stdDevMin[ dimIdx ] > segmentCastPtr->m_features.m_stdDev[ dimIdx ] )
744  stdDevMin[ dimIdx ] = segmentCastPtr->m_features.m_stdDev[ dimIdx ];
745  if( stdDevMax[ dimIdx ] < segmentCastPtr->m_features.m_stdDev[ dimIdx ] )
746  stdDevMax[ dimIdx ] = segmentCastPtr->m_features.m_stdDev[ dimIdx ];
747  }
748 
749  if( compactnessMin > segmentCastPtr->m_features.m_compactness )
750  compactnessMin = segmentCastPtr->m_features.m_compactness;
751  if( compactnessMax < segmentCastPtr->m_features.m_compactness )
752  compactnessMax = segmentCastPtr->m_features.m_compactness;
753 
754  if( smoothnessMin > segmentCastPtr->m_features.m_smoothness )
755  smoothnessMin = segmentCastPtr->m_features.m_smoothness;
756  if( smoothnessMax < segmentCastPtr->m_features.m_smoothness )
757  smoothnessMax = segmentCastPtr->m_features.m_smoothness;
758 
759  ++itB;
760  }
761 
762  for( dimIdx = 0; dimIdx < dimsNumber ; ++dimIdx )
763  {
764  if( stdDevMax[ dimIdx ] == stdDevMin[ dimIdx ] )
765  {
766  m_allSegsStdDevOffsets[ dimIdx ] = 0.0;
767 
768  if( stdDevMax[ dimIdx ] == 0.0 )
769  m_allSegsStdDevGain[ dimIdx ] = 1.0;
770  else
771  m_allSegsStdDevGain[ dimIdx ] = 1.0 / stdDevMax[ dimIdx ];
772  }
773  else
774  {
775  m_allSegsStdDevOffsets[ dimIdx ] = -1.0 * stdDevMin[ dimIdx ];
776  m_allSegsStdDevGain[ dimIdx ] = 1.0 /
777  ( stdDevMax[ dimIdx ] - stdDevMin[ dimIdx ] );
778  }
779  }
780 
781  if( compactnessMax == compactnessMin )
782  {
783  m_allSegsCompactnessOffset = 0.0;
784 
785  if( compactnessMax == 0.0 )
786  m_allSegsCompactnessGain = 1.0;
787  else
788  m_allSegsCompactnessGain = 1.0 / compactnessMax;
789  }
790  else
791  {
792  m_allSegsCompactnessOffset = -1.0 * compactnessMin;
793  m_allSegsCompactnessGain = 1.0 / ( compactnessMax - compactnessMin );
794  }
795 
796  if( smoothnessMax == smoothnessMin )
797  {
798  m_allSegsSmoothnessOffset = 0.0;
799 
800  if( smoothnessMax == 0.0 )
801  m_allSegsSmoothnessGain = 1.0;
802  else
803  m_allSegsSmoothnessGain = 1.0 / smoothnessMax;
804  }
805  else
806  {
807  m_allSegsSmoothnessOffset = -1.0 * smoothnessMin;
808  m_allSegsSmoothnessGain = 1.0 / ( smoothnessMax - smoothnessMin );
809  }
810  }
811 
812  //-------------------------------------------------------------------------
813 
815  {
816  m_isInitialized = false;
817  }
818 
820  {
821  reset();
822  }
823 
825  SegmenterStrategyParameters const* const strategyParams )
826  throw( te::rp::Exception )
827  {
828  m_isInitialized = false;
829  reset();
830 
832  dynamic_cast< SegmenterRegionGrowingStrategy::Parameters const* >( strategyParams );
833 
834  if( paramsPtr )
835  {
836  m_parameters = *( paramsPtr );
837 
839  "Invalid segmenter strategy parameter m_minSegmentSize" )
840 
843  "Invalid segmenter strategy parameter m_segmentsSimilarityThreshold" )
844 
847  "Invalid segmenter strategy parameter m_segmentFeatures" )
848 
849  if( ! m_parameters.m_bandsWeights.empty() )
850  {
851  TERP_TRUE_OR_RETURN_FALSE( paramsPtr->m_bandsWeights.size(),
852  "Invalid segmenter strategy parameter m_bandsWeights" );
853  double bandsWeightsSum = 0;
854  for( unsigned int bandsWeightsIdx = 0 ; bandsWeightsIdx <
855  paramsPtr->m_bandsWeights.size() ; ++bandsWeightsIdx )
856  {
857  bandsWeightsSum += paramsPtr->m_bandsWeights[ bandsWeightsIdx ];
858  }
859  TERP_TRUE_OR_RETURN_FALSE( bandsWeightsSum == 1.0,
860  "Invalid segmenter strategy parameter m_bandsWeights" );
861  }
862 
863  m_isInitialized = true;
864 
865  return true;
866  }
867  else
868  {
869  return false;
870  }
871  }
872 
874  {
875  m_isInitialized = false;
879  };
880 
882  SegmenterIdsManager& segmenterIdsManager,
883  const te::rst::Raster& inputRaster,
884  const std::vector< unsigned int >& inputRasterBands,
885  const std::vector< double >& inputRasterGains,
886  const std::vector< double >& inputRasterOffsets,
887  te::rst::Raster& outputRaster,
888  const unsigned int outputRasterBand,
889  const bool enableProgressInterface )
890  throw( te::rp::Exception )
891  {
893  "Instance not initialized" )
894 
895  // Updating the bands weights info, if needed
896 
897  if( m_parameters.m_bandsWeights.empty() )
898  m_parameters.m_bandsWeights.resize( inputRasterBands.size(), 1.0 /
899  ((double)inputRasterBands.size()) );
900 
901  // Initializing segments
902 
903  SegmentsIndexer segmentsIndexer( m_segmentsPool );
904  TERP_TRUE_OR_RETURN_FALSE( initializeSegments( segmenterIdsManager,
905  inputRaster, inputRasterBands, inputRasterGains,
906  inputRasterOffsets, segmentsIndexer ),
907  "Segments initalization error" );
908 
909  // Creating the merger instance
910 
911  std::auto_ptr< Merger > mergerPtr;
912  bool enablelocalMutualBestFitting = false;
913 
915  {
917  {
918  mergerPtr.reset( new MeanMerger() );
919  enablelocalMutualBestFitting = true;
920  break;
921  }
923  {
924  mergerPtr.reset( new BaatzMerger( m_parameters.m_colorWeight,
926  m_segmentsIdsMatrix, segmentsIndexer ) );
927  enablelocalMutualBestFitting = true;
928  break;
929  }
930  default :
931  {
932  TERP_LOG_AND_THROW( "Invalid segment features type" );
933  break;
934  }
935  }
936 
937  // Progress interface
938 
939  std::auto_ptr< te::common::TaskProgress > progressPtr;
940  if( enableProgressInterface )
941  {
942  progressPtr.reset( new te::common::TaskProgress );
943  progressPtr->setTotalSteps( 100 );
944  progressPtr->setMessage( "Segmentation" );
945  }
946 
947  // Segmentation loop
948 
949  double similarityThreshold = m_parameters.m_segmentsSimilarityThreshold /
951  unsigned int mergedSegments = 0;
952  unsigned int maxMergedSegments = 0;
953  unsigned int noMergeIterations = 0;
954  int currStep = 0;
955 
956 // exportSegs2Tif( segmentsIds, true, "merging" +
957 // te::common::Convert2String( mergetIterations ) + ".tif" );
958 
959  while ( true )
960  {
961  mergedSegments = mergeSegments( similarityThreshold, segmenterIdsManager,
962  *mergerPtr, enablelocalMutualBestFitting, segmentsIndexer );
963 // exportSegs2Tif( segmentsIds, true, "merging" +
964 // te::common::Convert2String( mergetIterations ) + ".tif" );
965 
966  if( enableProgressInterface )
967  {
968  if( maxMergedSegments )
969  {
970  currStep = (int)
971  (
972  (
973  (
974  ( (double)( maxMergedSegments - mergedSegments ) )
975  /
976  ((double)maxMergedSegments )
977  )
978  )
979  *
980  50.0
981  );
982 
983  if( currStep > progressPtr->getCurrentStep() )
984  {
985  progressPtr->setCurrentStep( currStep );
986  }
987  }
988 
989  if( ! progressPtr->isActive() )
990  {
991  return false;
992  }
993 
994  if( maxMergedSegments < mergedSegments )
995  {
996  maxMergedSegments = mergedSegments;
997  }
998  }
999 
1000  if( mergedSegments == 0 )
1001  {
1002  ++noMergeIterations;
1003 
1004  if( noMergeIterations > m_parameters.m_segmentsSimIncreaseSteps )
1005  {
1006  break;
1007  }
1008  else
1009  {
1010  similarityThreshold +=
1011  (
1013  /
1014  ( (double)( m_parameters.m_segmentsSimIncreaseSteps + 1 ) )
1015  );
1016  }
1017  }
1018  }
1019 
1020  if( enableProgressInterface )
1021  {
1022  progressPtr->setCurrentStep( 50 );
1023  if( ! progressPtr->isActive() )
1024  {
1025  return false;
1026  }
1027  }
1028 
1029  if( m_parameters.m_minSegmentSize > 1 )
1030  {
1031  maxMergedSegments = 0;
1032 
1033  while( true )
1034  {
1036  segmenterIdsManager, *mergerPtr, segmentsIndexer );
1037 // exportSegs2Tif( segmentsIds, true, "mergingSmall" +
1038 // te::common::Convert2String( mergetIterations ) + ".tif" );
1039 
1040  if( enableProgressInterface )
1041  {
1042  if( maxMergedSegments )
1043  {
1044  currStep = 50 + (int)
1045  (
1046  (
1047  (
1048  ( (double)( maxMergedSegments - mergedSegments ) )
1049  /
1050  ((double)maxMergedSegments )
1051  )
1052  )
1053  *
1054  50.0
1055  );
1056 
1057  if( currStep > progressPtr->getCurrentStep() )
1058  {
1059  progressPtr->setCurrentStep( currStep );
1060  }
1061  }
1062 
1063  if( ! progressPtr->isActive() )
1064  {
1065  return false;
1066  }
1067 
1068  if( maxMergedSegments < mergedSegments )
1069  {
1070  maxMergedSegments = mergedSegments;
1071  }
1072  }
1073 
1074  if( mergedSegments == 0 )
1075  {
1076  break;
1077  }
1078  }
1079  }
1080 
1081  if( enableProgressInterface )
1082  {
1083  progressPtr->setCurrentStep( 100 );
1084  if( ! progressPtr->isActive() )
1085  {
1086  return false;
1087  }
1088  }
1089 
1090  // Flush result to the output raster
1091 
1092  {
1093  const unsigned int nLines = inputRaster.getNumberOfRows();
1094  const unsigned int nCols = inputRaster.getNumberOfColumns();
1095  unsigned int col = 0;
1096  SegmenterSegmentsBlock::SegmentIdDataType* segmentsIdsLinePtr = 0;
1097 
1098  for( unsigned int line = 0 ; line < nLines ; ++line )
1099  {
1100  segmentsIdsLinePtr = m_segmentsIdsMatrix[ line ];
1101 
1102  for( col = 0 ; col < nCols ; ++col )
1103  {
1104  outputRaster.setValue( col, line, segmentsIdsLinePtr[ col ], outputRasterBand );
1105  }
1106  }
1107  }
1108 
1109  return true;
1110  }
1111 
1113  const unsigned int bandsToProcess,
1114  const unsigned int pixelsNumber ) const
1115  {
1116  TERP_TRUE_OR_THROW( m_isInitialized, "Instance not initialized" );
1117 
1118  // Test case: 6768 x 67923 = 45968256 pixels image
1119  // case1: 1 band
1120  // case2: 3 bands
1121 
1122  double minM = 0;
1123  double maxM = 0;
1124 
1126  {
1128  {
1129  minM = 17009.0; // MB
1130  maxM = 17711.0; // MB
1131  break;
1132  }
1134  {
1135  minM = 23629.4; // MB
1136  maxM = 24597.0; // MB
1137  break;
1138  }
1139  default :
1140  {
1141  TERP_LOG_AND_THROW( "Invalid segment features type" );
1142  break;
1143  }
1144  }
1145 
1146  if( bandsToProcess == 3 )
1147  {
1148  return maxM;
1149  }
1150  else
1151  {
1152  double dM = ( maxM - minM );
1153  double slope = dM / ( 3.0 - ((double)bandsToProcess) );
1154 
1155  return (
1156  ( ((double)bandsToProcess) * slope ) + minM
1157  )
1158  *
1159  (
1160  ((double)pixelsNumber) / 45968256.0
1161  )
1162  *
1163  (
1164  1024.0 * 1024.0
1165  );
1166  }
1167  }
1168 
1170  {
1171  TERP_TRUE_OR_THROW( m_isInitialized, "Instance not initialized" );
1172  return (unsigned int)( std::sqrt( (double)m_parameters.m_minSegmentSize) );
1173  }
1174 
1176  SegmenterIdsManager& segmenterIdsManager,
1177  const te::rst::Raster& inputRaster,
1178  const std::vector< unsigned int >& inputRasterBands,
1179  const std::vector< double >& inputRasterGains,
1180  const std::vector< double >& inputRasterOffsets,
1181  SegmentsIndexer& segsIndexer )
1182  {
1183  segsIndexer.clear();
1184 
1185  const unsigned int nLines = inputRaster.getNumberOfRows();
1186  const unsigned int nCols = inputRaster.getNumberOfColumns();
1187  const unsigned int inputRasterBandsSize = (unsigned int)
1188  inputRasterBands.size();
1189 
1190  // Allocating the ids matrix
1191 
1192  if( ( m_segmentsIdsMatrix.getLinesNumber() != nLines ) ||
1193  ( m_segmentsIdsMatrix.getColumnsNumber() != nCols ) )
1194  {
1197  "Error allocating segments Ids matrix" );
1198  }
1199 
1200  // fiding band dummy values
1201 
1202  std::vector< double > bandDummyValues;
1203 
1204  {
1205  for( unsigned int inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
1206  inputRasterBandsSize ; ++inputRasterBandsIdx )
1207  {
1208  bandDummyValues.push_back( inputRaster.getBand(
1209  inputRasterBands[ inputRasterBandsIdx ] )->getProperty()->m_noDataValue );
1210  }
1211  }
1212 
1213  // Indexing each segment
1214 
1215  unsigned int line = 0;
1216  unsigned int col = 0;
1217  Segment* segmentPtr = 0;
1218  Segment* neighborSegmentPtr = 0;
1219  SegmenterSegmentsBlock::SegmentIdDataType neighborSegmentId = 0;
1220  bool rasterValuesAreValid = true;
1221  unsigned int inputRasterBandsIdx = 0;
1222  double value = 0;
1223  const std::vector< double > dummyZeroesVector( inputRasterBandsSize, 0 );
1224 
1225  std::list< SegmenterSegmentsBlock::SegmentIdDataType >
1226  unusedLineSegmentIds;
1227 
1228  std::vector< SegmenterSegmentsBlock::SegmentIdDataType >
1229  lineSegmentIds;
1230  lineSegmentIds.reserve( nCols );
1231 
1232  std::vector< double > rasterValues;
1233  std::vector< double > rasterSquareValues;
1234  rasterValues.resize( inputRasterBandsSize, 0 );
1235  rasterSquareValues.resize( inputRasterBandsSize, 0 );
1236 
1237  for( line = 0 ; line < nLines ; ++line )
1238  {
1239  segmenterIdsManager.getNewIDs( nCols, lineSegmentIds );
1240 
1241  for( col = 0 ; col < nCols ; ++col )
1242  {
1243  rasterValuesAreValid = true;
1244 
1245  for( inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
1246  inputRasterBandsSize ; ++inputRasterBandsIdx )
1247  {
1248  inputRaster.getValue( col, line, value,
1249  inputRasterBands[ inputRasterBandsIdx ] );
1250 
1251  if( value == bandDummyValues[ inputRasterBandsIdx ] )
1252  {
1253  rasterValuesAreValid = false;
1254  break;
1255  }
1256  else
1257  {
1258  value += inputRasterOffsets[ inputRasterBandsIdx ];
1259  value *= inputRasterGains[ inputRasterBandsIdx ];
1260 
1261  rasterValues[ inputRasterBandsIdx ] = value;
1262  rasterSquareValues[ inputRasterBandsIdx ] = value * value;
1263  }
1264  }
1265 
1266  // assotiating a segment object
1267 
1268  if( rasterValuesAreValid )
1269  {
1271  {
1273  {
1274  segmentPtr = (MeanBasedSegment*)m_segmentsPool.retrive();
1275 
1276  if( segmentPtr == 0 )
1277  {
1278  segmentPtr = new MeanBasedSegment();
1279  }
1280 
1281  ((MeanBasedSegment*)segmentPtr)->m_features.m_means = rasterValues;
1282  break;
1283  }
1285  {
1286  segmentPtr = (BaatzBasedSegment*)m_segmentsPool.retrive();
1287 
1288  if( segmentPtr == 0 )
1289  {
1290  segmentPtr = new BaatzBasedSegment();
1291  }
1292 
1293  ((BaatzBasedSegment*)segmentPtr)->m_features.m_sums = rasterValues;
1294  ((BaatzBasedSegment*)segmentPtr)->m_features.m_squaresSum = rasterSquareValues;
1295  ((BaatzBasedSegment*)segmentPtr)->m_features.m_stdDev = dummyZeroesVector;
1296  ((BaatzBasedSegment*)segmentPtr)->m_features.m_edgeLength = 4;
1297  ((BaatzBasedSegment*)segmentPtr)->m_features.m_compactness = 4;
1298  ((BaatzBasedSegment*)segmentPtr)->m_features.m_smoothness = 1;
1299  break;
1300  }
1301  default :
1302  {
1303  TERP_LOG_AND_THROW( "Invalid segment features type" );
1304  break;
1305  }
1306  }
1307 
1308  segmentPtr->getFeatures()->m_id = lineSegmentIds[ col ];
1309  segmentPtr->getFeatures()->m_size = 1;
1310  segmentPtr->getFeatures()->m_xStart = col;
1311  segmentPtr->getFeatures()->m_xBound = col + 1;
1312  segmentPtr->getFeatures()->m_yStart = line;
1313  segmentPtr->getFeatures()->m_yBound = line + 1;
1314 
1315  m_segmentsIdsMatrix( line, col ) = segmentPtr->getFeatures()->m_id;
1316  segsIndexer[ segmentPtr->getFeatures()->m_id ] = segmentPtr;
1317 
1318  // updating the neighboorhood info
1319 
1320  segmentPtr->m_neighborSegments.clear();
1321 
1322  if( line )
1323  {
1324  neighborSegmentId = m_segmentsIdsMatrix( line - 1, col );
1325 
1326  if( neighborSegmentId )
1327  {
1328  neighborSegmentPtr = segsIndexer[ neighborSegmentId ];
1329  TERP_DEBUG_TRUE_OR_THROW( neighborSegmentPtr,
1330  "Invalid neighboorSegmentPtr" );
1331 
1332  segmentPtr->m_neighborSegments.push_back( neighborSegmentPtr );
1333 
1334  neighborSegmentPtr->m_neighborSegments.push_back( segmentPtr );
1335  }
1336  }
1337 
1338  if( col )
1339  {
1340  neighborSegmentId = m_segmentsIdsMatrix( line, col - 1 );
1341 
1342  if( neighborSegmentId )
1343  {
1344  neighborSegmentPtr = segsIndexer[ neighborSegmentId ];
1345  TERP_DEBUG_TRUE_OR_THROW( neighborSegmentPtr,
1346  "Invalid neighboorSegmentPtr" );
1347 
1348  segmentPtr->m_neighborSegments.push_back( neighborSegmentPtr );
1349 
1350  neighborSegmentPtr->m_neighborSegments.push_back( segmentPtr );
1351  }
1352  }
1353  }
1354  else // !rasterValueIsValid
1355  {
1356  m_segmentsIdsMatrix( line, col ) = 0;
1357  unusedLineSegmentIds.push_back( lineSegmentIds[ col ] );
1358  }
1359  }
1360 
1361  // Free unused IDs
1362 
1363  if( ! unusedLineSegmentIds.empty() )
1364  {
1365  segmenterIdsManager.addFreeIDs( unusedLineSegmentIds );
1366  unusedLineSegmentIds.clear();
1367  }
1368  }
1369 
1370  return true;
1371  }
1372 
1374  const double similarityThreshold,
1375  SegmenterIdsManager& segmenterIdsManager,
1376  Merger& merger,
1377  const bool enablelocalMutualBestFitting,
1378  SegmentsIndexer& segsIndexer )
1379  {
1380  unsigned int mergedSegmentsNumber = 0;
1381 
1382  std::list< Segment* >::iterator nSegsIt;
1383  std::list< Segment* >::iterator nSegsItEnd;
1384 
1385  std::list< Segment* >::iterator nSegNSegsIt;
1386  std::list< Segment* >::iterator nSegNSegsItEnd;
1387 
1388  std::list< Segment* >::iterator minForwardDissimilaritySegmentIt;
1389  double minForwardDissimilarityValue = 0;
1391  minForwardDissimilaritySegmentId = 0;
1392 
1393  std::list< Segment* >::iterator minBackwardDissimilaritySegmentIt;
1394 // Segment* minBackwardDissimilaritySegmentPtr;
1395  double minBackwardDissimilarityValue = 0;
1396 
1397  double forwardDissimilarityValue = 0;
1398  double backwardDissimilarityValue = 0;
1399 
1400  unsigned int segmentsLine = 0;
1401  unsigned int segmentsLineBound = 0;
1402  unsigned int segmentCol = 0;
1403  unsigned int segmentColStart = 0;
1404  unsigned int segmentColBound = 0;
1405 
1406  SegmenterSegmentsBlock::SegmentIdDataType* segmentsIdsLinePtr = 0;
1407 
1408  SegmenterSegmentsBlock::SegmentIdDataType currentSegmentId = 0;
1409 
1410  std::list< SegmenterSegmentsBlock::SegmentIdDataType > freeSegmentIds;
1411 
1412  // initializing the auxiliary segment features
1413 
1414  std::auto_ptr< SegmentFeatures > auxSegFeatures1;
1415  std::auto_ptr< SegmentFeatures > auxSegFeatures2;
1416  std::auto_ptr< SegmentFeatures > minForwardDissimilaritySegmentFeatures;
1417  if( ! segsIndexer.empty() )
1418  {
1419  auxSegFeatures1.reset(
1420  segsIndexer.begin()->second->getFeatures()->clone() );
1421  auxSegFeatures2.reset(
1422  segsIndexer.begin()->second->getFeatures()->clone() );
1423  minForwardDissimilaritySegmentFeatures.reset(
1424  segsIndexer.begin()->second->getFeatures()->clone() );
1425  }
1426 
1427  // Updating the merger state
1428 
1429  merger.update();
1430 
1431  // iterating over each segment
1432 
1433  SegmentsIndexer::iterator segsIt = segsIndexer.begin();
1434 
1435  while( segsIt != segsIndexer.end() )
1436  {
1437  // finding the neighbor segment with minimum dissimilary value
1438  // related to the current sement
1439 
1440  nSegsIt = segsIt->second->m_neighborSegments.begin();
1441  nSegsItEnd = segsIt->second->m_neighborSegments.end();
1442 
1443  minForwardDissimilaritySegmentIt = nSegsItEnd;
1444  minForwardDissimilarityValue = DBL_MAX;
1445 
1446  while( nSegsIt != nSegsItEnd )
1447  {
1448  forwardDissimilarityValue = merger.getDissimilarityIndex( segsIt->second,
1449  *nSegsIt, auxSegFeatures1.get() );
1450 
1451  if( ( forwardDissimilarityValue < similarityThreshold ) &&
1452  ( forwardDissimilarityValue < minForwardDissimilarityValue ) )
1453  {
1454  minForwardDissimilarityValue = forwardDissimilarityValue;
1455  minForwardDissimilaritySegmentIt = nSegsIt;
1456  minForwardDissimilaritySegmentId =
1457  (*minForwardDissimilaritySegmentIt)->getFeatures()->m_id;
1458  minForwardDissimilaritySegmentFeatures->copy( auxSegFeatures1.get() );
1459  }
1460 
1461  ++nSegsIt;
1462  }
1463 
1464  // does the neighbor wants to merge back ?
1465 
1466  if( enablelocalMutualBestFitting &&
1467  (minForwardDissimilaritySegmentIt != nSegsItEnd ) )
1468  {
1469  // Calculating all neighbor neighbor segments dissimilarity
1470 
1471  minBackwardDissimilaritySegmentIt =
1472  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.end();
1473  minBackwardDissimilarityValue = DBL_MAX;
1474 
1475  nSegNSegsIt =
1476  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.begin();
1477  nSegNSegsItEnd =
1478  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.end();
1479 
1480  while( nSegNSegsIt != nSegNSegsItEnd )
1481  {
1482  backwardDissimilarityValue =
1483  merger.getDissimilarityIndex( *minForwardDissimilaritySegmentIt,
1484  *nSegNSegsIt, auxSegFeatures2.get() );
1485 
1486  if( backwardDissimilarityValue < minBackwardDissimilarityValue )
1487  {
1488  minBackwardDissimilarityValue = backwardDissimilarityValue;
1489  minBackwardDissimilaritySegmentIt = nSegNSegsIt;
1490  }
1491 
1492  ++nSegNSegsIt;
1493  }
1494 
1495  if(
1496  (
1497  minBackwardDissimilaritySegmentIt
1498  ==
1499  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.end()
1500  )
1501  ||
1502  (
1503  ( *minBackwardDissimilaritySegmentIt )
1504  !=
1505  segsIt->second
1506  )
1507  )
1508  {
1509  minForwardDissimilaritySegmentIt = nSegsItEnd;
1510  }
1511  }
1512 
1513  // If the minimum dissimilary neighbor was found it will be merged
1514 
1515  if( minForwardDissimilaritySegmentIt != nSegsItEnd )
1516  {
1517  // merging segment data
1518 
1519  merger.mergeFeatures( segsIt->second, *minForwardDissimilaritySegmentIt,
1520  minForwardDissimilaritySegmentFeatures.get() );
1521 
1522  // updating the min dissimilarity segment neighborhood segments
1523  // with the current segment
1524 
1525  nSegNSegsIt =
1526  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.begin();
1527  nSegNSegsItEnd =
1528  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.end();
1529 
1530  while( nSegNSegsIt != nSegNSegsItEnd )
1531  {
1532  if( (*nSegNSegsIt) != segsIt->second )
1533  {
1534  // adding the min dissimilarity neighborhood segment to the
1535  // current one, if it is not already there
1536 
1537  if( std::find( segsIt->second->m_neighborSegments.begin(),
1538  segsIt->second->m_neighborSegments.end(), (*nSegNSegsIt) ) ==
1539  segsIt->second->m_neighborSegments.end() )
1540  {
1541  segsIt->second->m_neighborSegments.push_back( *nSegNSegsIt );
1542  }
1543 
1544  // adding the current segment into the min dissimilarity
1545  // neighborhood segments list, if it is not already there
1546 
1547  if( std::find( (*nSegNSegsIt)->m_neighborSegments.begin(),
1548  (*nSegNSegsIt)->m_neighborSegments.end(), segsIt->second ) ==
1549  (*nSegNSegsIt)->m_neighborSegments.end() )
1550  {
1551  (*nSegNSegsIt)->m_neighborSegments.push_back( segsIt->second );
1552  }
1553 
1554  // removing the merged segment reference from its neighbor
1555  // list
1556 
1557  (*nSegNSegsIt)->m_neighborSegments.remove(
1558  *minForwardDissimilaritySegmentIt );
1559  }
1560 
1561  ++nSegNSegsIt;
1562  }
1563 
1564  // updating the segments Ids indexer
1565 
1566  segmentsLineBound = (*minForwardDissimilaritySegmentIt)->getFeatures()->m_yBound;
1567  segmentColStart = (*minForwardDissimilaritySegmentIt)->getFeatures()->m_xStart;
1568  segmentColBound = (*minForwardDissimilaritySegmentIt)->getFeatures()->m_xBound;
1569  currentSegmentId = segsIt->second->getFeatures()->m_id;
1570 
1571  for( segmentsLine = (*minForwardDissimilaritySegmentIt)->getFeatures()->m_yStart ;
1572  segmentsLine < segmentsLineBound ; ++segmentsLine )
1573  {
1574  segmentsIdsLinePtr = m_segmentsIdsMatrix[ segmentsLine ];
1575 
1576  for( segmentCol = segmentColStart ; segmentCol <
1577  segmentColBound ; ++segmentCol )
1578  {
1579  if( segmentsIdsLinePtr[ segmentCol ] ==
1580  minForwardDissimilaritySegmentId )
1581  {
1582  segmentsIdsLinePtr[ segmentCol ] = currentSegmentId;
1583  }
1584  }
1585  }
1586 
1587  // moving to the pool the merged segment from the list
1588  // of neighborhood segments and from the global
1589  // segments container
1590  // The merged segment id will be given back to ids manager
1591 
1592  m_segmentsPool.store( *minForwardDissimilaritySegmentIt );
1593 
1594  segsIt->second->m_neighborSegments.erase(
1595  minForwardDissimilaritySegmentIt );
1596 
1597  segsIndexer.erase( minForwardDissimilaritySegmentId );
1598 
1599  freeSegmentIds.push_back( minForwardDissimilaritySegmentId );
1600 
1601  ++mergedSegmentsNumber;
1602  }
1603 
1604  ++segsIt;
1605  }
1606 
1607  // give back the free unused sement ids
1608 
1609  if( ! freeSegmentIds.empty() )
1610  {
1611  segmenterIdsManager.addFreeIDs( freeSegmentIds );
1612  }
1613 
1614  return mergedSegmentsNumber;
1615  }
1616 
1618  const unsigned int minSegmentSize,
1619  SegmenterIdsManager& segmenterIdsManager,
1620  Merger& merger,
1621  SegmentsIndexer& segsIndexer )
1622  {
1623  unsigned int mergedSegmentsNumber = 0;
1624 
1625  std::list< Segment* >::iterator nSegsIt;
1626  std::list< Segment* >::iterator nSegsItEnd;
1627 
1628  std::list< Segment* >::iterator nSegNSegsIt;
1629  std::list< Segment* >::iterator nSegNSegsItEnd;
1630 
1631  std::list< Segment* >::iterator minForwardDissimilaritySegmentIt;
1632  double minForwardDissimilarityValue = 0;
1634  minForwardDissimilaritySegmentId = 0;
1635 
1636  double forwardDissimilarityValue = 0;
1637 
1638  unsigned int segmentsLine = 0;
1639  unsigned int segmentsLineBound = 0;
1640  unsigned int segmentCol = 0;
1641  unsigned int segmentColStart = 0;
1642  unsigned int segmentColBound = 0;
1643 
1644  SegmenterSegmentsBlock::SegmentIdDataType* segmentsIdsLinePtr = 0;
1645 
1646  SegmenterSegmentsBlock::SegmentIdDataType currentSegmentId = 0;
1647 
1648  // initializing the auxiliary features
1649 
1650  std::auto_ptr< SegmentFeatures > candidateAuxSegFeatures;
1651  std::auto_ptr< SegmentFeatures > minForwardDissimilarityFeatures;
1652  if( ! segsIndexer.empty() )
1653  {
1654  candidateAuxSegFeatures.reset(
1655  segsIndexer.begin()->second->getFeatures()->clone() );
1656  minForwardDissimilarityFeatures.reset(
1657  candidateAuxSegFeatures->clone() );
1658  }
1659 
1660  // Updating the merger state
1661 
1662  merger.update();
1663 
1664  // iterating over each segment
1665 
1666  SegmentsIndexer::iterator segsIt = segsIndexer.begin();
1667 
1668  while( segsIt != segsIndexer.end() )
1669  {
1670  // is this a small segment ?
1671 
1672  if( segsIt->second->getFeatures()->m_size < minSegmentSize )
1673  {
1674  // Looking for the closest neighboorhood segment
1675 
1676  nSegsIt = segsIt->second->m_neighborSegments.begin();
1677  nSegsItEnd = segsIt->second->m_neighborSegments.end();
1678 
1679  minForwardDissimilaritySegmentIt = nSegsItEnd;
1680  minForwardDissimilarityValue = DBL_MAX;
1681 
1682  while( nSegsIt != nSegsItEnd )
1683  {
1684  forwardDissimilarityValue = merger.getDissimilarityIndex( segsIt->second,
1685  *nSegsIt, candidateAuxSegFeatures.get() );
1686 
1687  if( forwardDissimilarityValue < minForwardDissimilarityValue )
1688  {
1689  minForwardDissimilarityValue = forwardDissimilarityValue;
1690  minForwardDissimilaritySegmentIt = nSegsIt;
1691  minForwardDissimilaritySegmentId =
1692  (*minForwardDissimilaritySegmentIt)->getFeatures()->m_id;
1693  minForwardDissimilarityFeatures->copy( candidateAuxSegFeatures.get() );
1694  }
1695 
1696  ++nSegsIt;
1697  }
1698 
1699  // If the minimum dissimilary neighbor was found it will be merged
1700 
1701  if( minForwardDissimilaritySegmentIt != nSegsItEnd )
1702  {
1703  // merging the small segment data into there
1704  // closes segment data
1705 
1706  merger.mergeFeatures( (*minForwardDissimilaritySegmentIt),
1707  segsIt->second, minForwardDissimilarityFeatures.get() );
1708 
1709  // updating the the small segment neighborhood segments
1710  // with the current closest segment
1711 
1712  nSegNSegsIt =
1713  segsIt->second->m_neighborSegments.begin();
1714  nSegNSegsItEnd =
1715  segsIt->second->m_neighborSegments.end();
1716 
1717  while( nSegNSegsIt != nSegNSegsItEnd )
1718  {
1719  if( (*nSegNSegsIt) != (*minForwardDissimilaritySegmentIt) )
1720  {
1721  // adding the small segment neighborhood segment to the
1722  // closest segment, if it is not already there
1723 
1724  if( std::find(
1725  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.begin(),
1726  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.end(),
1727  (*nSegNSegsIt) ) ==
1728  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.end() )
1729  {
1730  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.push_back(
1731  *nSegNSegsIt );
1732  }
1733 
1734  // adding the closest segment into the small segment
1735  // neighborhood segments list, if it is not already there
1736 
1737  if( std::find( (*nSegNSegsIt)->m_neighborSegments.begin(),
1738  (*nSegNSegsIt)->m_neighborSegments.end(),
1739  (*minForwardDissimilaritySegmentIt) ) ==
1740  (*nSegNSegsIt)->m_neighborSegments.end() )
1741  {
1742  (*nSegNSegsIt)->m_neighborSegments.push_back(
1743  *minForwardDissimilaritySegmentIt );
1744  }
1745 
1746  // removing the small segment reference from its neighbor
1747  // list
1748 
1749  (*nSegNSegsIt)->m_neighborSegments.remove( segsIt->second );
1750  }
1751 
1752  ++nSegNSegsIt;
1753  }
1754 
1755  // updating the segments Ids container
1756 
1757  segmentsLineBound = segsIt->second->getFeatures()->m_yBound;
1758  segmentColStart = segsIt->second->getFeatures()->m_xStart;
1759  segmentColBound = segsIt->second->getFeatures()->m_xBound;
1760  currentSegmentId = segsIt->second->getFeatures()->m_id;
1761 
1762  for( segmentsLine = segsIt->second->getFeatures()->m_yStart ;
1763  segmentsLine < segmentsLineBound ; ++segmentsLine )
1764  {
1765  segmentsIdsLinePtr = m_segmentsIdsMatrix[ segmentsLine ];
1766 
1767  for( segmentCol = segmentColStart ; segmentCol <
1768  segmentColBound ; ++segmentCol )
1769  {
1770  if( segmentsIdsLinePtr[ segmentCol ] ==
1771  currentSegmentId )
1772  {
1773  segmentsIdsLinePtr[ segmentCol ] =
1774  minForwardDissimilaritySegmentId;
1775  }
1776  }
1777  }
1778 
1779  // moving to the pool and removing the small segment from the list
1780  // of the closest segment neighborhood segments list
1781  // and from the global segments container
1782  // The merged segment id will be given back to ids manager
1783 
1784  (*minForwardDissimilaritySegmentIt)->m_neighborSegments.remove(
1785  segsIt->second );
1786 
1787  m_segmentsPool.store( segsIt->second );
1788 
1789  ++segsIt;
1790 
1791  segsIndexer.erase( currentSegmentId );
1792 
1793  segmenterIdsManager.addFreeID( currentSegmentId );
1794 
1795  ++mergedSegmentsNumber;
1796  }
1797  else
1798  {
1799  ++segsIt;
1800  }
1801  }
1802  else
1803  {
1804  ++segsIt;
1805  }
1806  }
1807 
1808  return mergedSegmentsNumber;
1809  }
1810 
1812  const SegmentsIdsMatrixT& segmentsIds, bool normto8bits,
1813  const std::string& fileName )
1814  {
1815  std::map<std::string, std::string> rinfo;
1816  rinfo["SOURCE"] = fileName;
1817 
1818  const unsigned int linesNmb = segmentsIds.getLinesNumber();
1819  const unsigned int colsNmb = segmentsIds.getColumnsNumber();
1820 
1821  te::rst::Grid* gridPtr = new te::rst::Grid( colsNmb, linesNmb );
1822 
1823  std::vector< te::rst::BandProperty* > bandsProps;
1824  bandsProps.push_back( new te::rst::BandProperty( 0,
1825  (normto8bits ? te::dt::UCHAR_TYPE : te::dt::UINT32_TYPE) ) );
1826 
1827  te::rst::Raster* rasterPtr = te::rst::RasterFactory::make( "GDAL",
1828  gridPtr, bandsProps, rinfo );
1829  TERP_TRUE_OR_THROW( rasterPtr, "Invalid pointer" )
1830 
1831  unsigned int col = 0;
1832  unsigned int line = 0 ;
1833 
1834  double offset = 0.0;
1835  double scale = 1.0;
1836 
1837  if( normto8bits )
1838  {
1839  double minValue = DBL_MAX;
1840  double maxValue = -1.0 * DBL_MAX;
1841  double value = 0;
1842 
1843  for( line = 0 ; line < linesNmb ; ++line )
1844  {
1845  for( col = 0 ; col < colsNmb ; ++col )
1846  {
1847  value = (double)segmentsIds( line, col );
1848 
1849  if( value > maxValue ) maxValue = value;
1850  if( value < minValue ) minValue = value;
1851  }
1852  }
1853 
1854  offset = minValue;
1855  scale = 254.0 / ( maxValue - minValue );
1856  }
1857 
1858  double value = 0;
1859 
1860  for( line = 0 ; line < linesNmb ; ++line )
1861  {
1862  for( col = 0 ; col < colsNmb ; ++col )
1863  {
1864  value = ( ((double)segmentsIds( line, col )) - offset ) * scale;
1865  TERP_TRUE_OR_THROW( value <= 255.0, "Invalid value:" +
1866  boost::lexical_cast< std::string >( value ) )
1867 
1868  rasterPtr->setValue( col, line, value , 0 );
1869  }
1870  }
1871 
1872  delete rasterPtr;
1873  }
1874 
1876  const SegmentsIdsMatrixT& segsIds,
1877  const unsigned int& xStart, const unsigned int& yStart,
1878  const unsigned int& xBound, const unsigned int& yBound,
1881  unsigned int& edgeLength1,
1882  unsigned int& edgeLength2 )
1883  {
1884  const unsigned int colsNumber = segsIds.getColumnsNumber();
1885  const unsigned int linesNumber = segsIds.getLinesNumber();
1886 
1887  TERP_DEBUG_TRUE_OR_THROW( xStart < colsNumber,
1888  "Internal Error" )
1889  TERP_DEBUG_TRUE_OR_THROW( xBound <= colsNumber,
1890  "Internal Error" )
1891  TERP_DEBUG_TRUE_OR_THROW( yStart < linesNumber,
1892  "Internal Error" )
1893  TERP_DEBUG_TRUE_OR_THROW( yBound <= linesNumber,
1894  "Internal Error" )
1895  TERP_DEBUG_TRUE_OR_THROW( xStart < xBound, "Internal Error" )
1896  TERP_DEBUG_TRUE_OR_THROW( yStart < yBound, "Internal Error" )
1897 
1898  // finding the touching pixels
1899 
1900  edgeLength1 = 0;
1901  edgeLength2 = 0;
1902 
1903  unsigned int xIdx = 0;
1904  const unsigned int lastColIdx = colsNumber - 1;
1905  const unsigned int lastLineIdx = linesNumber - 1;
1906 
1907  for( unsigned int yIdx = yStart ; yIdx < yBound ; ++yIdx )
1908  {
1909  for( xIdx = xStart; xIdx < xBound ; ++xIdx )
1910  {
1911  if( segsIds[ yIdx ][ xIdx ] == id1 )
1912  {
1913  if( yIdx )
1914  if( segsIds[ yIdx - 1 ][ xIdx ] == id2 )
1915  {
1916  ++edgeLength1;
1917  continue;
1918  }
1919  if( xIdx )
1920  if( segsIds[ yIdx ][ xIdx - 1 ] == id2 )
1921  {
1922  ++edgeLength1;
1923  continue;
1924  }
1925  if( yIdx < lastLineIdx)
1926  if( segsIds[ yIdx + 1 ][ xIdx ] == id2 )
1927  {
1928  ++edgeLength1;
1929  continue;
1930  }
1931  if( xIdx < lastColIdx )
1932  if( segsIds[ yIdx ][ xIdx + 1 ] == id2 )
1933  {
1934  ++edgeLength1;
1935  continue;
1936  }
1937  }
1938  else if( segsIds[ yIdx ][ xIdx ] == id2 )
1939  {
1940  if( yIdx )
1941  if( segsIds[ yIdx - 1 ][ xIdx ] == id1 )
1942  {
1943  ++edgeLength2;
1944  continue;
1945  }
1946  if( xIdx )
1947  if( segsIds[ yIdx ][ xIdx - 1 ] == id1 )
1948  {
1949  ++edgeLength2;
1950  continue;
1951  }
1952  if( yIdx < lastLineIdx)
1953  if( segsIds[ yIdx + 1 ][ xIdx ] == id1 )
1954  {
1955  ++edgeLength2;
1956  continue;
1957  }
1958  if( xIdx < lastColIdx )
1959  if( segsIds[ yIdx ][ xIdx + 1 ] == id1 )
1960  {
1961  ++edgeLength2;
1962  continue;
1963  }
1964  }
1965  }
1966  }
1967  }
1968 
1969  //-------------------------------------------------------------------------
1970 
1972  : te::rp::SegmenterStrategyFactory( "RegionGrowing" )
1973  {
1974  }
1975 
1977  {
1978  }
1979 
1981  {
1983  }
1984 
1985  } // end namespace rp
1986 } // end namespace te
1987 
#define TERP_DEBUG_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:356
std::vector< double > m_allSegsStdDevGain
The gains applied to normalize the standard deviation value.
virtual void mergeFeatures(SegmenterRegionGrowingStrategy::Segment *const segment1Ptr, Segment const *const segment2Ptr, SegmenterRegionGrowingStrategy::SegmentFeatures const *const mergedFeatures) const =0
Merge specific segment features from both segments into the first segment.
Raster region growing segmenter strategy.
BaatzMerger(const double &colorWeight, const double &compactnessWeight, const std::vector< double > &bandsWeights, const SegmentsIdsMatrixT &segmentsIds, const SegmenterRegionGrowingStrategy::SegmentsIndexer &segments)
Default constructor.
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 getNumberOfRows() const
Returns the raster number of rows.
Definition: Raster.cpp:208
Raster region growing segmenter strategy.
unsigned int m_xBound
Segment lower bound X coordinate box over the label image.
Segmenter segments block description class.
double getMemUsageEstimation(const unsigned int bandsToProcess, const unsigned int pixelsNumber) const
Returns a memory estimation (bytes).
te::rp::SegmenterStrategy * build()
Concrete factories (derived from this one) must implement this method in order to create objects...
static Raster * make()
It creates and returns an empty raster with default raster driver.
unsigned int getLinesNumber() const
The number of current matrix lines.
Definition: Matrix.h:665
void store(SegmenterSegment *segPtr)
Store a new segment.
double m_compactnessWeight
The weight given to the compactness component, deafult:0.5, valid range: [0,1].
SegmenterSegmentsBlock::SegmentIdDataType m_id
Segment ID.
void addFreeID(const SegmenterSegmentsBlock::SegmentIdDataType &id)
Stores a free unique ID for later use.
std::vector< double > m_squaresSum
The sum of squares of pixel values (for each band).
void copy(SegmenterRegionGrowingStrategy::SegmentFeatures const *const otherPtr)
Copy the other instance state into this one.
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
double m_colorWeight
The weight given to the color component, deafult:0.5, valid range: [0,1].
std::vector< double > m_allSegsStdDevOffsets
The offsets applied to normalize the standard deviation value.
SegmenterSegmentsPool m_segmentsPool
A pool of segments that can be reused on each strategy execution.
std::list< Segment * > m_neighborSegments
Neighborhood segments.
unsigned int m_yStart
Segment upper Y coordinate box over the label image.
#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
void copy(SegmenterRegionGrowingStrategy::SegmentFeatures const *const otherPtr)
Copy the other instance state into this one.
Abstract parameters base interface.
void mergeFeatures(SegmenterRegionGrowingStrategy::Segment *const segmen1tPtr, Segment const *const segmen2tPtr, SegmenterRegionGrowingStrategy::SegmentFeatures const *const mergedFeatures) const
Merge specific segment features from both segments into the first segment.
A rectified grid is the spatial support for raster data.
Definition: Grid.h:55
bool initialize(SegmenterStrategyParameters const *const strategyParams)
Initialize the segmentation strategy.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
virtual SegmenterRegionGrowingStrategy::SegmentFeatures * getFeatures()=0
Returns the current segment internal features.
Segmenter segments IDs manager.
unsigned int m_segmentsSimIncreaseSteps
The maximum number of steps to increment the similarity threshold value for the cases where no segmen...
void addFreeIDs(const std::vector< SegmenterSegmentsBlock::SegmentIdDataType > &ids)
Stores free unique IDs for later use.
virtual void update()=0
Update the internal state.
unsigned int mergeSegments(const double similarityThreshold, SegmenterIdsManager &segmenterIdsManager, Merger &merger, const bool enablelocalMutualBestFitting, SegmentsIndexer &segsIndexer)
Merge closest segments.
unsigned int mergeSmallSegments(const unsigned int minSegmentSize, SegmenterIdsManager &segmenterIdsManager, Merger &merger, SegmentsIndexer &segsIndexer)
Merge only small segments to their closest segment.
The Baatz based features will be used - Reference: Baatz, M.; Schape, A. Multiresolution segmentation...
bool m_isInitialized
true if this instance is initialized.
SegmenterRegionGrowingStrategy::SegmentFeatures * clone() const
Creat a clone of this object.
Raster segmenter strategy base class.
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
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, SegmentsIndexer &segments)
Initialize the segment objects container and the segment IDs container.
std::vector< double > m_stdDev
Standard deviation of segment pixel velues.
AbstractParameters * clone() const
Create a clone copy of this instance.
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...
unsigned int m_minSegmentSize
A positive minimum segment size (pixels number - default: 100).
bool getNewIDs(const unsigned int &idsNumber, std::vector< SegmenterSegmentsBlock::SegmentIdDataType > &ids)
Returns new segment unique IDs.
SegmentFeaturesType m_segmentFeatures
What segment features will be used on the segmentation process (default:InvalidFeaturesType).
const SegmenterRegionGrowingStrategy::SegmentFeatures & operator=(const SegmenterRegionGrowingStrategy::SegmentFeatures &other)
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).
SegmentsIdsMatrixT m_segmentsIdsMatrix
A internal segments IDs matrix that can be reused on each strategy execution.
A raster band description.
Definition: BandProperty.h:61
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits&lt;double&gt;::max().
Definition: BandProperty.h:136
void clear()
Clear all stored segments.
double getDissimilarityIndex(SegmenterRegionGrowingStrategy::Segment const *const segmen1tPtr, SegmenterRegionGrowingStrategy::Segment const *const segmen2tPtr, SegmenterRegionGrowingStrategy::SegmentFeatures *mergedFeatures) const
Returns a dissimilarity index between this and the other segment (normalized between 0 and 1)...
double m_segmentsSimilarityThreshold
Segments similarity treshold - Segments with similarity values below this value will be merged; valid...
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:149
double getDissimilarityIndex(SegmenterRegionGrowingStrategy::Segment const *const segmen1tPtr, SegmenterRegionGrowingStrategy::Segment const *const segmen2tPtr, SegmenterRegionGrowingStrategy::SegmentFeatures *mergedFeatures) const
Returns a dissimilarity index between this and the other segment (normalized between 0 and 1)...
unsigned int getColumnsNumber() const
The number of current matrix columns.
Definition: Matrix.h:672
SegmenterSegment * retrive()
Retrive a stored segment.
void reset()
Reset (clear) the active instance data.
Definition: Matrix.h:474
An abstract class for raster data strucutures.
Definition: Raster.h:70
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:370
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
#define TERP_LOG_AND_THROW(message)
Logs a error message and throws.
Definition: Macros.h:138
void mergeFeatures(SegmenterRegionGrowingStrategy::Segment *const segmen1tPtr, Segment const *const segmen2tPtr, SegmenterRegionGrowingStrategy::SegmentFeatures const *const mergedFeatures) const
Merge specific segment features from both segments into the first segment.
Raster segmenter strategy factory base class.
The mean of segments pixel values will be used - Reference: S. A. Bins, L. M. G. Fonseca, G. J. Erthal e F. M. Ii, &quot;Satellite Imagery segmentation: a region growing approach&quot;, VIII Simposio Brasileiro de Sensoriamento Remoto, Salvador, BA, 14-19 abril 1996.
std::vector< double > m_means
Segment mean values (for each band), normalized between 0 and 1.
SegmenterRegionGrowingStrategy::Parameters m_parameters
Internal execution parameters.
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.
void reset()
Clear all internal allocated resources and go back to the initial not-initialized state...
Raster region growing segmenter strategy factory.
virtual double getDissimilarityIndex(SegmenterRegionGrowingStrategy::Segment const *const segment1Ptr, SegmenterRegionGrowingStrategy::Segment const *const segment2Ptr, SegmenterRegionGrowingStrategy::SegmentFeatures *mergedFeatures) const =0
Returns a dissimilarity index between this and the other segment (normalized between 0 and 1)...
const Parameters & operator=(const Parameters &params)
unsigned int getOptimalBlocksOverlapSize() const
Returns a optimal blocks overlap size (number of border pixels overlapped between blocks...
unsigned int m_xStart
Segment left X coordinate box over the label image.
SegmenterRegionGrowingStrategy::SegmentFeatures * clone() const
Creat a clone of this object.
unsigned int m_yBound
Segment lower bound Y coordinate box over the label image.
void exportSegs2Tif(const SegmentsIdsMatrixT &segmentsIds, bool normto8bits, const std::string &fileName)
Export the segments IDs to a tif file.