All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Segmenter.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/rp/Segmenter.cpp
22  \brief Raster segmentation.
23 */
24 
25 #include "Segmenter.h"
26 
28 #include "Functions.h"
29 #include "Macros.h"
30 
31 #include "../raster/RasterFactory.h"
32 #include "../raster/Band.h"
33 #include "../raster/BandProperty.h"
34 #include "../raster/Raster.h"
35 #include "../raster/Enums.h"
36 #include "../raster/Grid.h"
37 #include "../raster/Utils.h"
38 #include "../raster/SynchronizedRaster.h"
39 #include "../memory/CachedRaster.h"
40 #include "../dataaccess/datasource/DataSource.h"
41 #include "../common/PlatformUtils.h"
42 #include "../common/StringUtils.h"
43 #include "../geometry/Coord2D.h"
44 #include "../datatype/Enums.h"
45 
46 #include <map>
47 #include <memory>
48 #include <climits>
49 #include <cmath>
50 #include <cfloat>
51 
52 #include <boost/thread.hpp>
53 #include <boost/lexical_cast.hpp>
54 
55 namespace te
56 {
57  namespace rp
58  {
60  {
62  reset();
63  }
64 
66  {
67  m_segStratParamsPtr = 0;
68  reset();
69  operator=( other );
70  }
71 
73  {
74  reset();
75  }
76 
77  void Segmenter::InputParameters::reset() throw( te::rp::Exception )
78  {
79  m_inputRasterPtr = 0;
80  m_inputRasterBands.clear();
81  m_inputRasterNoDataValues.clear();
82  m_enableThreadedProcessing = true;
83  m_maxSegThreads = 0;
84  m_enableBlockProcessing = true;
85  m_maxBlockSize = 0;
86  m_blocksOverlapPercent = 10;
87  m_strategyName.clear();
88  m_enableProgress = false;
89  m_enableRasterCache = true;
90 
91  if( m_segStratParamsPtr )
92  {
93  delete m_segStratParamsPtr;
94  m_segStratParamsPtr = 0;
95  }
96  }
97 
99  const Segmenter::InputParameters& params )
100  {
101  reset();
102 
103  m_inputRasterPtr = params.m_inputRasterPtr;
104  m_inputRasterBands = params.m_inputRasterBands;
105  m_inputRasterNoDataValues = params.m_inputRasterNoDataValues;
106  m_enableThreadedProcessing = params.m_enableThreadedProcessing;
107  m_maxSegThreads = params.m_maxSegThreads;
108  m_enableBlockProcessing = params.m_enableBlockProcessing;
109  m_maxBlockSize = params.m_maxBlockSize;
110  m_blocksOverlapPercent = params.m_blocksOverlapPercent;
111  m_strategyName = params.m_strategyName;
112  m_enableProgress = params.m_enableProgress;
113  m_enableRasterCache = params.m_enableRasterCache;
114 
115  m_segStratParamsPtr = params.m_segStratParamsPtr ?
117  : 0;
118 
119  return *this;
120  }
121 
123  {
124  return new InputParameters( *this );
125  }
126 
128  const SegmenterStrategyParameters& params )
129  {
130  if( m_segStratParamsPtr )
131  {
132  delete m_segStratParamsPtr;
133  m_segStratParamsPtr = 0;
134  }
135 
136  m_segStratParamsPtr = (SegmenterStrategyParameters*)params.clone();
137  }
138 
141  {
142  return m_segStratParamsPtr;
143  }
144 
146  {
147  reset();
148  }
149 
151  {
152  reset();
153  operator=( other );
154  }
155 
157  {
158  reset();
159  }
160 
161  void Segmenter::OutputParameters::reset() throw( te::rp::Exception )
162  {
163  m_rType.clear();
164  m_rInfo.clear();
165  m_outputRasterPtr.reset();
166  }
167 
169  const Segmenter::OutputParameters& params )
170  {
171  reset();
172 
173  m_rType = params.m_rType;
174  m_rInfo = params.m_rInfo;
175 
176  return *this;
177  }
178 
180  {
181  return new OutputParameters( *this );
182  }
183 
185  {
187  m_outputParametersPtr = 0;
188  m_segsBlocksMatrixPtr = 0;
189  m_generalMutexPtr = 0;
190  m_inputRasterSyncPtr = 0;
191  m_outputRasterSyncPtr = 0;
192  m_blockProcessedSignalMutexPtr = 0;
193  m_abortSegmentationFlagPtr = 0;
194  m_segmentsIdsManagerPtr = 0;
195  m_blockProcessedSignalPtr = 0;
196  m_runningThreadsCounterPtr = 0;
197  m_inputRasterBandMinValues.clear();
198  m_inputRasterBandMaxValues.clear();
199  m_inputRasterNoDataValues.clear();
200  m_enableStrategyProgress = false;
201  m_maxInputRasterCachedBlocks = 0;
202  }
203 
205  {
206  }
207 
209  {
210  m_instanceInitialized = false;
211  }
212 
214  {
215  }
216 
218  throw( te::rp::Exception )
219  {
221  {
222  // creating the output raster
223 
224  Segmenter::OutputParameters* outputParamsPtr = dynamic_cast<
225  Segmenter::OutputParameters* >( &outputParams );
226  TERP_TRUE_OR_RETURN_FALSE( outputParamsPtr, "Invalid parameters" );
227 
228  {
229  std::vector< te::rst::BandProperty* > bandsProperties;
230  bandsProperties.push_back( new te::rst::BandProperty(
233  bandsProperties[ 0 ]->m_colorInterp = te::rst::GrayIdxCInt;
234  bandsProperties[ 0 ]->m_noDataValue = 0;
235  bandsProperties[ 0 ]->m_type = te::dt::UINT32_TYPE;
236 
237  outputParamsPtr->m_outputRasterPtr.reset(
239  outputParamsPtr->m_rType,
241  bandsProperties,
242  outputParamsPtr->m_rInfo,
243  0,
244  0 ) );
245  TERP_TRUE_OR_RETURN_FALSE( outputParamsPtr->m_outputRasterPtr.get(),
246  "Output raster creation error" );
247 
248  // Fill with zeroes
249 
250  te::rst::Raster& outRaster = (*outputParamsPtr->m_outputRasterPtr);
251  te::rst::Band& outBand = (*outRaster.getBand( 0 ));
252  const unsigned int nRows =outRaster.getNumberOfRows();
253  const unsigned int nCols = outRaster.getNumberOfColumns();
254  unsigned int row = 0;
255  unsigned int col = 0;
256 
257  for( row = 0 ; row < nRows ; ++row )
258  {
259  for( col = 0 ; col < nCols ; ++col )
260  {
261  outBand.setValue( col, row, 0.0 );
262  }
263  }
264  }
265 
266  // instantiating the segmentation strategy
267 
268  std::auto_ptr< SegmenterStrategy > strategyPtr(
270  TERP_TRUE_OR_RETURN_FALSE( strategyPtr.get(),
271  "Unable to create an segmentation strategy" );
272  TERP_TRUE_OR_RETURN_FALSE( strategyPtr->initialize(
274  "Unable to initialize the segmentation strategy" );
275 
276  const double stratMemUsageEstimation = strategyPtr->getMemUsageEstimation(
280  TERP_DEBUG_TRUE_OR_THROW( stratMemUsageEstimation > 0.0,
281  "Invalid strategy memory usage factorMemUsageFactor" );
282 
283  // Guessing memory limits
284 
285  const unsigned int totalRasterPixels =
288 // const double originalRasterDataMemUsageEstimation = (double)(
289 // totalRasterPixels *
290 // ((unsigned int)m_inputParameters.m_inputRasterBands.size()) *
291 // ( (unsigned int)te::rst::GetPixelSize( m_inputParameters.m_inputRasterPtr->getBandDataType( 0 ) ) ) );
292  const double totalPhysMem = (double)te::common::GetTotalPhysicalMemory();
293  const double usedVMem = (double)te::common::GetUsedVirtualMemory();
294  const double totalVMem = ( (double)te::common::GetTotalVirtualMemory() );
295  const double freeVMem = MIN( totalPhysMem, ( totalVMem - usedVMem ) );
296  const double pixelRequiredRam = stratMemUsageEstimation / ((double)totalRasterPixels);
297  const double maxSimultaneousMemoryPixels = std::min( ((double)totalRasterPixels),
298  0.75 * freeVMem / pixelRequiredRam );
299 
300  // Cache issues
301 
302  std::auto_ptr< te::rst::Raster > cachedRasterHandler;
303  te::rst::Raster const * cachedRasterPtr = m_inputParameters.m_inputRasterPtr;
304 
306  {
307  cachedRasterHandler.reset( new te::mem::CachedRaster(
309  cachedRasterPtr = cachedRasterHandler.get();
310  }
311 
312  // Finding the input raster normalization parameters
313 
314  std::vector< double > inputRasterBandMinValues(
316  std::vector< double > inputRasterBandMaxValues(
318 
319  {
320  const unsigned int nRows =
321  cachedRasterPtr->getNumberOfRows();
322  const unsigned int nCols =
323  cachedRasterPtr->getNumberOfColumns();
324  unsigned int row = 0;
325  unsigned int col = 0;
326  double bandMin = DBL_MAX;
327  double bandMax = -1.0 * DBL_MAX;
328  double value = 0;
329 
330  std::vector< double > noDataValues;
332  {
333  for( unsigned int inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
334  m_inputParameters.m_inputRasterBands.size() ; ++inputRasterBandsIdx )
335  {
336  noDataValues.push_back(
339  inputRasterBandsIdx ] )->getProperty()->m_noDataValue );
340  }
341  }
342  else
343  {
345  }
346 
347  for( unsigned int inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
348  m_inputParameters.m_inputRasterBands.size() ; ++inputRasterBandsIdx )
349  {
350  const te::rst::Band& band =
351  *(cachedRasterPtr->getBand(
352  m_inputParameters.m_inputRasterBands[ inputRasterBandsIdx ] ) );
353  bandMin = DBL_MAX;
354  bandMax = -1.0 * DBL_MAX;
355 
356  for( row = 0 ; row < nRows ; ++row )
357  {
358  for( col = 0 ; col < nCols ; ++col )
359  {
360  band.getValue( col, row, value );
361 
362  if( value != noDataValues[ inputRasterBandsIdx ] )
363  {
364  if( bandMin > value ) bandMin = value;
365  if( bandMax < value ) bandMax = value;
366  }
367  }
368  }
369 
370  inputRasterBandMinValues[ inputRasterBandsIdx ] = bandMin;
371  inputRasterBandMaxValues[ inputRasterBandsIdx ] = bandMax;
372  }
373  }
374 
375  // defining the number of processing threads
376 
377  unsigned int maxSegThreads = 0;
378 
381  {
383  {
384  maxSegThreads = m_inputParameters.m_maxSegThreads;
385  }
386  else
387  {
388  maxSegThreads = te::common::GetPhysProcNumber();
389  if( maxSegThreads == 1 )
390  {
391  maxSegThreads = 0;
392  }
393  }
394  }
395 
396  // Calc the maximum block width & height
397 
398  unsigned int maxNonExpandedBlockWidth = 0;
399  unsigned int maxNonExpandedBlockHeight = 0;
400  unsigned int maxExpandedBlockWidth = 0;
401  unsigned int maxExpandedBlockHeight = 0;
402  unsigned int blocksHOverlapSize = 0;
403  unsigned int blocksVOverlapSize = 0;
404 
406  &&
407  (
408  ( maxSegThreads > 0 )
409  ||
410  ( maxSimultaneousMemoryPixels < ((double)totalRasterPixels ) )
411  ||
412  (
414  &&
415  (
417  <
418  totalRasterPixels
419  )
420  )
421  )
422  )
423  {
424  // Calculating max bock pixels using the avaliable resources or
425  // the user given parameters
426 
427  unsigned int maxBlockPixels = 0;
428 
430  {
431  maxBlockPixels = m_inputParameters.m_maxBlockSize *
433  }
434  else
435  {
436  maxBlockPixels = static_cast<unsigned int>(
437  ( maxSimultaneousMemoryPixels /
438  ( static_cast<double>( maxSegThreads ? maxSegThreads : 1 ) ) ) );
439  }
440 
441  // updating maxBlockPixels considering the blocks overlap size
442 
444  200,
445  maxBlockPixels,
446  blocksHOverlapSize,
447  blocksVOverlapSize,
448  maxNonExpandedBlockWidth,
449  maxNonExpandedBlockHeight,
450  maxExpandedBlockWidth,
451  maxExpandedBlockHeight ),
452  "Error calculating best block size" );
453  }
454  else
455  {
456  maxNonExpandedBlockWidth = maxExpandedBlockWidth =
457  cachedRasterPtr->getNumberOfColumns();
458  maxNonExpandedBlockHeight = maxExpandedBlockHeight =
459  cachedRasterPtr->getNumberOfRows();
460  }
461 
462  // Defining number of blocks
463 
464  const unsigned int hBlocksNumber = (unsigned int)ceil(
465  ((double)cachedRasterPtr->getNumberOfColumns()) /
466  ((double)maxNonExpandedBlockWidth) );
467  const unsigned int vBlocksNumber = (unsigned int)ceil(
468  ((double)cachedRasterPtr->getNumberOfRows()) /
469  ((double)maxNonExpandedBlockHeight ) );
470 
471  // Generating cut off profiles. When possible, an empty profile
472  // vector is generated
473 
474  std::vector< std::vector< unsigned int> > imageHorizontalProfiles;
475  std::vector< std::vector< unsigned int> > imageVerticalProfiles;
476 
479  {
480 // std::cout << std::endl << "Starting CutOff profiles generation" << std::endl;
481 
482  const unsigned int verticalProfilesNeighborhoodSize = blocksHOverlapSize / 2;
483  const unsigned int horizontalProfilesNeighborhoodSize = blocksVOverlapSize / 2;
484  const unsigned int pixelNeighborhoodSize = 5;
485  const unsigned int profileAntiSmoothingFactor = 3;
486  std::vector< unsigned int > imageHorizontalProfilesCenterLines;
487  std::vector< unsigned int > imageVerticalProfilesCenterLines;
488  std::vector< unsigned int> profile;
489  unsigned int profileIdx = 0;
490 
491  for( profileIdx = 1 ; profileIdx < hBlocksNumber ;
492  ++profileIdx )
493  {
494  profile.clear();
495 
496  const unsigned int centerLine = std::min(
497  ( profileIdx * maxNonExpandedBlockHeight ) - 1,
498  cachedRasterPtr->getNumberOfRows() - 1 );
499 
501  *(cachedRasterPtr), m_inputParameters.m_inputRasterBands,
502  pixelNeighborhoodSize, horizontalProfilesNeighborhoodSize,
503  profileAntiSmoothingFactor, profile ),
504  "Horizontal profile generation error" );
505 
506  imageHorizontalProfiles.push_back( profile );
507  imageHorizontalProfilesCenterLines.push_back( centerLine );
508  }
509 
510  for( profileIdx = 1 ; profileIdx < vBlocksNumber ;
511  ++profileIdx )
512  {
513  profile.clear();
514 
515  const unsigned int centerLine = std::min(
516  ( profileIdx * maxNonExpandedBlockWidth ) - 1,
517  cachedRasterPtr->getNumberOfColumns() - 1 );
518 
520  *(cachedRasterPtr), m_inputParameters.m_inputRasterBands,
521  pixelNeighborhoodSize, verticalProfilesNeighborhoodSize,
522  profileAntiSmoothingFactor, profile ),
523  "Horizontal profile generation error" );
524 
525  imageVerticalProfiles.push_back( profile );
526  imageVerticalProfilesCenterLines.push_back( centerLine );
527  }
528 
529 /* TERP_TRUE_OR_THROW( createCutOffLinesTiff( imageHorizontalProfiles,
530  imageHorizontalProfilesCenterLines,
531  imageVerticalProfiles, imageVerticalProfilesCenterLines,
532  "cutoflines.tif" ), "internal error" ) */
533 
534 
535 // std::cout << std::endl << "CutOff profiles generated" << std::endl;
536  }
537 
538  // Initializing the segments blocks matrix
539 
540  SegmentsBlocksMatrixT segmentsblocksMatrix;
541  segmentsblocksMatrix.reset( SegmentsBlocksMatrixT::RAMMemPol );
542 
543  {
544  TERP_TRUE_OR_RETURN_FALSE( segmentsblocksMatrix.reset( vBlocksNumber,
545  hBlocksNumber ), "Blocks matrix reset error" );
546 
547  const int linesBound = (int)
548  cachedRasterPtr->getNumberOfRows();
549  const int colsBound = (int)
550  cachedRasterPtr->getNumberOfColumns();
551  int expandedBlockXBound = 0;
552  int expandedBlockYBound = 0;
553  int blockXStart = 0;
554  int blockYStart = 0;
555  int expandedBlockXStart = 0;
556  int expandedBlockYStart = 0;
557 
558  for( unsigned int segmentsMatrixLine = 0 ; segmentsMatrixLine <
559  segmentsblocksMatrix.getLinesNumber() ; ++segmentsMatrixLine )
560  {
561  for( unsigned int segmentsMatrixCol = 0 ; segmentsMatrixCol <
562  segmentsblocksMatrix.getColumnsNumber() ; ++segmentsMatrixCol )
563  {
564  blockXStart = (int)( segmentsMatrixCol * maxNonExpandedBlockWidth );
565  blockYStart = (int)( segmentsMatrixLine * maxNonExpandedBlockHeight );
566 
567  expandedBlockXStart = std::max( 0, blockXStart - ((int)blocksHOverlapSize) );
568  expandedBlockYStart = std::max( 0, blockYStart - ((int)blocksVOverlapSize) );
569 
570  expandedBlockXBound = std::min( blockXStart + ((int)maxNonExpandedBlockWidth)
571  + ((int)blocksHOverlapSize), colsBound );
572  expandedBlockYBound = std::min( blockYStart + ((int)maxNonExpandedBlockHeight)
573  + ((int)blocksVOverlapSize), linesBound );
574 
575  SegmenterSegmentsBlock& segmentsBlock = segmentsblocksMatrix(
576  segmentsMatrixLine, segmentsMatrixCol );
577  segmentsBlock.m_status =
579  segmentsBlock.m_startX = (unsigned int)expandedBlockXStart;
580  segmentsBlock.m_startY = (unsigned int)expandedBlockYStart;
581  segmentsBlock.m_width = (unsigned int)( expandedBlockXBound -
582  expandedBlockXStart );
583  segmentsBlock.m_height = (unsigned int)( expandedBlockYBound -
584  expandedBlockYStart );
585  segmentsBlock.m_segmentsMatrixXIndex = segmentsMatrixCol;
586  segmentsBlock.m_segmentsMatrixYIndex = segmentsMatrixLine;
587 
588  // transfering cutoff profiles
589 
592  {
594  imageHorizontalProfiles, imageVerticalProfiles,
595  segmentsBlock ), "Block cutOff profiles update error" );
596  }
597  else
598  {
599  segmentsBlock.m_topCutOffProfile.resize( segmentsBlock.m_width,
600  0 );
601  segmentsBlock.m_bottomCutOffProfile.resize( segmentsBlock.m_width,
602  segmentsBlock.m_height - 1 );
603  segmentsBlock.m_leftCutOffProfile.resize( segmentsBlock.m_height,
604  0 );
605  segmentsBlock.m_rightCutOffProfile.resize( segmentsBlock.m_height,
606  segmentsBlock.m_width - 1 );
607  }
608  }
609  }
610  }
611 
612  // Disabling de raster cache
613  // since it will be not used during segmentation
614 
615  cachedRasterHandler.reset();
616  cachedRasterPtr = 0;
617 
618  // The progress interface
619 
620  const bool enableStrategyProgress = m_inputParameters.m_enableProgress &&
621  ( ( vBlocksNumber * hBlocksNumber ) == 1 ) && ( maxSegThreads == 0 );
622 
623  std::auto_ptr< te::common::TaskProgress > progressPtr;
624  if( m_inputParameters.m_enableProgress && ( ! enableStrategyProgress ) )
625  {
626  progressPtr.reset( new te::common::TaskProgress );
627  progressPtr->setTotalSteps( 1 + ( vBlocksNumber * hBlocksNumber ) );
628  progressPtr->setMessage( "Segmentation" );
629  progressPtr->pulse();
630  }
631 
632  // Starting the segmentation
633 
634  boost::mutex generalMutex;
635  boost::mutex blockProcessedSignalMutex;
636 
637  te::rst::RasterSynchronizer inputRasterSync(
640  te::rst::RasterSynchronizer outputRasterSync( *(outputParamsPtr->m_outputRasterPtr),
642 
643  volatile bool abortSegmentationFlag = false;
644 
645  SegmenterIdsManager segmenterIdsManager;
646 
647  boost::condition_variable blockProcessedSignal;
648 
649  volatile unsigned int runningThreadsCounter = 0;
650 
651  SegmenterThreadEntryParams baseSegThreadParams;
652  baseSegThreadParams.m_inputParameters = m_inputParameters;
653  baseSegThreadParams.m_outputParametersPtr = outputParamsPtr;
654  baseSegThreadParams.m_segsBlocksMatrixPtr = &segmentsblocksMatrix;
655  baseSegThreadParams.m_generalMutexPtr = &generalMutex;
656  baseSegThreadParams.m_inputRasterSyncPtr =
657  &inputRasterSync;
658  baseSegThreadParams.m_outputRasterSyncPtr =
659  &outputRasterSync;
660  baseSegThreadParams.m_blockProcessedSignalMutexPtr =
661  &blockProcessedSignalMutex;
662  baseSegThreadParams.m_abortSegmentationFlagPtr = &abortSegmentationFlag;
663  baseSegThreadParams.m_segmentsIdsManagerPtr = &segmenterIdsManager;
664  baseSegThreadParams.m_blockProcessedSignalPtr = &blockProcessedSignal;
665  baseSegThreadParams.m_runningThreadsCounterPtr =
666  &runningThreadsCounter;
667  baseSegThreadParams.m_inputRasterBandMinValues = inputRasterBandMinValues;
668  baseSegThreadParams.m_inputRasterBandMaxValues = inputRasterBandMaxValues;
669  baseSegThreadParams.m_enableStrategyProgress = enableStrategyProgress;
670 
672  {
673  for( unsigned int inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
674  m_inputParameters.m_inputRasterBands.size() ; ++inputRasterBandsIdx )
675  {
676  baseSegThreadParams.m_inputRasterNoDataValues.push_back(
679  inputRasterBandsIdx ] )->getProperty()->m_noDataValue );
680  }
681  }
682  else
683  {
685  }
686 
688  {
689  int bandBlockSizeBytes =
692  double maxSimultaneousCacheBlocks = ( 0.05 * freeVMem ) / ((double)bandBlockSizeBytes);
693 
694  if( maxSegThreads )
695  {
696  baseSegThreadParams.m_maxInputRasterCachedBlocks = std::max(
697  1u, (unsigned int)( maxSimultaneousCacheBlocks / ((double)maxSegThreads) ) );
698  }
699  else
700  {
701  baseSegThreadParams.m_maxInputRasterCachedBlocks = (unsigned int)
702  maxSimultaneousCacheBlocks;
703  }
704  }
705  else
706  {
707  baseSegThreadParams.m_maxInputRasterCachedBlocks = 1;
708  }
709 
710  if( maxSegThreads && ( ( vBlocksNumber * hBlocksNumber ) > 1 ) )
711  { // threaded segmentation mode
712 
713  // spawning the segmentation threads
714 
715  runningThreadsCounter = maxSegThreads;
716 
717  boost::thread_group threads;
718  std::vector< SegmenterThreadEntryParams > threadsParams( maxSegThreads );
719 
720  for( unsigned int threadIdx = 0 ; threadIdx < maxSegThreads ;
721  ++threadIdx )
722  {
723  threadsParams[ threadIdx ] = baseSegThreadParams;
724 
725  threads.add_thread( new boost::thread( segmenterThreadEntry,
726  &( threadsParams[ threadIdx ] ) ) );
727  };
728 
729  // waiting all threads to finish
730 
731  int prevSegmentedBlocksNmb = 0;
732 
733  while( (!abortSegmentationFlag) && (runningThreadsCounter > 0 ) )
734  {
735  boost::unique_lock<boost::mutex> lock( blockProcessedSignalMutex );
736  blockProcessedSignal.timed_wait( lock,
737  boost::posix_time::seconds( 1 ) );
738 
739 // std::cout << std::endl << "Woke up" << std::endl;
740 
741  if( progressPtr.get() )
742  {
743  int segmentedBlocksNmb = 0;
744  for( unsigned int segmentsMatrixLine = 0 ; segmentsMatrixLine <
745  segmentsblocksMatrix.getLinesNumber() ; ++segmentsMatrixLine )
746  {
747  for( unsigned int segmentsMatrixCol = 0 ; segmentsMatrixCol <
748  segmentsblocksMatrix.getColumnsNumber() ; ++segmentsMatrixCol )
749  {
750  if( segmentsblocksMatrix[ segmentsMatrixLine ][ segmentsMatrixCol ].m_status
752  {
753  ++segmentedBlocksNmb;
754  }
755  }
756  }
757 
758  if( segmentedBlocksNmb != prevSegmentedBlocksNmb )
759  {
760  progressPtr->pulse();
761  prevSegmentedBlocksNmb = segmentedBlocksNmb;
762  }
763 
764  if( ! progressPtr->isActive() )
765  {
766  abortSegmentationFlag = true;
767  }
768 
769 // std::cout << std::endl << "segmentedBlocksNmb:" << segmentedBlocksNmb << std::endl;
770  }
771  }
772 
773  // joining all threads
774 
775  threads.join_all();
776 /*
777  globalMutex.lock();
778  std::cout << std::endl << "Threads joined." << std::endl;
779  globalMutex.unlock();
780 */
781  }
782  else
783  { // non-threaded segmentation mode
784  runningThreadsCounter = 1;
785  segmenterThreadEntry( &baseSegThreadParams );
786  }
787 
788  return (!abortSegmentationFlag);
789  }
790  else
791  {
792  return false;
793  }
794  }
795 
796  void Segmenter::reset() throw( te::rp::Exception )
797  {
798  m_instanceInitialized = false;
800  }
801 
803  throw( te::rp::Exception )
804  {
805  reset();
806 
807  Segmenter::InputParameters const* inputParamsPtr = dynamic_cast<
808  Segmenter::InputParameters const* >( &inputParams );
809 
810  TERP_TRUE_OR_RETURN_FALSE( inputParamsPtr, "Invalid parameters" );
812  "Invalid raster pointer" );
815  "Invalid raster" );
816 
817  TERP_TRUE_OR_RETURN_FALSE( inputParamsPtr->m_inputRasterBands.size() > 0,
818  "Invalid raster bands number" );
819  for( unsigned int inputRasterBandsIdx = 0 ; inputRasterBandsIdx <
820  inputParamsPtr->m_inputRasterBands.size() ; ++inputRasterBandsIdx )
821  {
823  inputRasterBandsIdx ] < inputParamsPtr->m_inputRasterPtr->getNumberOfBands(),
824  "Invalid raster band number" );
825  }
826 
827  TERP_TRUE_OR_RETURN_FALSE( ( inputParamsPtr->m_inputRasterNoDataValues.empty() ?
828  true : ( inputParamsPtr->m_inputRasterNoDataValues.size() ==
829  inputParamsPtr->m_inputRasterBands.size() ) ),
830  "Invalid no-data values" );
831 
832  TERP_TRUE_OR_RETURN_FALSE( inputParamsPtr->m_blocksOverlapPercent <= 25,
833  "Invalid blocks overlapped area percentage" );
834 
835  m_inputParameters = *inputParamsPtr;
836  m_instanceInitialized = true;
837 
838  return true;
839  }
840 
842  {
843  return m_instanceInitialized;
844  }
845 
847  const unsigned int minExapandedBlockPixels,
848  const unsigned int maxExapandedBlockPixels,
849  unsigned int& blocksHOverlapSize,
850  unsigned int& blocksVOverlapSize,
851  unsigned int& nonExpandedBlockWidth,
852  unsigned int& nonExpandedBlockHeight,
853  unsigned int& expandedBlockWidth,
854  unsigned int& expandedBlockHeight ) const
855  {
856  TERP_TRUE_OR_THROW( minExapandedBlockPixels <= maxExapandedBlockPixels,
857  "Invalid min and mas block pixels number" );
858 
859  const double totalImageLines = (double)m_inputParameters.m_inputRasterPtr->getNumberOfRows();
860  const double totalImageCols = (double)m_inputParameters.m_inputRasterPtr->getNumberOfColumns();
861 
862  const double maxScaleFactor = (totalImageLines * totalImageCols) /
863  ((double)minExapandedBlockPixels);
864 
865  unsigned int rescaledAndExpandedBlockPixelsNmb = 0;
866 
867  for( double scaleFactor = 1.0 ; scaleFactor <= maxScaleFactor ;
868  scaleFactor += 1.0 )
869  {
870  nonExpandedBlockHeight = (unsigned int)std::ceil( ((double)totalImageLines) / scaleFactor );
871  nonExpandedBlockWidth = (unsigned int)std::ceil( ((double)totalImageCols) / scaleFactor );
872 
873  blocksHOverlapSize = (unsigned int)( ((double)m_inputParameters.m_blocksOverlapPercent) *
874  ((double)nonExpandedBlockWidth) / 100.0 );
875  blocksVOverlapSize = (unsigned int)( ((double)m_inputParameters.m_blocksOverlapPercent) *
876  ((double)nonExpandedBlockHeight) / 100.0 );
877 
878  expandedBlockHeight = nonExpandedBlockHeight + blocksVOverlapSize +
879  blocksVOverlapSize;
880  expandedBlockWidth = nonExpandedBlockWidth + blocksHOverlapSize +
881  blocksHOverlapSize;
882 
883  rescaledAndExpandedBlockPixelsNmb = expandedBlockHeight * expandedBlockWidth;
884 
885  if( rescaledAndExpandedBlockPixelsNmb <= maxExapandedBlockPixels )
886  {
887  return true;
888  }
889  }
890 
891  return false;
892  }
893 
895  {
896  TERP_DEBUG_TRUE_OR_THROW( paramsPtr, "Invalid pointer" );
898  "Invalid parameter" );
900  "Invalid parameter" );
902  "Invalid parameter" );
904  "Invalid parameter" );
906  "Invalid parameter" );
908  "Invalid parameter" );
910  "Invalid parameter" );
912  "Invalid parameter" );
914  "Invalid parameter" );
916  "Invalid parameter" );
918  "Invalid parameter" );
920  "Invalid parameter" );
922  "Invalid parameter" );
923 
924  // Creating the input raster instance
925 
927  *(paramsPtr->m_inputRasterSyncPtr) );
928 
929  // Creating the segmentation strategy instance
930 
931  paramsPtr->m_generalMutexPtr->lock();
932 
933  boost::shared_ptr< SegmenterStrategy > strategyPtr(
935  paramsPtr->m_inputParameters.m_strategyName ) );
936  TERP_TRUE_OR_THROW( strategyPtr.get(),
937  "Unable to create an segmentation strategy" );
938  if( ! strategyPtr->initialize(
939  paramsPtr->m_inputParameters.getSegStrategyParams() ) )
940  {
941  *(paramsPtr->m_runningThreadsCounterPtr) =
942  *(paramsPtr->m_runningThreadsCounterPtr) - 1;
943  *(paramsPtr->m_abortSegmentationFlagPtr) = true;
944 
945 // std::cout << std::endl<< "Thread exit (error)"
946 // << std::endl;
947 
948  paramsPtr->m_generalMutexPtr->unlock();
949 
950  return;
951  }
952  else
953  {
954  paramsPtr->m_generalMutexPtr->unlock();
955  }
956 
957  // Looking for a non processed segments block
958 
959  for( unsigned int sBMLine = 0 ; sBMLine <
960  paramsPtr->m_segsBlocksMatrixPtr->getLinesNumber() ; ++sBMLine )
961  {
962  for( unsigned int sBMCol = 0 ; sBMCol <
963  paramsPtr->m_segsBlocksMatrixPtr->getColumnsNumber() ; ++sBMCol )
964  {
965  if( *(paramsPtr->m_abortSegmentationFlagPtr) )
966  {
967  paramsPtr->m_generalMutexPtr->lock();
968 
969  *(paramsPtr->m_runningThreadsCounterPtr) =
970  *(paramsPtr->m_runningThreadsCounterPtr) - 1;
971 
972 // std::cout << std::endl<< "Thread exit (error)"
973 // << std::endl;
974 
975  paramsPtr->m_generalMutexPtr->unlock();
976 
977  return;
978  }
979  else
980  {
981  paramsPtr->m_generalMutexPtr->lock();
982 
983  SegmenterSegmentsBlock& segsBlk =
984  paramsPtr->m_segsBlocksMatrixPtr->operator()( sBMLine, sBMCol );
985 
987  {
988 // TERP_LOGMSG( "Thread:" + boost::lexical_cast< std::string >(
989 // boost::this_thread::get_id() ) + " - Processing block:[" +
990 // boost::lexical_cast< std::string >( sBMLine ) + "," +
991 // boost::lexical_cast< std::string >( sBMCol ) + "]" );
992 
994 /*
995  std::cout << std::endl<< "Start block processing [" +
996  te::common::Convert2String( sBMCol ) + "," +
997  te::common::Convert2String( sBMLine ) + "]"
998  << std::endl;
999 */
1000  paramsPtr->m_generalMutexPtr->unlock();
1001 
1002  // Creating the output raster instance
1003 
1004  te::rst::SynchronizedRaster outputRaster( 1, *(paramsPtr->m_outputRasterSyncPtr) );
1005 
1006  // Executing the strategy
1007 
1008  if( ! strategyPtr->execute(
1009  *paramsPtr->m_segmentsIdsManagerPtr,
1010  segsBlk,
1011  inputRaster,
1013  paramsPtr->m_inputRasterNoDataValues,
1014  paramsPtr->m_inputRasterBandMinValues,
1015  paramsPtr->m_inputRasterBandMaxValues,
1016  outputRaster,
1017  0,
1018  paramsPtr->m_enableStrategyProgress ) )
1019  {
1020  paramsPtr->m_generalMutexPtr->lock();
1021 
1022  *(paramsPtr->m_runningThreadsCounterPtr) =
1023  *(paramsPtr->m_runningThreadsCounterPtr) - 1;
1024  *(paramsPtr->m_abortSegmentationFlagPtr) = true;
1025 
1026 // std::cout << std::endl<< "Thread exit (error)"
1027 // << std::endl;
1028 
1029  paramsPtr->m_generalMutexPtr->unlock();
1030 
1031  return;
1032  }
1033 
1034  // updating block status
1035 
1036  paramsPtr->m_generalMutexPtr->lock();
1037 
1039 /*
1040  std::cout << std::endl<< "Block processed [" +
1041  te::common::Convert2String( sBMCol ) + "," +
1042  te::common::Convert2String( sBMLine ) + "]"
1043  << std::endl;
1044 */
1045  paramsPtr->m_generalMutexPtr->unlock();
1046 
1047  // notifying the main thread with the block processed signal
1048 
1049  boost::lock_guard<boost::mutex> blockProcessedSignalLockGuard(
1050  *( paramsPtr->m_blockProcessedSignalMutexPtr) );
1051 
1052  paramsPtr->m_blockProcessedSignalPtr->notify_one();
1053 
1054  }
1055  else
1056  {
1057  paramsPtr->m_generalMutexPtr->unlock();
1058  }
1059  }
1060  }
1061  }
1062 
1063  // Destroying the strategy object
1064 
1065  strategyPtr.reset();
1066 
1067  // ending tasks
1068 
1069  paramsPtr->m_generalMutexPtr->lock();
1070 
1071  *(paramsPtr->m_runningThreadsCounterPtr) =
1072  *(paramsPtr->m_runningThreadsCounterPtr) - 1;
1073 
1074 // std::cout << std::endl<< "Thread exit (OK)"
1075 // << std::endl;
1076 
1077  paramsPtr->m_generalMutexPtr->unlock();
1078  }
1079 
1080  bool Segmenter::genImageHCutOffProfile( const unsigned int profileCenter,
1081  const te::rst::Raster& inRaster,
1082  const std::vector< unsigned int >& inRasterBands,
1083  const unsigned int pixelNeighborhoodSize,
1084  const unsigned int tileNeighborhoodSize,
1085  const unsigned int profileAntiSmoothingFactor,
1086  std::vector< unsigned int>& profile ) const
1087  {
1088  profile.clear();
1089 
1090  if( profileAntiSmoothingFactor == 0 )
1091  {
1092  return false;
1093  }
1094  if( profileCenter >= inRaster.getNumberOfRows() )
1095  {
1096  return false;
1097  }
1098  if( tileNeighborhoodSize < pixelNeighborhoodSize )
1099  {
1100  return false;
1101  }
1102 
1103  const int inRasterRowsNmb = (int)inRaster.getNumberOfRows();
1104  const int inRasterColsNmb = (int)inRaster.getNumberOfColumns();
1105  const int inRasterBandsSize = (int)inRasterBands.size();
1106 
1107  // Calculating the tiles buffer dimension
1108 
1109  const int tilesBufferStartIdx = MAX( 0, MIN( inRasterRowsNmb - 1,
1110  ((int)profileCenter) - ((int)tileNeighborhoodSize) ) );
1111  const int tilesBufferBoundIdx = MAX( 0, MIN( inRasterRowsNmb,
1112  1 + ((int)profileCenter) + ((int)tileNeighborhoodSize) ) );
1113  const int tilesBufferSize = tilesBufferBoundIdx - tilesBufferStartIdx;
1114  if( tilesBufferSize < ( 1 + ( 2 * ( (int)( pixelNeighborhoodSize ) ) ) ) )
1115  return false;
1116 
1117  const int minCrossProfileStartIdx = tilesBufferStartIdx +
1118  (int)pixelNeighborhoodSize;
1119  const int maxCrossProfileBoundIdx = tilesBufferBoundIdx -
1120  (int)pixelNeighborhoodSize;
1121 
1122  int crossProfileIdx = 0;
1123  int crossProfileStartIdx = 0;
1124  int crossProfileBoundIdx = 0;
1125 
1126  int pixelNBStartIdx = 0;
1127  int pixelNBEndIdx = 0;
1128  int pixel1NBIdx = 0;
1129  int pixel2NBIdx = 0;
1130  int pixelNBOffset = 0;
1131 
1132  double diffSum = 0;
1133  double currBandDiffSum = 0;
1134  double higherDiffSum = 0;
1135  int higherDiffSumIdx = 0;
1136 
1137  int inRasterBandsIdx = 0;
1138  unsigned int bandIdx = 0;
1139 
1140  double pixel1Value = 0;
1141  double pixel2Value = 0;
1142 
1143  profile.resize( inRasterColsNmb, 0 );
1144 
1145  for( int profileElementIdx = 0 ; profileElementIdx < inRasterColsNmb ;
1146  ++profileElementIdx )
1147  {
1148  if( profileElementIdx )
1149  {
1150  crossProfileStartIdx = profile[ profileElementIdx - 1 ] -
1151  (int)profileAntiSmoothingFactor;
1152  crossProfileStartIdx = MAX( crossProfileStartIdx,
1153  minCrossProfileStartIdx );
1154 
1155  crossProfileBoundIdx = profile[ profileElementIdx - 1 ] + 1 +
1156  ((int)profileAntiSmoothingFactor);
1157  crossProfileBoundIdx = MIN( crossProfileBoundIdx,
1158  maxCrossProfileBoundIdx );
1159  }
1160  else
1161  {
1162  crossProfileStartIdx = minCrossProfileStartIdx;
1163  crossProfileBoundIdx = maxCrossProfileBoundIdx;
1164  }
1165 
1166  higherDiffSum = 0;
1167  higherDiffSumIdx = crossProfileStartIdx;
1168 
1169  for( crossProfileIdx = crossProfileStartIdx ; crossProfileIdx <
1170  crossProfileBoundIdx ; ++crossProfileIdx )
1171  {
1172  // look for the higher diff using all bands
1173  // within the defined neighborhood
1174 
1175  diffSum = 0;
1176 
1177  for( inRasterBandsIdx = 0 ; inRasterBandsIdx < inRasterBandsSize ;
1178  ++inRasterBandsIdx )
1179  {
1180  bandIdx = inRasterBands[ inRasterBandsIdx ];
1181  TERP_DEBUG_TRUE_OR_THROW( bandIdx < inRaster.getNumberOfBands(),
1182  "Invalid band" )
1183 
1184  pixelNBStartIdx = crossProfileIdx - ( (int)pixelNeighborhoodSize);
1185  pixelNBEndIdx = crossProfileIdx + ( (int)pixelNeighborhoodSize);
1186  currBandDiffSum = 0;
1187 
1188  for( pixelNBOffset = 0 ; pixelNBOffset < ((int)pixelNeighborhoodSize) ;
1189  ++pixelNBOffset )
1190  {
1191  pixel1NBIdx = pixelNBStartIdx + pixelNBOffset;
1192  pixel2NBIdx = pixelNBEndIdx - pixelNBOffset;
1193 
1194  TERP_DEBUG_TRUE_OR_THROW( ( pixel1NBIdx >= 0 ) &&
1195  ( pixel1NBIdx < inRasterRowsNmb ), "Invalid pixel2Idx" )
1196  TERP_DEBUG_TRUE_OR_THROW( ( pixel2NBIdx >= 0 ) &&
1197  ( pixel2NBIdx < inRasterRowsNmb ), "Invalid pixel2Idx" )
1198 
1199  inRaster.getValue( profileElementIdx,
1200  pixel1NBIdx, pixel1Value, bandIdx );
1201  inRaster.getValue( profileElementIdx,
1202  pixel2NBIdx, pixel2Value, bandIdx );
1203 
1204  currBandDiffSum += ABS( pixel1Value - pixel2Value );
1205  }
1206 
1207  diffSum += ( currBandDiffSum / ((double)( pixelNBEndIdx -
1208  pixelNBStartIdx + 1 ) ) );
1209  }
1210 
1211  if( diffSum > higherDiffSum )
1212  {
1213  higherDiffSum = diffSum;
1214  higherDiffSumIdx = crossProfileIdx;
1215  }
1216  }
1217 
1218  profile[ profileElementIdx ] = higherDiffSumIdx;
1219  }
1220 
1221  return true;
1222  }
1223 
1224  bool Segmenter::genImageVCutOffProfile( const unsigned int profileCenter,
1225  const te::rst::Raster& inRaster,
1226  const std::vector< unsigned int >& inRasterBands,
1227  const unsigned int pixelNeighborhoodSize,
1228  const unsigned int tileNeighborhoodSize,
1229  const unsigned int profileAntiSmoothingFactor,
1230  std::vector< unsigned int>& profile ) const
1231  {
1232  profile.clear();
1233 
1234  if( profileAntiSmoothingFactor == 0 )
1235  {
1236  return false;
1237  }
1238  if( profileCenter >= inRaster.getNumberOfColumns() )
1239  {
1240  return false;
1241  }
1242  if( tileNeighborhoodSize < pixelNeighborhoodSize )
1243  {
1244  return false;
1245  }
1246 
1247  const int inRasterRowsNmb = (int)inRaster.getNumberOfRows();
1248  const int inRasterColsNmb = (int)inRaster.getNumberOfColumns();
1249  const int inRasterBandsSize = (int)inRasterBands.size();
1250 
1251  // Calculating the tiles buffer dimension
1252 
1253  const int tilesBufferStartIdx = MAX( 0, MIN( inRasterColsNmb - 1,
1254  ((int)profileCenter) - ((int)tileNeighborhoodSize) ) );
1255  const int tilesBufferBoundIdx = MAX( 0, MIN( inRasterColsNmb,
1256  1 + ((int)profileCenter) + ((int)tileNeighborhoodSize) ) );
1257  const int tilesBufferSize = tilesBufferBoundIdx - tilesBufferStartIdx;
1258  if( tilesBufferSize < ( 1 + ( 2 * ( (int)( pixelNeighborhoodSize ) ) ) ) )
1259  return false;
1260 
1261  const int minCrossProfileStartIdx = tilesBufferStartIdx +
1262  (int)pixelNeighborhoodSize;
1263  const int maxCrossProfileBoundIdx = tilesBufferBoundIdx -
1264  (int)pixelNeighborhoodSize;
1265 
1266  int crossProfileIdx = 0;
1267  int crossProfileStartIdx = 0;
1268  int crossProfileBoundIdx = 0;
1269 
1270  int pixelNBStartIdx = 0;
1271  int pixelNBEndIdx = 0;
1272  int pixel1NBIdx = 0;
1273  int pixel2NBIdx = 0;
1274  int pixelNBOffset = 0;
1275 
1276  double diffSum = 0;
1277  double currBandDiffSum = 0;
1278  double higherDiffSum = 0;
1279  int higherDiffSumIdx = 0;
1280 
1281  int inRasterBandsIdx = 0;
1282  unsigned int bandIdx = 0;
1283 
1284  double pixel1Value = 0;
1285  double pixel2Value = 0;
1286 
1287  profile.resize( inRasterRowsNmb, 0 );
1288 
1289  for( int profileElementIdx = 0 ; profileElementIdx < inRasterRowsNmb ;
1290  ++profileElementIdx )
1291  {
1292  if( profileElementIdx )
1293  {
1294  crossProfileStartIdx = profile[ profileElementIdx - 1 ] -
1295  (int)profileAntiSmoothingFactor;
1296  crossProfileStartIdx = MAX( crossProfileStartIdx,
1297  minCrossProfileStartIdx );
1298 
1299  crossProfileBoundIdx = profile[ profileElementIdx - 1 ] + 1 +
1300  ((int)profileAntiSmoothingFactor);
1301  crossProfileBoundIdx = MIN( crossProfileBoundIdx,
1302  maxCrossProfileBoundIdx );
1303  }
1304  else
1305  {
1306  crossProfileStartIdx = minCrossProfileStartIdx;
1307  crossProfileBoundIdx = maxCrossProfileBoundIdx;
1308  }
1309 
1310  higherDiffSum = 0;
1311  higherDiffSumIdx = crossProfileStartIdx;
1312 
1313  for( crossProfileIdx = crossProfileStartIdx ; crossProfileIdx <
1314  crossProfileBoundIdx ; ++crossProfileIdx )
1315  {
1316  // look for the higher diff using all bands
1317  // within the defined neighborhood
1318 
1319  diffSum = 0;
1320 
1321  for( inRasterBandsIdx = 0 ; inRasterBandsIdx < inRasterBandsSize ;
1322  ++inRasterBandsIdx )
1323  {
1324  bandIdx = inRasterBands[ inRasterBandsIdx ];
1325  TERP_DEBUG_TRUE_OR_THROW( bandIdx < inRaster.getNumberOfBands(),
1326  "Invalid band" )
1327 
1328  pixelNBStartIdx = crossProfileIdx - ( (int)pixelNeighborhoodSize);
1329  pixelNBEndIdx = crossProfileIdx + ( (int)pixelNeighborhoodSize);
1330  currBandDiffSum = 0;
1331 
1332  for( pixelNBOffset = 0 ; pixelNBOffset < ((int)pixelNeighborhoodSize) ;
1333  ++pixelNBOffset )
1334  {
1335  pixel1NBIdx = pixelNBStartIdx + pixelNBOffset;
1336  pixel2NBIdx = pixelNBEndIdx - pixelNBOffset;
1337 
1338  TERP_DEBUG_TRUE_OR_THROW( ( pixel1NBIdx >= 0 ) &&
1339  ( pixel1NBIdx < inRasterColsNmb ), "Invalid pixel2Idx" )
1340  TERP_DEBUG_TRUE_OR_THROW( ( pixel2NBIdx >= 0 ) &&
1341  ( pixel2NBIdx < inRasterColsNmb ), "Invalid pixel2Idx" )
1342 
1343  inRaster.getValue( pixel1NBIdx, profileElementIdx,
1344  pixel1Value, bandIdx );
1345  inRaster.getValue( pixel2NBIdx, profileElementIdx,
1346  pixel2Value, bandIdx );
1347 
1348  currBandDiffSum += ABS( pixel1Value - pixel2Value );
1349  }
1350 
1351  diffSum += ( currBandDiffSum / ((double)( pixelNBEndIdx -
1352  pixelNBStartIdx + 1 ) ) );
1353  }
1354 
1355  if( diffSum > higherDiffSum )
1356  {
1357  higherDiffSum = diffSum;
1358  higherDiffSumIdx = crossProfileIdx;
1359  }
1360  }
1361 
1362  profile[ profileElementIdx ] = higherDiffSumIdx;
1363  }
1364 
1365  return true;
1366  }
1367 
1369  const std::vector< std::vector< unsigned int> >& imageHorizontalProfiles,
1370  const std::vector< std::vector< unsigned int> >& imageVerticalProfiles,
1371  SegmenterSegmentsBlock& segmentsBlock ) const
1372  {
1373  if( segmentsBlock.m_segmentsMatrixXIndex > imageVerticalProfiles.size() )
1374  {
1375  return false;
1376  }
1377  if( segmentsBlock.m_segmentsMatrixYIndex > imageHorizontalProfiles.size() )
1378  {
1379  return false;
1380  }
1381 
1382  // generating m_topCutOffProfile
1383 
1384  segmentsBlock.m_topCutOffProfile.clear();
1385 
1386  if( ( segmentsBlock.m_segmentsMatrixYIndex > 0 ) &&
1387  ( segmentsBlock.m_segmentsMatrixYIndex <=
1388  imageHorizontalProfiles.size() ) )
1389  {
1390  const std::vector< unsigned int >& profile = imageHorizontalProfiles[
1391  segmentsBlock.m_segmentsMatrixYIndex - 1 ];
1392 
1393  if( profile.empty() )
1394  {
1395  return false;
1396  }
1397  else
1398  {
1399  segmentsBlock.m_topCutOffProfile.resize( segmentsBlock.m_width );
1400  int profElementValue = 0;
1401 
1402  for( unsigned int profEIdx = 0 ; profEIdx < segmentsBlock.m_width ;
1403  ++profEIdx )
1404  {
1405  if( profEIdx + segmentsBlock.m_startX >= profile.size() )
1406  {
1407  return false;
1408  }
1409 
1410  profElementValue =
1411  ((int)profile[ profEIdx + segmentsBlock.m_startX ]) -
1412  ((int)segmentsBlock.m_startY);
1413  profElementValue = MAX( 0, profElementValue );
1414  profElementValue = MIN( (int)segmentsBlock.m_height, profElementValue );
1415 
1416  segmentsBlock.m_topCutOffProfile[ profEIdx ] = profElementValue;
1417  }
1418  }
1419  }
1420  else
1421  {
1422  segmentsBlock.m_topCutOffProfile.resize( segmentsBlock.m_width, 0 );
1423  }
1424 
1425  // generating m_bottomCutOffProfile
1426 
1427  segmentsBlock.m_bottomCutOffProfile.clear();
1428 
1429  if( segmentsBlock.m_segmentsMatrixYIndex <
1430  imageHorizontalProfiles.size() )
1431  {
1432  const std::vector< unsigned int >& profile = imageHorizontalProfiles[
1433  segmentsBlock.m_segmentsMatrixYIndex ];
1434 
1435  if( profile.empty() )
1436  {
1437  return false;
1438  }
1439  else
1440  {
1441  segmentsBlock.m_bottomCutOffProfile.resize( segmentsBlock.m_width );
1442  int profElementValue = 0;
1443 
1444  for( unsigned int profEIdx = 0 ; profEIdx < segmentsBlock.m_width ;
1445  ++profEIdx )
1446  {
1447  if( profEIdx + segmentsBlock.m_startX >= profile.size() )
1448  {
1449  return false;
1450  }
1451 
1452  profElementValue =
1453  ((int)profile[ profEIdx + segmentsBlock.m_startX ]) -
1454  ((int)segmentsBlock.m_startY);
1455  profElementValue = MAX( 0, profElementValue );
1456  profElementValue = MIN( (int)segmentsBlock.m_height, profElementValue );
1457 
1458  segmentsBlock.m_bottomCutOffProfile[ profEIdx ] = profElementValue;
1459  }
1460  }
1461  }
1462  else
1463  {
1464  segmentsBlock.m_bottomCutOffProfile.resize( segmentsBlock.m_width,
1465  segmentsBlock.m_height - 1);
1466  }
1467 
1468  // generating m_leftCutOffProfile
1469 
1470  segmentsBlock.m_leftCutOffProfile.clear();
1471 
1472  if( ( segmentsBlock.m_segmentsMatrixXIndex > 0 ) &&
1473  ( segmentsBlock.m_segmentsMatrixXIndex <=
1474  imageVerticalProfiles.size() ) )
1475  {
1476  const std::vector< unsigned int >& profile = imageVerticalProfiles[
1477  segmentsBlock.m_segmentsMatrixXIndex - 1 ];
1478 
1479  if( profile.empty() )
1480  {
1481  return false;
1482  }
1483  else
1484  {
1485  segmentsBlock.m_leftCutOffProfile.resize( segmentsBlock.m_height );
1486  int profElementValue = 0;
1487 
1488  for( unsigned int profEIdx = 0 ; profEIdx < segmentsBlock.m_height ;
1489  ++profEIdx )
1490  {
1491  if( profEIdx + segmentsBlock.m_startY >= profile.size() )
1492  {
1493  return false;
1494  }
1495 
1496  profElementValue =
1497  ((int)profile[ profEIdx + segmentsBlock.m_startY ]) -
1498  ((int)segmentsBlock.m_startX);
1499  profElementValue = MAX( 0, profElementValue );
1500  profElementValue = MIN( (int)segmentsBlock.m_width, profElementValue );
1501 
1502  segmentsBlock.m_leftCutOffProfile[ profEIdx ] = profElementValue;
1503  }
1504  }
1505  }
1506  else
1507  {
1508  segmentsBlock.m_leftCutOffProfile.resize( segmentsBlock.m_height, 0 );
1509  }
1510 
1511  // generating m_rightCutOffProfile
1512 
1513  segmentsBlock.m_rightCutOffProfile.clear();
1514 
1515  if( segmentsBlock.m_segmentsMatrixXIndex <
1516  imageVerticalProfiles.size() )
1517  {
1518  const std::vector< unsigned int >& profile = imageVerticalProfiles[
1519  segmentsBlock.m_segmentsMatrixXIndex ];
1520 
1521  if( profile.empty() )
1522  {
1523  return false;
1524  }
1525  else
1526  {
1527  segmentsBlock.m_rightCutOffProfile.resize( segmentsBlock.m_height );
1528  int profElementValue = 0;
1529 
1530  for( unsigned int profEIdx = 0 ; profEIdx < segmentsBlock.m_height ;
1531  ++profEIdx )
1532  {
1533  if( profEIdx + segmentsBlock.m_startY >= profile.size() )
1534  {
1535  return false;
1536  }
1537 
1538  profElementValue =
1539  ((int)profile[ profEIdx + segmentsBlock.m_startY ]) -
1540  ((int)segmentsBlock.m_startX);
1541  profElementValue = MAX( 0, profElementValue );
1542  profElementValue = MIN( (int)segmentsBlock.m_width, profElementValue );
1543 
1544  segmentsBlock.m_rightCutOffProfile[ profEIdx ] = profElementValue;
1545  }
1546  }
1547  }
1548  else
1549  {
1550  segmentsBlock.m_rightCutOffProfile.resize( segmentsBlock.m_height,
1551  segmentsBlock.m_width - 1 );
1552  }
1553 
1554  assert( segmentsBlock.m_topCutOffProfile.size() == segmentsBlock.m_width );
1555  assert( segmentsBlock.m_bottomCutOffProfile.size() == segmentsBlock.m_width );
1556  assert( segmentsBlock.m_leftCutOffProfile.size() == segmentsBlock.m_height );
1557  assert( segmentsBlock.m_rightCutOffProfile.size() == segmentsBlock.m_height );
1558 
1559  return true;
1560  }
1561 
1563  const std::vector< std::vector< unsigned int> >& imageHorizontalProfiles,
1564  const std::vector< unsigned int >& imageHorizontalProfilesCenterLines,
1565  const std::vector< std::vector< unsigned int> >& imageVerticalProfiles,
1566  const std::vector< unsigned int >& imageVerticalProfilesCenterLines,
1567  const std::string& filename )
1568  {
1569  TERP_TRUE_OR_THROW( imageHorizontalProfiles.size() ==
1570  imageHorizontalProfilesCenterLines.size(), "Internal error" )
1571  TERP_TRUE_OR_THROW( imageVerticalProfiles.size() ==
1572  imageVerticalProfilesCenterLines.size(), "Internal error" )
1573 
1574  std::vector< te::rst::BandProperty* > bandsProperties;
1575  bandsProperties.push_back( new te::rst::BandProperty(
1578  bandsProperties[ 0 ]->m_colorInterp = te::rst::GrayIdxCInt;
1579  bandsProperties[ 0 ]->m_noDataValue = 0;
1580  bandsProperties[ 0 ]->m_type = te::dt::UCHAR_TYPE;
1581  //bandsProperties[ 0 ]->m_noDataValue = 0;
1582 
1583  std::map< std::string, std::string > rInfo;
1584  rInfo[ "URI" ] = "cutofflines.tif";
1585 
1586  std::auto_ptr< te::rst::Raster > outRasterPtr(
1589  bandsProperties, rInfo ) );
1590  TERP_TRUE_OR_RETURN_FALSE( outRasterPtr.get(),
1591  "Tiff creation error" )
1592 
1593  {
1594  for( unsigned int profIdx = 0 ; profIdx < imageHorizontalProfiles.size() ;
1595  ++profIdx )
1596  {
1597  const std::vector< unsigned int>& profile =
1598  imageHorizontalProfiles[ profIdx ];
1599  TERP_TRUE_OR_THROW( profile.size() ==
1600  outRasterPtr->getGrid()->getNumberOfColumns(), "Internal error" )
1601 
1602  const unsigned int centerLineIdx =
1603  imageHorizontalProfilesCenterLines[ profIdx ];
1604  TERP_TRUE_OR_THROW( centerLineIdx <
1605  outRasterPtr->getGrid()->getNumberOfRows(), "Internal error" )
1606 
1607 
1608  for( unsigned int eIdx = 0 ; eIdx < profile.size() ;
1609  ++eIdx )
1610  {
1611  TERP_TRUE_OR_THROW( profile[ eIdx ] <
1612  outRasterPtr->getGrid()->getNumberOfRows(), "Internal error" )
1613 
1614  outRasterPtr->setValue( eIdx, centerLineIdx, 255, 0 );
1615  outRasterPtr->setValue( eIdx, profile[ eIdx ] , 255, 0 );
1616  }
1617  }
1618  }
1619 
1620  {
1621  for( unsigned int profIdx = 0 ; profIdx < imageVerticalProfiles.size() ;
1622  ++profIdx )
1623  {
1624  const std::vector< unsigned int>& profile =
1625  imageVerticalProfiles[ profIdx ];
1626  TERP_TRUE_OR_THROW( profile.size() ==
1627  outRasterPtr->getGrid()->getNumberOfRows(), "Internal error" )
1628 
1629  const unsigned int centerLineIdx =
1630  imageVerticalProfilesCenterLines[ profIdx ];
1631  TERP_TRUE_OR_THROW( centerLineIdx <
1632  outRasterPtr->getGrid()->getNumberOfColumns(), "Internal error" )
1633 
1634  for( unsigned int eIdx = 0 ; eIdx < profile.size() ;
1635  ++eIdx )
1636  {
1637  TERP_TRUE_OR_THROW( profile[ eIdx ] <
1638  outRasterPtr->getGrid()->getNumberOfRows(), "Internal error" )
1639 
1640  outRasterPtr->setValue( centerLineIdx, eIdx, 255, 0 );
1641  outRasterPtr->setValue( profile[ eIdx ], eIdx, 255, 0 );
1642  }
1643  }
1644  }
1645 
1646  return true;
1647  }
1648  } // end namespace rp
1649 } // end namespace te
1650 
bool m_instanceInitialized
Definition: Segmenter.h:255
Segmenter segments IDs manager.
virtual AbstractParameters * clone() const =0
Create a clone copy of this instance.
Raster segmenter strategy factory base class.
AbstractParameters * clone() const
Create a clone copy of this instance.
Definition: Segmenter.cpp:179
std::string m_strategyName
The segmenter strategy name see each te::rp::SegmenterStrategyFactory inherited classes documentation...
Definition: Segmenter.h:101
unsigned char m_blocksOverlapPercent
The percentage of blocks overlapped area (valid range:0-25, defaul:10).
Definition: Segmenter.h:99
An adapter class to allow concurrent access to raster data by multiple threads.
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
Definition: Segmenter.cpp:77
Segmenter Output Parameters.
Definition: Segmenter.h:149
#define ABS(x)
Absolute value.
Definition: Macros.h:402
Index into a lookup table.
Definition: Enums.h:57
bool updateBlockCutOffProfiles(const std::vector< std::vector< unsigned int > > &imageHorizontalProfiles, const std::vector< std::vector< unsigned int > > &imageVerticalProfiles, SegmenterSegmentsBlock &segmentsBlock) const
Update the block cutOff profiles using the full image profiles.
Definition: Segmenter.cpp:1368
virtual void getValue(unsigned int c, unsigned int r, double &value) const =0
Returns the cell attribute value.
SegmenterIdsManager * m_segmentsIdsManagerPtr
Pointer to the segments Ids manager - (default 0).
Definition: Segmenter.h:227
A raster band description.
Definition: BandProperty.h:61
unsigned int getNumberOfColumns() const
Returns the raster number of columns.
Definition: Raster.cpp:213
bool initialize(const AlgorithmInputParameters &inputParams)
Initialize the algorithm instance making it ready for execution.
Definition: Segmenter.cpp:802
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
AbstractParameters * clone() const
Create a clone copy of this instance.
Definition: Segmenter.cpp:122
std::vector< double > m_inputRasterBandMaxValues
A vector of input raster bands maximum values.
Definition: Segmenter.h:239
boost::mutex * m_blockProcessedSignalMutexPtr
Pointer to the mutex used by the block processed signal (default:0).
Definition: Segmenter.h:221
bool createCutOffLinesTiff(const std::vector< std::vector< unsigned int > > &imageHorizontalProfiles, const std::vector< unsigned int > &imageHorizontalProfilesCenterLines, const std::vector< std::vector< unsigned int > > &imageVerticalProfiles, const std::vector< unsigned int > &imageVerticalProfilesCenterLines, const std::string &filename)
Definition: Segmenter.cpp:1562
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
std::vector< double > m_inputRasterBandMinValues
A vector of input raster bands minimum values.
Definition: Segmenter.h:236
Raster Processing algorithm output parameters base interface.
#define MIN(a, b)
Macro that returns min between two values.
std::auto_ptr< te::rst::Raster > m_outputRasterPtr
A pointer the ge generated output raster (label image).
Definition: Segmenter.h:157
std::string m_rType
Output raster data source type (as described in te::raster::RasterFactory ).
Definition: Segmenter.h:153
The parameters passed to the Segmenter::segmenterthreadEntry method.
Definition: Segmenter.h:199
An access synchronizer to be used in SynchronizedRaster raster instances.
double m_noDataValue
Value to indicate elements where there is no data, default is std::numeric_limits::max().
Definition: BandProperty.h:136
bool isInitialized() const
Returns true if the algorithm instance is initialized and ready for execution.
Definition: Segmenter.cpp:841
bool calcBestBlockSize(const unsigned int minExapandedBlockPixels, const unsigned int maxExapandedBlockPixels, unsigned int &blocksHOverlapSize, unsigned int &blocksVOverlapSize, unsigned int &nonExpandedBlockWidth, unsigned int &nonExpandedBlockHeight, unsigned int &expandedBlockWidth, unsigned int &expandedBlockHeight) const
Calc the best sub-image block size for each thread to process.
Definition: Segmenter.cpp:846
#define MAX(a, b)
Macro that returns max between two values.
bool volatile * m_abortSegmentationFlagPtr
Pointer to the abort segmentation flag (default:0).
Definition: Segmenter.h:224
unsigned int m_maxBlockSize
The input image will be split into blocks with this width for processing, this parameter tells the ma...
Definition: Segmenter.h:97
static void segmenterThreadEntry(SegmenterThreadEntryParams *paramsPtr)
Segmenter thread entry.
Definition: Segmenter.cpp:894
Raster Processing functions.
#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
const Algorithm & operator=(const Algorithm &)
Definition: Algorithm.cpp:43
bool m_enableProgress
Enable/Disable the progress interface (default:false).
Definition: Segmenter.h:103
te::common::AccessPolicy getAccessPolicy() const
Returns the raster access policy.
Definition: Raster.cpp:89
void reset()
Clear all internal allocated resources and reset the parameters instance to its initial state...
Definition: Segmenter.cpp:161
TECOMMONEXPORT unsigned int GetPhysProcNumber()
Returns the number of physical processors.
Raster segmentation.
std::vector< unsigned int > m_rightCutOffProfile
Segmenter::InputParameters m_inputParameters
Segmenter execution parameters.
Definition: Segmenter.h:257
void setSegStrategyParams(const SegmenterStrategyParameters &segStratParams)
Set specific segmenter strategy parameters.
Definition: Segmenter.cpp:127
TECOMMONEXPORT unsigned long int GetUsedVirtualMemory()
Returns the amount of used virtual memory (bytes) for the current process (physical + swapped)...
An abstract class for raster data strucutures.
Definition: Raster.h:71
unsigned int getNumberOfRows() const
Returns the raster number of rows.
Definition: Raster.cpp:208
unsigned int getColumnsNumber() const
The number of current matrix columns.
Definition: Matrix.h:678
te::rst::Raster const * m_inputRasterPtr
Input raster.
Definition: Segmenter.h:85
BandProperty * getProperty()
Returns the band property.
Definition: Band.cpp:428
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
A RAM cache adaptor to an external existent raster that must always be avaliable. ...
Definition: CachedRaster.h:52
te::rst::RasterSynchronizer * m_inputRasterSyncPtr
Pointer to the input raster synchronizer (default:0).
Definition: Segmenter.h:215
Segmenter::OutputParameters * m_outputParametersPtr
A pointer to the global segmenter input execution parameters (default:0).
Definition: Segmenter.h:206
unsigned int m_maxInputRasterCachedBlocks
The maximum number of input raster cached blocks per-thread.
Definition: Segmenter.h:248
A raster band description.
Definition: Band.h:63
Segmenter Input Parameters.
Definition: Segmenter.h:81
std::vector< double > m_inputRasterNoDataValues
A vector of values to be used as input raster no-data values.
Definition: Segmenter.h:242
Grid * getGrid()
It returns the raster grid.
Definition: Raster.cpp:94
static te::rp::SegmenterStrategy * make(const std::string &factoryKey)
It creates an object with the appropriated factory.
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
virtual void setValue(unsigned int c, unsigned int r, const double value)=0
Sets the cell attribute value.
std::map< std::string, std::string > m_rInfo
The necessary information to create the raster (as described in te::raster::RasterFactory).
Definition: Segmenter.h:155
Abstract parameters base interface.
bool genImageHCutOffProfile(const unsigned int profileCenter, const te::rst::Raster &inRaster, const std::vector< unsigned int > &inRasterBands, const unsigned int pixelNeighborhoodSize, const unsigned int tileNeighborhoodSize, const unsigned int profileAntiSmoothingFactor, std::vector< unsigned int > &profile) const
Generate the horizontal cutOff prifles for the entire image..
Definition: Segmenter.cpp:1080
bool m_enableRasterCache
Enable/Disable the use of raster data cache (default:true).
Definition: Segmenter.h:105
bool genImageVCutOffProfile(const unsigned int profileCenter, const te::rst::Raster &inRaster, const std::vector< unsigned int > &inRasterBands, const unsigned int pixelNeighborhoodSize, const unsigned int tileNeighborhoodSize, const unsigned int profileAntiSmoothingFactor, std::vector< unsigned int > &profile) const
Generate the vertical cutOff prifles for the entire image..
Definition: Segmenter.cpp:1224
bool m_enableStrategyProgress
Enable/Disable the segmentation strategy to use its own progress interface (default:false).
Definition: Segmenter.h:245
A generic template matrix.
Definition: Matrix.h:51
static Raster * make()
It creates and returns an empty raster with default raster driver.
SegmenterStrategyParameters * m_segStratParamsPtr
A pointer to the internal specific segmenter strategy parameters or NULL if no parameters are present...
Definition: Segmenter.h:142
const Segmenter::InputParameters & operator=(const Segmenter::InputParameters &params)
Definition: Segmenter.cpp:98
SegmentsBlocksMatrixT * m_segsBlocksMatrixPtr
Pointer to the segments blocks matrix (default:0).
Definition: Segmenter.h:209
Raster Processing algorithm input parameters base interface.
Segmenter segments block description class.
boost::condition_variable * m_blockProcessedSignalPtr
Pointer to a signal to be emited when a segments block was processed (default:0). ...
Definition: Segmenter.h:230
TECOMMONEXPORT unsigned long int GetTotalPhysicalMemory()
Returns the amount of total physical memory (bytes).
boost::mutex * m_generalMutexPtr
Pointer to a general global mutex (default:0).
Definition: Segmenter.h:212
te::rst::RasterSynchronizer * m_outputRasterSyncPtr
Pointer to the output raster synchronizer (default:0).
Definition: Segmenter.h:218
bool m_enableThreadedProcessing
If true, threaded processing will be performed (best with multi-core or multi-processor systems (defa...
Definition: Segmenter.h:91
bool execute(AlgorithmOutputParameters &outputParams)
Executes the algorithm using the supplied parameters.
Definition: Segmenter.cpp:217
unsigned int m_maxSegThreads
The maximum number of concurrent segmenter threads (default:0 - automatically found).
Definition: Segmenter.h:93
void reset()
Clear all internal allocated objects and reset the algorithm to its initial state.
Definition: Segmenter.cpp:796
#define TERP_DEBUG_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:356
A rectified grid is the spatial support for raster data.
Definition: Grid.h:68
const Segmenter::OutputParameters & operator=(const Segmenter::OutputParameters &params)
Definition: Segmenter.cpp:168
std::vector< double > m_inputRasterNoDataValues
A vector of values to be used as input raster no-data values or an empty vector indicating to use the...
Definition: Segmenter.h:89
std::vector< unsigned int > m_topCutOffProfile
virtual int getBlockSize() const
It returns the number of bytes ocuppied by a data block.
Definition: Band.cpp:630
SegmenterStrategyParameters const * getSegStrategyParams() const
Returns a pointer to the internal specific segmenter strategy parameters.
Definition: Segmenter.cpp:140
unsigned int getLinesNumber() const
The number of current matrix lines.
Definition: Matrix.h:671
unsigned int volatile * m_runningThreadsCounterPtr
Pointer to the running threads counter - default 0).
Definition: Segmenter.h:233
std::vector< unsigned int > m_inputRasterBands
Bands to be processed from the input raster.
Definition: Segmenter.h:87
#define TERP_TRUE_OR_THROW(value, message)
Checks if value is true and throws an exception if not.
Definition: Macros.h:149
Segmenter::InputParameters m_inputParameters
The global segmenter input execution parameters.
Definition: Segmenter.h:203
TECOMMONEXPORT unsigned long int GetTotalVirtualMemory()
Returns the amount of total virtual memory (bytes) that can be claimed by the current process (physic...
std::vector< unsigned int > m_leftCutOffProfile
bool m_enableBlockProcessing
If true, the original raster will be splitted into small blocks, each one will be segmented independe...
Definition: Segmenter.h:95
std::vector< unsigned int > m_bottomCutOffProfile