/*========================================================================= Copyright (c) Remi Cresson (IRSTEA). All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MODULES_REMOTE_SIMPLEEXTRACTIONTOOLS_INCLUDE_OTBCACHELESSLABELIMAGETOVECTORDATA_txx_ #define MODULES_REMOTE_SIMPLEEXTRACTIONTOOLS_INCLUDE_OTBCACHELESSLABELIMAGETOVECTORDATA_txx_ #include "otbCacheLessLabelImageToVectorData.h" #include "itkObjectFactoryBase.h" #include "itkImageRegionMultidimensionalSplitter.h" #include "itkImageRegionIterator.h" #include "otbNumberOfDivisionsStrippedStreamingManager.h" #include "otbNumberOfDivisionsTiledStreamingManager.h" #include "otbNumberOfLinesStrippedStreamingManager.h" #include "otbRAMDrivenStrippedStreamingManager.h" #include "otbTileDimensionTiledStreamingManager.h" #include "otbRAMDrivenTiledStreamingManager.h" #include "otbRAMDrivenAdaptativeStreamingManager.h" namespace otb { /** * */ template <class TInputImagePixel> CacheLessLabelImageToVectorData<TInputImagePixel> ::CacheLessLabelImageToVectorData() : m_NumberOfDivisions(0), m_CurrentDivision(0), m_DivisionProgress(0.0), m_IsObserving(true), m_ObserverID(0) { // By default, we use tiled streaming, with automatic tile size // We don't set any parameter, so the memory size is retrieved from the OTB configuration options this->SetAutomaticAdaptativeStreaming(); } /** * */ template <class TInputImagePixel> CacheLessLabelImageToVectorData<TInputImagePixel> ::~CacheLessLabelImageToVectorData() { } template <class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetNumberOfDivisionsStrippedStreaming(unsigned int nbDivisions) { typedef NumberOfDivisionsStrippedStreamingManager<InputImageType> NumberOfDivisionsStrippedStreamingManagerType; typename NumberOfDivisionsStrippedStreamingManagerType::Pointer streamingManager = NumberOfDivisionsStrippedStreamingManagerType::New(); streamingManager->SetNumberOfDivisions(nbDivisions); m_StreamingManager = streamingManager; } template <class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetNumberOfDivisionsTiledStreaming(unsigned int nbDivisions) { typedef NumberOfDivisionsTiledStreamingManager<InputImageType> NumberOfDivisionsTiledStreamingManagerType; typename NumberOfDivisionsTiledStreamingManagerType::Pointer streamingManager = NumberOfDivisionsTiledStreamingManagerType::New(); streamingManager->SetNumberOfDivisions(nbDivisions); m_StreamingManager = streamingManager; } template <class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetNumberOfLinesStrippedStreaming(unsigned int nbLinesPerStrip) { typedef NumberOfLinesStrippedStreamingManager<InputImageType> NumberOfLinesStrippedStreamingManagerType; typename NumberOfLinesStrippedStreamingManagerType::Pointer streamingManager = NumberOfLinesStrippedStreamingManagerType::New(); streamingManager->SetNumberOfLinesPerStrip(nbLinesPerStrip); m_StreamingManager = streamingManager; } template <class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetAutomaticStrippedStreaming(unsigned int availableRAM, double bias) { typedef RAMDrivenStrippedStreamingManager<InputImageType> RAMDrivenStrippedStreamingManagerType; typename RAMDrivenStrippedStreamingManagerType::Pointer streamingManager = RAMDrivenStrippedStreamingManagerType::New(); streamingManager->SetAvailableRAMInMB(availableRAM); streamingManager->SetBias(bias); m_StreamingManager = streamingManager; } template <class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetTileDimensionTiledStreaming(unsigned int tileDimension) { typedef TileDimensionTiledStreamingManager<InputImageType> TileDimensionTiledStreamingManagerType; typename TileDimensionTiledStreamingManagerType::Pointer streamingManager = TileDimensionTiledStreamingManagerType::New(); streamingManager->SetTileDimension(tileDimension); m_StreamingManager = streamingManager; } template <class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetAutomaticTiledStreaming(unsigned int availableRAM, double bias) { typedef RAMDrivenTiledStreamingManager<InputImageType> RAMDrivenTiledStreamingManagerType; typename RAMDrivenTiledStreamingManagerType::Pointer streamingManager = RAMDrivenTiledStreamingManagerType::New(); streamingManager->SetAvailableRAMInMB(availableRAM); streamingManager->SetBias(bias); m_StreamingManager = streamingManager; } template <class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetAutomaticAdaptativeStreaming(unsigned int availableRAM, double bias) { typedef RAMDrivenAdaptativeStreamingManager<InputImageType> RAMDrivenAdaptativeStreamingManagerType; typename RAMDrivenAdaptativeStreamingManagerType::Pointer streamingManager = RAMDrivenAdaptativeStreamingManagerType::New(); streamingManager->SetAvailableRAMInMB(availableRAM); streamingManager->SetBias(bias); m_StreamingManager = streamingManager; } template<class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::SetInput(const InputImageType* input) { this->ProcessObject::SetNthInput(0,const_cast<InputImageType*>(input)); } template<class TInputImagePixel> const typename CacheLessLabelImageToVectorData<TInputImagePixel>::InputImageType* CacheLessLabelImageToVectorData<TInputImagePixel> ::GetInput() { if (this->GetNumberOfInputs() < 1) { return ITK_NULLPTR; } return static_cast<const InputImageType*>(this->ProcessObject::GetInput(0)); } /** * Update method : update output information of input and write to file */ template<class TInputImagePixel> void CacheLessLabelImageToVectorData<TInputImagePixel> ::Update() { // Update output information on input image InputImagePointer inputPtr = const_cast<InputImageType *>(this->GetInput()); // Make sure input is available if ( inputPtr.IsNull() ) { itkExceptionMacro(<< "No input to writer"); } this->SetAbortGenerateData(0); this->SetProgress(0.0); /** * Tell all Observers that the filter is starting */ this->InvokeEvent(itk::StartEvent()); /** * Grab the input */ inputPtr->UpdateOutputInformation(); InputImageRegionType inputRegion = inputPtr->GetLargestPossibleRegion(); // Allocate the buffer image bufferedInputImage = InputImageType::New(); bufferedInputImage->SetRegions(inputRegion); bufferedInputImage->Allocate(); bufferedInputImage->SetMetaDataDictionary(inputPtr->GetMetaDataDictionary()); bufferedInputImage->SetSpacing(inputPtr->GetSignedSpacing()); bufferedInputImage->SetOrigin (inputPtr->GetOrigin() ); /** Compare the buffered region with the inputRegion which is the largest * possible region or a user defined region through extended filename * Not sure that if this modification is needed */ if (inputPtr->GetBufferedRegion() == inputRegion) { otbMsgDevMacro(<< "Buffered region is the largest possible region, there is no need for streaming."); this->SetNumberOfDivisionsStrippedStreaming(1); } m_StreamingManager->PrepareStreaming(inputPtr, inputRegion); m_NumberOfDivisions = m_StreamingManager->GetNumberOfSplits(); otbMsgDebugMacro(<< "Number Of Stream Divisions : " << m_NumberOfDivisions); /** * Loop over the number of pieces, execute the upstream pipeline on each * piece, and copy the results into the output image. */ InputImageRegionType streamRegion; this->UpdateProgress(0); m_CurrentDivision = 0; m_DivisionProgress = 0; // Get the source process object itk::ProcessObject* source = inputPtr->GetSource(); m_IsObserving = false; m_ObserverID = 0; // Check if source exists if(source) { typedef itk::MemberCommand<Self> CommandType; typedef typename CommandType::Pointer CommandPointerType; CommandPointerType command = CommandType::New(); command->SetCallbackFunction(this, &Self::ObserveSourceFilterProgress); m_ObserverID = source->AddObserver(itk::ProgressEvent(), command); m_IsObserving = true; } else { itkWarningMacro(<< "Could not get the source process object. Progress report might be buggy"); } for (m_CurrentDivision = 0; m_CurrentDivision < m_NumberOfDivisions && !this->GetAbortGenerateData(); m_CurrentDivision++, m_DivisionProgress = 0, this->UpdateFilterProgress()) { streamRegion = m_StreamingManager->GetSplit(m_CurrentDivision); inputPtr->SetRequestedRegion(streamRegion); inputPtr->PropagateRequestedRegion(); inputPtr->UpdateOutputData(); // Copy output in buffer ConstIteratorType inIt(inputPtr, streamRegion); IteratorType outIt(bufferedInputImage, streamRegion); for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd(); ++outIt, ++inIt) { outIt.Set(inIt.Get()); } } // Vectorize the buffered image vectorizeFilter = LabelImageToVectorDataFilterType::New(); vectorizeFilter->SetInput(bufferedInputImage); vectorizeFilter->SetInputMask(bufferedInputImage); vectorizeFilter->Update(); this->GraftOutput( vectorizeFilter->GetOutput() ); /** * If we ended due to aborting, push the progress up to 1.0 (since * it probably didn't end there) */ if (!this->GetAbortGenerateData()) { this->UpdateProgress(1.0); } // Notify end event observers this->InvokeEvent(itk::EndEvent()); if (m_IsObserving) { m_IsObserving = false; source->RemoveObserver(m_ObserverID); } /** * Release any inputs if marked for release */ this->ReleaseInputs(); } } // end namespace otb #endif