/*========================================================================= Program: Insight Segmentation & Registration Toolkit Module: $RCSfile: itkBinaryClosingByReconstructionImageFilter.txx,v $ Language: C++ Copyright (c) Insight Software Consortium. All rights reserved. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. 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 __itkBinaryClosingByReconstructionImageFilter_txx #define __itkBinaryClosingByReconstructionImageFilter_txx #include "itkBinaryClosingByReconstructionImageFilter.h" #include "itkBinaryReconstructionByErosionImageFilter.h" #include "itkBinaryDilateImageFilter.h" #include "itkProgressAccumulator.h" #include "itkCropImageFilter.h" #include "itkConstantPadImageFilter.h" #include "itkConstNeighborhoodIterator.h" #include "itkNeighborhoodIterator.h" #include "itkProgressReporter.h" namespace itk { template BinaryClosingByReconstructionImageFilter ::BinaryClosingByReconstructionImageFilter() : m_Kernel() { m_ForegroundValue = NumericTraits::max(); m_FullyConnected = false; } template void BinaryClosingByReconstructionImageFilter ::GenerateInputRequestedRegion() { // call the superclass' implementation of this method Superclass::GenerateInputRequestedRegion(); // We need all the input. InputImagePointer input = const_cast(this->GetInput()); if( input ) { input->SetRequestedRegion( input->GetLargestPossibleRegion() ); } } template void BinaryClosingByReconstructionImageFilter ::GenerateData() { // Allocate the outputs this->AllocateOutputs(); // let choose a background value. Background value should not be given by user // because closing is extensive so no background pixels will be added // it is just needed for internal erosion filter and constant padder InputPixelType backgroundValue = NumericTraits::Zero; if ( m_ForegroundValue == backgroundValue ) { // current background value is already used for foreground value // choose another one backgroundValue = NumericTraits::max(); } /** set up erosion and dilation methods */ typename BinaryDilateImageFilter::Pointer dilate = BinaryDilateImageFilter::New(); typename BinaryReconstructionByErosionImageFilter::Pointer erode = BinaryReconstructionByErosionImageFilter::New(); // create the pipeline without input and output image dilate->ReleaseDataFlagOn(); dilate->SetKernel( this->GetKernel() ); dilate->SetDilateValue( m_ForegroundValue ); dilate->SetBackgroundValue( backgroundValue ); dilate->SetInput( this->GetInput() ); dilate->SetNumberOfThreads( this->GetNumberOfThreads() ); erode->ReleaseDataFlagOn(); erode->SetForegroundValue( m_ForegroundValue ); erode->SetBackgroundValue( backgroundValue ); erode->SetMarkerImage( dilate->GetOutput() ); erode->SetFullyConnected( m_FullyConnected ); erode->SetMaskImage( this->GetInput() ); erode->SetNumberOfThreads( this->GetNumberOfThreads() ); /** set up the minipipeline */ ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); progress->SetMiniPipelineFilter(this); progress->RegisterInternalFilter(erode, .8f); progress->RegisterInternalFilter(dilate, .2f); /** execute the minipipeline */ erode->GraftOutput( this->GetOutput() ); erode->Update(); this->GraftOutput( erode->GetOutput() ); } template void BinaryClosingByReconstructionImageFilter ::PrintSelf(std::ostream &os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Kernel: " << m_Kernel << std::endl; os << indent << "ForegroundValue: " << static_cast::PrintType>(m_ForegroundValue) << std::endl; os << indent << "FullyConnected: " << m_FullyConnected << std::endl; } }// end namespace itk #endif