SegmenterRegionGrowingFunctions.h
Go to the documentation of this file.
1 /* Copyright (C) 2015 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/SegmenterRegionGrowingfunctions.h
22  \brief Useful functions for Region Growing segmentation.
23  */
24 
25 #ifndef __TERRALIB_RP_INTERNAL_SEGMENTERREGIONGROWINGFUNCTIONS_H
26 #define __TERRALIB_RP_INTERNAL_SEGMENTERREGIONGROWINGFUNCTIONS_H
27 
28 #include "Matrix.h"
29 #include "SegmenterIdsManager.h"
32 #include "SegmenterSegmentsBlock.h"
33 
34 namespace te
35 {
36  namespace rp
37  {
38  namespace rg
39  {
40  /*!
41  \brief Definition for segments ids matrix type.
42  */
45 
46  /*!
47  \brief Iteration counter type.
48  */
49  typedef unsigned short int IterationCounterType;
50 
51  /*!
52  \brief Mean Strategy feature type.
53  */
54  typedef float MeanFeatureType;
55 
56  /*!
57  \brief Baatz Strategy feature type.
58  */
59  typedef float BaatzFeatureType;
60 
61  /*!
62  \brief Export the segments IDs to a tif file.
63  \param segmentsIds The output segment ids container.
64  \param normto8bits If true, a 8 bits file will be generated.
65  \param fileName The output tif file name.
66  */
67  void exportSegs2Tif( const SegmentsIdsMatrixT& segmentsIds,
68  bool normto8bits, const std::string& fileName );
69 
70  /*!
71  \brief Returns the number of active segments.
72  \param actSegsListHeadPtr A pointer the the active segments list head.
73  \return Returns the number of active segments.
74  */
75  template< typename FeatureDataTypeT >
77  {
78  unsigned int returnValue = 0;
79 
80  SegmenterRegionGrowingSegment< FeatureDataTypeT >* currSegPtr = actSegsListHeadPtr;
81 
82  while( currSegPtr ) {
83  ++returnValue;
84  currSegPtr = currSegPtr->m_nextActiveSegment;
85  }
86 
87  return returnValue;
88  }
89 
90  /*!
91  \brief Merge closest segments.
92  \param segmentsIds Segments ids container.
93  \param disimilarityThreshold The maximum similarity value allowed when deciding when to merge two segments.
94  \param maxSegSizeThreshold Segments with sizes smaller then this value will allways be merged with the closest segment (disimilarityThreshold will be ignored).
95  \param segmenterIdsManager A segments ids manager to acquire unique segments ids.
96  \param merger The merger instance to use.
97  \param enablelocalMutualBestFitting If enabled, a merge only occurs between two segments if the minimum dissimilarity criteria is best fulfilled mutually.
98  \param enableSameIterationMerges If enabled, a merged segment could be merged with another under the same iteration.
99  \param auxSeg1Ptr A pointer to a valid auxiliar segment that will be used by this method.
100  \param auxSeg2Ptr A pointer to a valid auxiliar segment that will be used by this method.
101  \param auxSeg3Ptr A pointer to a valid auxiliar segment that will be used by this method.
102  \param minFoundDissimilarity The minimum dissimilarity value found.
103  \param maxFoundDissimilarity The maximum dissimilarity value found.
104  \param totalMergesNumber The total number of merges.
105  \param mergeIterationCounter A reference to a iteration number counter (this variable will be only incremented, never zeroed. It never must be reset. ).
106  \param actSegsListHeadPtr A pointer the the active segments list head.
107  */
108  template< typename FeatureDataTypeT >
109  void mergeSegments( SegmentsIdsMatrixT& segmentsIds,
110  const DissimilarityTypeT disimilarityThreshold,
111  const unsigned int maxSegSizeThreshold,
112  SegmenterIdsManager& segmenterIdsManager,
114  const bool enablelocalMutualBestFitting,
115  const bool enableSameIterationMerges,
119  DissimilarityTypeT& minFoundDissimilarity,
120  DissimilarityTypeT& maxFoundDissimilarity,
121  unsigned int& totalMergesNumber,
122  IterationCounterType& globalMergeIterationsCounter,
123  SegmenterRegionGrowingSegment< FeatureDataTypeT >** const actSegsListHeadPtrPtr )
124  {
125  TERP_TRUE_OR_THROW( actSegsListHeadPtrPtr != 0, "Invalid active segments list header pointer" );
126  TERP_TRUE_OR_THROW( (*actSegsListHeadPtrPtr) != 0, "Invalid active segments list header pointer" );
127 
128  minFoundDissimilarity = std::numeric_limits< DissimilarityTypeT >::max();
129  maxFoundDissimilarity = DissimilarityTypeT( -1.0 * minFoundDissimilarity );
130  totalMergesNumber = 0;
131 
132  // Globals
133  DissimilarityTypeT internalDisimilarityThreshold = disimilarityThreshold;
134  unsigned int internalMaxSegSizeThreshold = maxSegSizeThreshold;
135 
136  if( maxSegSizeThreshold ) {
137  internalDisimilarityThreshold = std::numeric_limits< DissimilarityTypeT >::max();
138 
139  } else {
140  internalMaxSegSizeThreshold = std::numeric_limits< unsigned int >::max();
141 
142  }
143 
144  unsigned int iterationMergedSegmentsNumber = 0;
145  unsigned int segmentsLine = 0;
146  unsigned int segmentsLineBound = 0;
147  unsigned int segmentCol = 0;
148  unsigned int segmentColStart = 0;
149  unsigned int segmentColBound = 0;
150  SegmenterRegionGrowingSegment< FeatureDataTypeT >* minForwardDissimilaritySegmentPtr = 0;
151  DissimilarityTypeT forwardDissimilarityValue = 0;
152  DissimilarityTypeT minForwardDissimilarityValue = 0;
153  SegmenterRegionGrowingSegment< FeatureDataTypeT >* minBackwardDissimilaritySegmentPtr = 0;
154  DissimilarityTypeT backwardDissimilarityValue = 0;
155  DissimilarityTypeT minBackwardDissimilarityValue = 0;
156  SegmenterSegmentsBlock::SegmentIdDataType* segmentsIdsLinePtr = 0;
157  SegmenterSegmentsBlock::SegmentIdDataType currentSegmentId = 0;
158  std::list< SegmenterSegmentsBlock::SegmentIdDataType > freeSegmentIds;
159  unsigned int neighborSegIdx = 0;
160  SegmenterRegionGrowingSegment< FeatureDataTypeT >* currActSegPtr = (*actSegsListHeadPtrPtr);
161 
162  // Main iterations loop
163  do {
164  iterationMergedSegmentsNumber = 0;
165  currActSegPtr = (*actSegsListHeadPtrPtr);
166 
167  // Updating the merger state
168  merger.update( *actSegsListHeadPtrPtr );
169 
170  // iterating over each segment
171  do {
172  if( ( enableSameIterationMerges || ( currActSegPtr->m_mergetIteration < globalMergeIterationsCounter ) )
173  &&
174  ( currActSegPtr->m_size <= internalMaxSegSizeThreshold ) ) {
175 
176  // finding the neighbor segment with minimum dissimilary value
177  // related to the current sement
178 
179  minForwardDissimilaritySegmentPtr = 0;
180  minForwardDissimilarityValue = std::numeric_limits< DissimilarityTypeT >::max();
181 
182  for( neighborSegIdx = 0 ; neighborSegIdx < currActSegPtr->m_neighborSegmentsSize ;
183  ++neighborSegIdx ) {
184 
185  if( currActSegPtr->m_neighborSegments[ neighborSegIdx ] ) {
186  forwardDissimilarityValue = merger.getDissimilarity( currActSegPtr,
187  currActSegPtr->m_neighborSegments[ neighborSegIdx ],
188  auxSeg1Ptr );
189 
190  if( ( forwardDissimilarityValue <= internalDisimilarityThreshold )
191  &&
192  ( forwardDissimilarityValue < minForwardDissimilarityValue ) ) {
193  minForwardDissimilarityValue = forwardDissimilarityValue;
194  minForwardDissimilaritySegmentPtr = currActSegPtr->m_neighborSegments[ neighborSegIdx ];
195  auxSeg3Ptr->operator=( *auxSeg1Ptr );
196  }
197  }
198  }
199 
200  // does the neighbor wants to merge back ?
201 
202  if( enablelocalMutualBestFitting && ( minForwardDissimilaritySegmentPtr != 0 ) ) {
203  // Calculating all neighbor neighbor segments dissimilarity
204 
205  minBackwardDissimilaritySegmentPtr = 0;
206  backwardDissimilarityValue = 0;
207  minBackwardDissimilarityValue = std::numeric_limits< DissimilarityTypeT >::max();
208 
209  for( neighborSegIdx = 0 ;
210  neighborSegIdx < minForwardDissimilaritySegmentPtr->m_neighborSegmentsSize ;
211  ++neighborSegIdx ) {
212 
213  if( minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] ) {
214 
215  backwardDissimilarityValue =
216  merger.getDissimilarity( minForwardDissimilaritySegmentPtr,
217  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ],
218  auxSeg2Ptr );
219 
220  if( backwardDissimilarityValue < minBackwardDissimilarityValue ) {
221  minBackwardDissimilarityValue = backwardDissimilarityValue;
222  minBackwardDissimilaritySegmentPtr =
223  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ];
224  }
225  }
226  }
227 
228  if( minBackwardDissimilaritySegmentPtr != currActSegPtr ) {
229  minForwardDissimilaritySegmentPtr = 0;
230  }
231  }
232 
233  // if the min forward dissimilarity segment was found
234  if( ( minForwardDissimilaritySegmentPtr != 0 )
235  &&
236  ( enableSameIterationMerges ||
237  ( minForwardDissimilaritySegmentPtr->m_mergetIteration < globalMergeIterationsCounter )
238  ) ) {
239 
240  if( minFoundDissimilarity > minForwardDissimilarityValue ) {
241  minFoundDissimilarity = minForwardDissimilarityValue;
242  }
243 
244  if( maxFoundDissimilarity < minForwardDissimilarityValue ) {
245  maxFoundDissimilarity = minForwardDissimilarityValue;
246  }
247 
248  // If the maximum similary neighbor was found it will be merged
249  // if the dissimilarity value is below the threshold
250  // merging segment data
251 
252  merger.mergeFeatures( currActSegPtr,
253  minForwardDissimilaritySegmentPtr,
254  auxSeg3Ptr );
255 
256  currActSegPtr->m_mergetIteration = globalMergeIterationsCounter;
257 
258  currActSegPtr->removeNeighborSegmentPtr( minForwardDissimilaritySegmentPtr );
259 
260  // updating the max similarity segment neighborhood segments
261  // with the current segment
262 
263  for( neighborSegIdx = 0 ;
264  neighborSegIdx < minForwardDissimilaritySegmentPtr->m_neighborSegmentsSize;
265  ++neighborSegIdx ) {
266 
267  if(
268  ( minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] != 0 )
269  &&
270  ( minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] != currActSegPtr ) ) {
271  // adding the max similarity neighborhood segments to the
272  // current one, if it is not already there
273 
274  currActSegPtr->addNeighborSegmentPtr(
275 
276  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ] );
277 
278  // adding the current segment into the max similarity
279  // neighborhood segments list, if it is not already there
280 
281  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ]->addNeighborSegmentPtr(
282  currActSegPtr );
283 
284  // removing the merged segment reference from its neighbor
285  // list
286  minForwardDissimilaritySegmentPtr->m_neighborSegments[ neighborSegIdx ]->removeNeighborSegmentPtr(
287  minForwardDissimilaritySegmentPtr );
288  }
289  }
290 
291  // updating the segments Ids container matrix
292 
293  segmentsLineBound = minForwardDissimilaritySegmentPtr->m_yBound;
294  segmentColStart = minForwardDissimilaritySegmentPtr->m_xStart;
295  segmentColBound = minForwardDissimilaritySegmentPtr->m_xBound;
296  currentSegmentId = currActSegPtr->m_id;
297 
298  for( segmentsLine = minForwardDissimilaritySegmentPtr->m_yStart ;
299  segmentsLine < segmentsLineBound ; ++segmentsLine ) {
300  segmentsIdsLinePtr = segmentsIds[ segmentsLine ];
301 
302  for( segmentCol = segmentColStart ; segmentCol < segmentColBound ; ++segmentCol ) {
303  if( segmentsIdsLinePtr[ segmentCol ] ==
304  minForwardDissimilaritySegmentPtr->m_id ) {
305  segmentsIdsLinePtr[ segmentCol ] = currentSegmentId;
306  }
307  }
308  }
309 
310  // disabling the merged segment
311  // The merged segment id will be given back to ids manager
312 
313  if( minForwardDissimilaritySegmentPtr == (*actSegsListHeadPtrPtr) ) {
314  (*actSegsListHeadPtrPtr) = (*actSegsListHeadPtrPtr)->m_nextActiveSegment;
315  }
316 
317  if( minForwardDissimilaritySegmentPtr->m_prevActiveSegment ) {
318  minForwardDissimilaritySegmentPtr->m_prevActiveSegment->m_nextActiveSegment =
319  minForwardDissimilaritySegmentPtr->m_nextActiveSegment;
320  }
321 
322  if( minForwardDissimilaritySegmentPtr->m_nextActiveSegment ) {
323  minForwardDissimilaritySegmentPtr->m_nextActiveSegment->m_prevActiveSegment =
324  minForwardDissimilaritySegmentPtr->m_prevActiveSegment;
325  }
326 
327  minForwardDissimilaritySegmentPtr->disable();
328 
329  minForwardDissimilaritySegmentPtr->removeAllNeighborSegmentsPtrs();
330 
331  freeSegmentIds.push_back( minForwardDissimilaritySegmentPtr->m_id );
332 
333  ++iterationMergedSegmentsNumber;
334  }
335  }
336 
337  // going to the next segment
338  currActSegPtr = currActSegPtr->m_nextActiveSegment;
339 
340  } while( currActSegPtr );
341 
342  // give back the free unused sement ids
343 
344  if( ! freeSegmentIds.empty() ) {
345  segmenterIdsManager.addFreeIDs( freeSegmentIds );
346  freeSegmentIds.clear();
347  }
348 
349  totalMergesNumber += iterationMergedSegmentsNumber;
350 
351  // std::cout << std::endl << "Iteration Number: " << iterationNumber <<
352  // " Merged segments number:" << iterationMergedSegmentsNumber << std::endl;
353 
354  ++globalMergeIterationsCounter;
355 
356  } while( iterationMergedSegmentsNumber &&
357  ( globalMergeIterationsCounter <
358  std::numeric_limits< IterationCounterType >::max() ) );
359  }
360  } // end namespace rg
361  } // end namespace rp
362 } // end namespace te
363 
364 #endif // __TERRALIB_RP_INTERNAL_SEGMENTERREGIONGROWINGFUNCTIONS_H
unsigned int getActiveSegmentsNumber(SegmenterRegionGrowingSegment< FeatureDataTypeT > *const actSegsListHeadPtr)
Returns the number of active segments.
Segmenter segments IDs manager.
unsigned int m_xStart
Segment left X coordinate box over the label image.
double DissimilarityTypeT
Type for dissimilarity.
unsigned short int IterationCounterType
Iteration counter type.
void disable()
Disable this segment ( same as m_mergetIteration = std::numeric_limits< SegmenterRegionGrowingSegment...
void mergeSegments(SegmentsIdsMatrixT &segmentsIds, const DissimilarityTypeT disimilarityThreshold, const unsigned int maxSegSizeThreshold, SegmenterIdsManager &segmenterIdsManager, SegmenterRegionGrowingMerger< FeatureDataTypeT > &merger, const bool enablelocalMutualBestFitting, const bool enableSameIterationMerges, SegmenterRegionGrowingSegment< FeatureDataTypeT > *auxSeg1Ptr, SegmenterRegionGrowingSegment< FeatureDataTypeT > *auxSeg2Ptr, SegmenterRegionGrowingSegment< FeatureDataTypeT > *auxSeg3Ptr, DissimilarityTypeT &minFoundDissimilarity, DissimilarityTypeT &maxFoundDissimilarity, unsigned int &totalMergesNumber, IterationCounterType &globalMergeIterationsCounter, SegmenterRegionGrowingSegment< FeatureDataTypeT > **const actSegsListHeadPtrPtr)
Merge closest segments.
float BaatzFeatureType
Baatz Strategy feature type.
unsigned int m_neighborSegmentsSize
The current size of m_neighborSegments.
Segmenter merger used in region growing process.
virtual DissimilarityTypeT getDissimilarity(SegmenterRegionGrowingSegment< FeatureDataTypeT > const *const segment1Ptr, SegmenterRegionGrowingSegment< FeatureDataTypeT > const *const segment2Ptr, SegmenterRegionGrowingSegment< FeatureDataTypeT > *const mergePreviewSegPtr) const =0
Returns a dimilarity index between this and the other segment.
Segments IDs manager.
SegmenterRegionGrowingSegment< FeatureDataTypeT > * m_prevActiveSegment
A pointer to the previous active segment.
IterationCounterType m_mergetIteration
The current merge iteration.
Region Growing segment.
SegmenterRegionGrowingSegment< FeatureDataTypeT > * m_nextActiveSegment
A pointer to the next active segment.
void removeAllNeighborSegmentsPtrs()
Remove all neighbor segments.
URI C++ Library.
Abstract class for the segments merger.
void addNeighborSegmentPtr(SegmenterRegionGrowingSegment< FeatureDataTypeT > *const nSegPtr)
Add a pointer of a neighbor segment (if it is not already there).
SegmenterSegmentsBlock::SegmentIdDataType m_id
Segment ID.
unsigned int m_yStart
Segment upper Y coordinate box over the label image.
Generic template matrix.
Matrix< SegmenterSegmentsBlock::SegmentIdDataType > SegmentsIdsMatrixT
Definition for segments ids matrix type.
SegmenterRegionGrowingSegment< FeatureDataTypeT > ** m_neighborSegments
Neighborhood segments pointers (some pointers can be null) or a null pointer if there is no neighborh...
Segments block.
unsigned int m_xBound
Segment lower bound X coordinate box over the label image.
void removeNeighborSegmentPtr(SegmenterRegionGrowingSegment< FeatureDataTypeT > *const nSegPtr)
Remove all occurrences of a neighbor segment.
float MeanFeatureType
Mean Strategy feature type.
virtual void update(SegmenterRegionGrowingSegment< FeatureDataTypeT > *const actSegsListHeadPtr)=0
Update the internal state.
unsigned int m_yBound
Segment lower bound Y coordinate box over the label image.
unsigned int m_size
Segment area (pixels number).
void addFreeIDs(const std::vector< SegmenterSegmentsBlock::SegmentIdDataType > &ids)
Stores free unique IDs for later use.
virtual void mergeFeatures(SegmenterRegionGrowingSegment< FeatureDataTypeT > *const segment1Ptr, SegmenterRegionGrowingSegment< FeatureDataTypeT > const *const segment2Ptr, SegmenterRegionGrowingSegment< FeatureDataTypeT > 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.
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:149