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