diff --git a/include/itkBoxSpatialObjectToVTKPolyDataFilter.hxx b/include/itkBoxSpatialObjectToVTKPolyDataFilter.hxx index a4d3cd6..e4d9fb7 100644 --- a/include/itkBoxSpatialObjectToVTKPolyDataFilter.hxx +++ b/include/itkBoxSpatialObjectToVTKPolyDataFilter.hxx @@ -83,13 +83,13 @@ BoxSpatialObjectToVTKPolyDataFilter { switch (dim) { case 0: - cubeSource->SetXLength(spatialObject->GetSize()[0]); + cubeSource->SetXLength(spatialObject->GetSizeInObjectSpace()[0]); break; case 1: - cubeSource->SetYLength(spatialObject->GetSize()[1]); + cubeSource->SetYLength(spatialObject->GetSizeInObjectSpace()[1]); break; case 2: - cubeSource->SetZLength(spatialObject->GetSize()[2]); + cubeSource->SetZLength(spatialObject->GetSizeInObjectSpace()[2]); break; default: itkExceptionMacro("Unsupported dimension for SpatialObject conversion."); diff --git a/include/itkImageToRGBVTKImageFilter.h b/include/itkImageToRGBVTKImageFilter.h new file mode 100644 index 0000000..17624aa --- /dev/null +++ b/include/itkImageToRGBVTKImageFilter.h @@ -0,0 +1,85 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkImageToRGBVTKImageFilter_h +#define itkImageToRGBVTKImageFilter_h + +#include "itkProcessObject.h" +#include "vtkSmartPointer.h" +#include "vtkImageData.h" + +namespace itk +{ +/** \class ImageToRGBVTKImageFilter + * \brief Converts an ITK image into a VTK image. + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputImage > +class ITK_TEMPLATE_EXPORT ImageToRGBVTKImageFilter:public ProcessObject +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(ImageToRGBVTKImageFilter); + + /** Standard class type aliases. */ + using Self = ImageToRGBVTKImageFilter; + using Superclass = ProcessObject; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ImageToRGBVTKImageFilter, ProcessObject); + + /** Some type alias. */ + using InputImageType = TInputImage; + using InputImagePointer = typename InputImageType::ConstPointer; + using InputRegionType = typename InputImageType::RegionType; + using InputSpacingType = typename InputImageType::SpacingType; + using InputSizeType = typename InputImageType::SizeType; + using InputPixelType = typename InputImageType::PixelType; + using InputIndexType = typename InputImageType::IndexType; + + /** Get the output in the form of a vtkImage. + This call is delegated to the internal vtkImageImporter filter */ + vtkSmartPointer< vtkImageData > GetOutput() const; + + /** Set the input in the form of an itk::Image */ + using Superclass::SetInput; + void SetInput(const InputImageType *); + + /** This call delegate the update to the importer */ + void Update() override; + +protected: + ImageToRGBVTKImageFilter(); + ~ImageToRGBVTKImageFilter() override; + +private: + InputImagePointer m_Input; + vtkSmartPointer< vtkImageData > m_Output; +}; +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkImageToRGBVTKImageFilter.hxx" +#endif + +#endif diff --git a/include/itkImageToRGBVTKImageFilter.hxx b/include/itkImageToRGBVTKImageFilter.hxx new file mode 100644 index 0000000..4209e2f --- /dev/null +++ b/include/itkImageToRGBVTKImageFilter.hxx @@ -0,0 +1,149 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkImageToRGBVTKImageFilter_hxx +#define itkImageToRGBVTKImageFilter_hxx + +#include "vtkVersion.h" + +#include "itkImageToRGBVTKImageFilter.h" + +namespace itk +{ +/** + * Constructor + */ +template< typename TInputImage > +ImageToRGBVTKImageFilter< TInputImage > +::ImageToRGBVTKImageFilter() +{ + m_Output = vtkSmartPointer< vtkImageData >::New(); +} + +/** + * Destructor + */ +template< typename TInputImage > +ImageToRGBVTKImageFilter< TInputImage > +::~ImageToRGBVTKImageFilter() +{} + +/** + * Set an itk::Image as input + */ +template< typename TInputImage > +void +ImageToRGBVTKImageFilter< TInputImage > +::SetInput(const InputImageType *inputImage) +{ + m_Input = inputImage; + this->Modified(); +} + +/** + * Get a vtkImage as output + */ +template< typename TInputImage > +vtkSmartPointer< vtkImageData > +ImageToRGBVTKImageFilter< TInputImage > +::GetOutput() const +{ + return m_Output; +} + +/** + * Delegate the Update to the importer + */ +template< typename TInputImage > +void +ImageToRGBVTKImageFilter< TInputImage > +::Update() +{ + int dimension[3]; + dimension[0] = 0; + dimension[1] = 0; + dimension[2] = 0; + + double spacing[3]; + spacing[0] = 0.; + spacing[1] = 0.; + spacing[2] = 0.; + + InputRegionType region = m_Input->GetLargestPossibleRegion(); + InputSizeType itk_size = region.GetSize(); + + InputSpacingType itk_spacing = m_Input->GetSpacing(); + + for( unsigned int i = 0; i < TInputImage::ImageDimension; i++ ) + { + dimension[i] = static_cast< int >( itk_size[i] ); + spacing[i] = static_cast< double >( itk_spacing[i] ); + } + m_Output->SetDimensions( dimension ); + m_Output->SetSpacing( spacing ); + m_Output->SetExtent( 0, dimension[0], + 0, dimension[1], + 0, dimension[2] ); +#if VTK_MAJOR_VERSION <= 5 + m_Output->SetNumberOfScalarComponents( 3 ); + + // at first let's convert it to unsigned char + m_Output->SetScalarTypeToUnsignedChar(); + m_Output->AllocateScalars(); +#else + m_Output->AllocateScalars(VTK_UNSIGNED_CHAR,3); +#endif + //TODO: use itk iterators instead + for( int x = 0; x < dimension[0]; x++ ) + { + for( int y = 0; y < dimension[1]; y++ ) + { + if( TInputImage::ImageDimension == 3 ) + { + for( int z = 0; z < dimension[2]; z++ ) + { + auto * vtkpixel = static_cast(m_Output->GetScalarPointer(x,y,z)); + InputIndexType index; + index[0] = x; + index[1] = y; + index[2] = z; + + InputPixelType itkpixel = m_Input->GetPixel(index); + vtkpixel[0] = itkpixel; + vtkpixel[1] = itkpixel; + vtkpixel[2] = itkpixel; + } + } + else + { + auto * vtkpixel = static_cast(m_Output->GetScalarPointer(x,y,0)); + InputIndexType index; + index[0] = x; + index[1] = y; + + InputPixelType itkpixel = m_Input->GetPixel(index); + vtkpixel[0] = itkpixel; + vtkpixel[1] = itkpixel; + vtkpixel[2] = itkpixel; + } + } + } +} + +} // end namespace itk + +#endif diff --git a/include/itkLevelSetIterationUpdateCommand.h b/include/itkLevelSetIterationUpdateCommand.h new file mode 100644 index 0000000..285a85b --- /dev/null +++ b/include/itkLevelSetIterationUpdateCommand.h @@ -0,0 +1,84 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkLevelSetIterationUpdateCommand_h +#define itkLevelSetIterationUpdateCommand_h + +#include "itkCommand.h" +#include "itkWeakPointer.h" +#include "itkIntTypes.h" + +namespace itk +{ + +/** \class LevelSetIterationUpdateCommand + * \brief Call update on one filter when another filter iterates. + * + * \tparam TIteratingFilter Filter that invokes iteration events. + * \tparam TFilterToUpdate Filter to call update on when the iteration event + * occurs. + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TIteratingFilter, typename TFilterToUpdate > +class ITK_TEMPLATE_EXPORT LevelSetIterationUpdateCommand : public Command +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetIterationUpdateCommand); + + using Self = LevelSetIterationUpdateCommand; + using Superclass = Command; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + using IteratingFilterType = TIteratingFilter; + using FilterToUpdateType = TFilterToUpdate; + + /** Run-time type information (and related methods). */ + itkTypeMacro( LevelSetIterationUpdateCommand, Command ); + + itkNewMacro( Self ); + + void Execute( const Object* caller, const EventObject& event ) override; + + void Execute( Object* caller, const EventObject& event ) override; + + /** Set/Get the filter to call Update() on. */ + itkSetObjectMacro( FilterToUpdate, FilterToUpdateType ); + itkGetModifiableObjectMacro(FilterToUpdate, FilterToUpdateType ); + + /** Set/Get the period that Update() is called on the FilterToUpdate. It is + * in units of iterations. */ + itkSetMacro( UpdatePeriod, IdentifierType ); + itkGetConstMacro( UpdatePeriod, IdentifierType ); + +protected: + LevelSetIterationUpdateCommand(); + ~LevelSetIterationUpdateCommand() override; + +private: + WeakPointer< FilterToUpdateType > m_FilterToUpdate; + IdentifierType m_UpdatePeriod; +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLevelSetIterationUpdateCommand.hxx" +#endif + +#endif diff --git a/include/itkLevelSetIterationUpdateCommand.hxx b/include/itkLevelSetIterationUpdateCommand.hxx new file mode 100644 index 0000000..9cf4fc7 --- /dev/null +++ b/include/itkLevelSetIterationUpdateCommand.hxx @@ -0,0 +1,69 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkLevelSetIterationUpdateCommand_hxx +#define itkLevelSetIterationUpdateCommand_hxx + +#include "itkLevelSetIterationUpdateCommand.h" + +namespace itk +{ + +template< typename TIteratingFilter, typename TFilterToUpdate > +LevelSetIterationUpdateCommand< TIteratingFilter, TFilterToUpdate > +::LevelSetIterationUpdateCommand(): + m_UpdatePeriod( 1 ) +{ +} + +template< typename TIteratingFilter, typename TFilterToUpdate > +LevelSetIterationUpdateCommand< TIteratingFilter, TFilterToUpdate > +::~LevelSetIterationUpdateCommand() +{ +} + +template< typename TIteratingFilter, typename TFilterToUpdate > +void +LevelSetIterationUpdateCommand< TIteratingFilter, TFilterToUpdate > +::Execute( const Object* caller, const EventObject& event ) +{ + this->Execute( const_cast< Object* >( caller ), event ); +} + +template< typename TIteratingFilter, typename TFilterToUpdate > +void +LevelSetIterationUpdateCommand< TIteratingFilter, TFilterToUpdate > +::Execute( Object* caller, const EventObject& event ) +{ + auto * filter = dynamic_cast< IteratingFilterType * >( caller ); + + // Was filter->AddObserver() called correctly? + itkAssertInDebugAndIgnoreInReleaseMacro( filter != nullptr ); + + // If we have the right event. + if( IterationEvent().CheckEvent( &event ) && filter->GetNumberOfIterations() % this->m_UpdatePeriod == 0 ) + { + // Was the FilterToUpdate set? + itkAssertInDebugAndIgnoreInReleaseMacro( this->m_FilterToUpdate ); + this->m_FilterToUpdate->SetCurrentIteration( filter->GetNumberOfIterations() ); + this->m_FilterToUpdate->Update(); + } +} + +} // end namespace itk + +#endif diff --git a/include/itkLevelSetTovtkImageData.h b/include/itkLevelSetTovtkImageData.h new file mode 100644 index 0000000..ad1e814 --- /dev/null +++ b/include/itkLevelSetTovtkImageData.h @@ -0,0 +1,228 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkLevelSetTovtkImageData_h +#define itkLevelSetTovtkImageData_h + +#include "itkLevelSetTovtkImageDataBase.h" + +#include "itkLevelSetDenseImage.h" +#include "itkWhitakerSparseLevelSetImage.h" +#include "itkShiSparseLevelSetImage.h" +#include "itkMalcolmSparseLevelSetImage.h" + +#include "itkImage.h" +#include "itkImageToVTKImageFilter.h" +#include "itkImageRegionIteratorWithIndex.h" + +#include "itkLabelMapToLabelImageFilter.h" + +namespace itk +{ +template< typename TLevelSet > +class ITK_TEMPLATE_EXPORT LevelSetTovtkImageData + {}; + +/** \class LevelSetTovtkImageData + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TImage > +class ITK_TEMPLATE_EXPORT LevelSetTovtkImageData< LevelSetDenseImage< TImage > > : + public LevelSetTovtkImageDataBase< LevelSetDenseImage< TImage > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetTovtkImageData); + + using ImageType = TImage; + using LevelSetType = LevelSetDenseImage< ImageType >; + + using Self = LevelSetTovtkImageData; + using Superclass = LevelSetTovtkImageDataBase< LevelSetType >; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro( LevelSetTovtkImageData, LevelSetTovtkImageDataBase ); + + using LevelSetPointer = typename LevelSetType::Pointer; + + vtkImageData* GetOutput() const override; + +protected: + LevelSetTovtkImageData(); + ~LevelSetTovtkImageData() override; + + void GenerateData() override; + +private: + using ConverterType = ImageToVTKImageFilter< ImageType >; + using ConverterPointer = typename ConverterType::Pointer; + + ConverterPointer m_Converter; +}; + +// ----------------------------------------------------------------------------- +template< typename TOutput, unsigned int VDimension > +class ITK_TEMPLATE_EXPORT LevelSetTovtkImageData< WhitakerSparseLevelSetImage< TOutput, VDimension > > : + public LevelSetTovtkImageDataBase< WhitakerSparseLevelSetImage< TOutput, VDimension > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetTovtkImageData); + + using LevelSetType = WhitakerSparseLevelSetImage< TOutput, VDimension >; + + using Self = LevelSetTovtkImageData; + using Superclass = LevelSetTovtkImageDataBase< LevelSetType >; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro( LevelSetTovtkImageData, LevelSetTovtkImageDataBase ); + + using LevelSetPointer = typename LevelSetType::Pointer; + + vtkImageData* GetOutput() const override; + +protected: + LevelSetTovtkImageData(); + ~LevelSetTovtkImageData() override; + + void GenerateData() override; + +private: + using ImageType = Image< TOutput, VDimension >; + using ImagePointer = typename ImageType::Pointer; + + using ConverterType = ImageToVTKImageFilter< ImageType >; + using ConverterPointer = typename ConverterType::Pointer; + + ImagePointer m_InternalImage; + ConverterPointer m_Converter; +}; + + +// ----------------------------------------------------------------------------- +template< unsigned int VDimension > +class ITK_TEMPLATE_EXPORT LevelSetTovtkImageData< ShiSparseLevelSetImage< VDimension > > : + public LevelSetTovtkImageDataBase< ShiSparseLevelSetImage< VDimension > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetTovtkImageData); + + using LevelSetType = ShiSparseLevelSetImage< VDimension >; + + using Self = LevelSetTovtkImageData; + using Superclass = LevelSetTovtkImageDataBase< LevelSetType >; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro( LevelSetTovtkImageData, LevelSetTovtkImageDataBase ); + + using LevelSetPointer = typename LevelSetType::Pointer; + + vtkImageData* GetOutput() const override; + +protected: + LevelSetTovtkImageData(); + ~LevelSetTovtkImageData() override; + + void GenerateData() override; + +private: + using LabelMapType = typename LevelSetType::LabelMapType; + using LabelMapPointer = typename LevelSetType::LabelMapPointer; + using LabelMapConstPointer = typename LevelSetType::LabelMapConstPointer; + + using ImageType = Image< int8_t, VDimension >; + using ImagePointer = typename ImageType::Pointer; + + using LabelMapToLabelImageFilterType = LabelMapToLabelImageFilter< LabelMapType, ImageType >; + using LabelMapToLabelImageFilterPointer = typename LabelMapToLabelImageFilterType::Pointer; + + LabelMapToLabelImageFilterPointer m_LabelMapToLabelImageFilter; + + using ConverterType = ImageToVTKImageFilter< ImageType >; + using ConverterPointer = typename ConverterType::Pointer; + + ConverterPointer m_Converter; +}; + +// ----------------------------------------------------------------------------- +template< unsigned int VDimension > +class ITK_TEMPLATE_EXPORT LevelSetTovtkImageData< MalcolmSparseLevelSetImage< VDimension > > : + public LevelSetTovtkImageDataBase< MalcolmSparseLevelSetImage< VDimension > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetTovtkImageData); + + using LevelSetType = MalcolmSparseLevelSetImage< VDimension >; + + using Self = LevelSetTovtkImageData; + using Superclass = LevelSetTovtkImageDataBase< LevelSetType >; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro( LevelSetTovtkImageData, LevelSetTovtkImageDataBase ); + + using LevelSetPointer = typename LevelSetType::Pointer; + + vtkImageData* GetOutput() const override; + +protected: + LevelSetTovtkImageData(); + ~LevelSetTovtkImageData() override; + + void GenerateData() override; + +private: + using LabelMapType = typename LevelSetType::LabelMapType; + using LabelMapPointer = typename LevelSetType::LabelMapPointer; + + using ImageType = Image< int8_t, VDimension >; + using ImagePointer = typename ImageType::Pointer; + + using LabelMapToLabelImageFilterType = LabelMapToLabelImageFilter< LabelMapType, ImageType >; + using LabelMapToLabelImageFilterPointer = typename LabelMapToLabelImageFilterType::Pointer; + + LabelMapToLabelImageFilterPointer m_LabelMapToLabelImageFilter; + + using ConverterType = ImageToVTKImageFilter< ImageType >; + using ConverterPointer = typename ConverterType::Pointer; + + ConverterPointer m_Converter; +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLevelSetTovtkImageData.hxx" +#endif +#endif // itkLevelSetTovtkImageData_h diff --git a/include/itkLevelSetTovtkImageData.hxx b/include/itkLevelSetTovtkImageData.hxx new file mode 100644 index 0000000..e1f7d2d --- /dev/null +++ b/include/itkLevelSetTovtkImageData.hxx @@ -0,0 +1,217 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkLevelSetTovtkImageData_hxx +#define itkLevelSetTovtkImageData_hxx + +#include "itkLevelSetTovtkImageData.h" + +#include "itkLevelSetDenseImage.h" +#include "itkWhitakerSparseLevelSetImage.h" +#include "itkShiSparseLevelSetImage.h" +#include "itkMalcolmSparseLevelSetImage.h" + +#include "itkImage.h" +#include "itkImageToVTKImageFilter.h" +#include "itkImageRegionIteratorWithIndex.h" + +#include "itkLabelMapToLabelImageFilter.h" + +namespace itk +{ +template< typename TImage > +LevelSetTovtkImageData< LevelSetDenseImage< TImage > > +::LevelSetTovtkImageData() +{ + this->m_Converter = ConverterType::New(); +} + +template< typename TImage > +LevelSetTovtkImageData< LevelSetDenseImage< TImage > > +::~LevelSetTovtkImageData() +{} + +template< typename TImage > +vtkImageData* +LevelSetTovtkImageData< LevelSetDenseImage< TImage > > +::GetOutput() const + { + return this->m_Converter->GetOutput(); + } + +template< typename TImage > +void +LevelSetTovtkImageData< LevelSetDenseImage< TImage > > +::GenerateData() + { + if( !this->m_LevelSet->GetImage() ) + { + itkGenericExceptionMacro( <<"this->m_LevelSet->GetImage() is nullptr" ); + } + this->m_Converter->SetInput( this->m_LevelSet->GetImage() ); + this->m_Converter->Update(); + } + +// ----------------------------------------------------------------------------- +template< typename TOutput, unsigned int VDimension > +LevelSetTovtkImageData< WhitakerSparseLevelSetImage< TOutput, VDimension > > +::LevelSetTovtkImageData() +{ + m_InternalImage = ImageType::New(); + m_Converter = ConverterType::New(); +} + +template< typename TOutput, unsigned int VDimension > +LevelSetTovtkImageData< WhitakerSparseLevelSetImage< TOutput, VDimension > > +::~LevelSetTovtkImageData() +{} + +template< typename TOutput, unsigned int VDimension > +vtkImageData* +LevelSetTovtkImageData< WhitakerSparseLevelSetImage< TOutput, VDimension > > +::GetOutput() const + { + return m_Converter->GetOutput(); + } + +template< typename TOutput, unsigned int VDimension > +void +LevelSetTovtkImageData< WhitakerSparseLevelSetImage< TOutput, VDimension > > +::GenerateData() + { + if( this->m_LevelSet->GetLabelMap() == nullptr ) + { + itkGenericExceptionMacro( <<"this->m_LevelSet->GetLabelMap() is nullptr" ); + } + + typename LevelSetType::LabelMapConstPointer labelmap = this->m_LevelSet->GetLabelMap(); + + this->m_InternalImage->SetRegions( labelmap->GetLargestPossibleRegion() ); + this->m_InternalImage->SetSpacing( labelmap->GetSpacing() ); + this->m_InternalImage->SetOrigin( labelmap->GetOrigin() ); + this->m_InternalImage->SetDirection( labelmap->GetDirection() ); + this->m_InternalImage->SetNumberOfComponentsPerPixel( 1 ); + this->m_InternalImage->Allocate(); + + using IteratorType = ImageRegionIteratorWithIndex< ImageType >; + + IteratorType it( this->m_InternalImage, this->m_InternalImage->GetLargestPossibleRegion() ); + it.GoToBegin(); + + typename ImageType::IndexType idx; + + while( !it.IsAtEnd() ) + { + idx = it.GetIndex(); + it.Set( this->m_LevelSet->Evaluate( idx ) ); + ++it; + } + + this->m_Converter->SetInput( this->m_InternalImage ); + this->m_Converter->Update(); + } + + +// ----------------------------------------------------------------------------- +template< unsigned int VDimension > +LevelSetTovtkImageData< ShiSparseLevelSetImage< VDimension > > +::LevelSetTovtkImageData() +{ + m_LabelMapToLabelImageFilter = LabelMapToLabelImageFilterType::New(); + m_Converter = ConverterType::New(); +} + +template< unsigned int VDimension > +LevelSetTovtkImageData< ShiSparseLevelSetImage< VDimension > > +::~LevelSetTovtkImageData() + {} + +template< unsigned int VDimension > +vtkImageData* +LevelSetTovtkImageData< ShiSparseLevelSetImage< VDimension > > +::GetOutput() const + { + return this->m_Converter->GetOutput(); + } + +template< unsigned int VDimension > +void +LevelSetTovtkImageData< ShiSparseLevelSetImage< VDimension > > +::GenerateData() + { + if( this->m_LevelSet->GetLabelMap() == nullptr ) + { + itkGenericExceptionMacro( <<"this->m_LevelSet->GetLabelMap() is nullptr" ); + } + + LabelMapPointer labelmap = this->m_LevelSet->GetModifiableLabelMap(); + + this->m_LabelMapToLabelImageFilter->SetInput( labelmap ); + this->m_LabelMapToLabelImageFilter->Modified(); + this->m_LabelMapToLabelImageFilter->Update(); + + this->m_Converter->SetInput( m_LabelMapToLabelImageFilter->GetOutput() ); + this->m_Converter->Modified(); + this->m_Converter->Update(); + } + +// ----------------------------------------------------------------------------- +template< unsigned int VDimension > +LevelSetTovtkImageData< MalcolmSparseLevelSetImage< VDimension > > +::LevelSetTovtkImageData() + { + m_LabelMapToLabelImageFilter = LabelMapToLabelImageFilterType::New(); + m_Converter = ConverterType::New(); + } + +template< unsigned int VDimension > +LevelSetTovtkImageData< MalcolmSparseLevelSetImage< VDimension > > +::~LevelSetTovtkImageData() + {} + +template< unsigned int VDimension > +vtkImageData* +LevelSetTovtkImageData< MalcolmSparseLevelSetImage< VDimension > > +::GetOutput() const + { + return this->m_Converter->GetOutput(); + } + +template< unsigned int VDimension > +void +LevelSetTovtkImageData< MalcolmSparseLevelSetImage< VDimension > > +::GenerateData() + { + if( this->m_LevelSet->GetLabelMap() == nullptr ) + { + itkGenericExceptionMacro( <<"this->m_LevelSet->GetLabelMap() is nullptr" ); + } + + LabelMapPointer labelmap = this->m_LevelSet->GetModifiableLabelMap(); + + this->m_LabelMapToLabelImageFilter->SetInput( labelmap ); + this->m_LabelMapToLabelImageFilter->Modified(); + this->m_LabelMapToLabelImageFilter->Update(); + + this->m_Converter->SetInput( m_LabelMapToLabelImageFilter->GetOutput() ); + this->m_Converter->Modified(); + this->m_Converter->Update(); + } +} + +#endif // itkLevelSetTovtkImageData_h diff --git a/include/itkLevelSetTovtkImageDataBase.h b/include/itkLevelSetTovtkImageDataBase.h new file mode 100644 index 0000000..c71f604 --- /dev/null +++ b/include/itkLevelSetTovtkImageDataBase.h @@ -0,0 +1,66 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkLevelSetTovtkImageDataBase_h +#define itkLevelSetTovtkImageDataBase_h + +#include "itkProcessObject.h" + +class vtkImageData; + +namespace itk +{ +/** \class LevelSetTovtkImageDataBase + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TLevelSet > +class ITK_TEMPLATE_EXPORT LevelSetTovtkImageDataBase : public ProcessObject +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetTovtkImageDataBase); + + using Self = LevelSetTovtkImageDataBase; + using Superclass = ProcessObject; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Run-time type information (and related methods). */ + itkTypeMacro(LevelSetTovtkImageDataBase, ProcessObject); + + using LevelSetType = TLevelSet; + using LevelSetPointer = typename LevelSetType::Pointer; + + using Superclass::SetInput; + virtual void SetInput( LevelSetType* iLevelSet ); + + virtual vtkImageData* GetOutput() const = 0; + + void Update() override; + +protected: + LevelSetTovtkImageDataBase(); + ~LevelSetTovtkImageDataBase() override; + + LevelSetPointer m_LevelSet; +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLevelSetTovtkImageDataBase.hxx" +#endif +#endif // itkLevelSetTovtkImageDataBase_h diff --git a/include/itkLevelSetTovtkImageDataBase.hxx b/include/itkLevelSetTovtkImageDataBase.hxx new file mode 100644 index 0000000..e6dead6 --- /dev/null +++ b/include/itkLevelSetTovtkImageDataBase.hxx @@ -0,0 +1,58 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkLevelSetTovtkImageDataBase_hxx +#define itkLevelSetTovtkImageDataBase_hxx + +#include "itkLevelSetTovtkImageDataBase.h" + +namespace itk +{ +template< typename TLevelSet > +LevelSetTovtkImageDataBase< TLevelSet > +::LevelSetTovtkImageDataBase() + {} + +template< typename TLevelSet > +LevelSetTovtkImageDataBase< TLevelSet > +::~LevelSetTovtkImageDataBase() + {} + +template< typename TLevelSet > +void +LevelSetTovtkImageDataBase< TLevelSet > +::SetInput( LevelSetType* iLevelSet ) +{ + if( !iLevelSet ) + { + itkGenericExceptionMacro( <<"iLevelSet is nullptr" ); + } + m_LevelSet = iLevelSet; +} + +template< typename TLevelSet > +void +LevelSetTovtkImageDataBase< TLevelSet > +::Update() +{ + this->GenerateData(); +} + +} + +#endif // itkLevelSetTovtkImageDataBase_h diff --git a/include/itkVTKVisualize2DLevelSetAsElevationMap.h b/include/itkVTKVisualize2DLevelSetAsElevationMap.h new file mode 100644 index 0000000..bd5ee74 --- /dev/null +++ b/include/itkVTKVisualize2DLevelSetAsElevationMap.h @@ -0,0 +1,116 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkVTKVisualize2DLevelSetAsElevationMap_h +#define itkVTKVisualize2DLevelSetAsElevationMap_h + +#include "itkVTKVisualizeImageLevelSet.h" + +#include "itkImageToVTKImageFilter.h" +#include "itkConceptChecking.h" + +#include "vtkPolyData.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkScalarBarActor.h" + +namespace itk +{ + +template< typename TInputImage, typename TLevelSet > +class ITK_TEMPLATE_EXPORT VTKVisualize2DLevelSetAsElevationMap : + public VTKVisualizeImageLevelSet< TInputImage, ImageToVTKImageFilter< TInputImage > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualize2DLevelSetAsElevationMap); + + using Self = VTKVisualize2DLevelSetAsElevationMap; + using Superclass = VTKVisualizeImageLevelSet< TInputImage, ImageToVTKImageFilter< TInputImage > >; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + itkNewMacro( Self ); + + /** Run-time type information (and related methods). */ + itkTypeMacro(itkVTKVisualize2DLevelSetAsElevationMap, VTKVisualizeImageLevelSet); + + using InputImageType = typename Superclass::InputImageType; + using InputImageSizeType = typename InputImageType::SizeType; + using InputImageSizeValueType = typename InputImageType::SizeValueType; + + using LevelSetType = TLevelSet; + using LevelSetPointer = typename LevelSetType::Pointer; + + void SetLevelSet( LevelSetType * levelSet ); + +#ifdef ITK_USE_CONCEPT_CHECKING + itkConceptMacro( Is2Dimensional, + ( Concept::SameDimension< LevelSetType::Dimension, 2 > ) ); +#endif + + /* Set the height scaling for visualization */ + void SetHeightScaling( const double c ) + { + m_HeightScaling = c; + } + + /* Get the height scaling for visualization */ + double GetHeightScaling() const + { + return m_HeightScaling; + } + + /* Get the surface mesh*/ + vtkPolyData* GetElevationMapMesh() const + { + return m_Mesh; + } + +protected: + VTKVisualize2DLevelSetAsElevationMap(); + ~VTKVisualize2DLevelSetAsElevationMap() override; + + void PrepareVTKPipeline() override; + + void GenerateElevationMap(); + +private: + LevelSetPointer m_LevelSet; + + vtkSmartPointer< vtkPolyData > m_Mesh; + vtkSmartPointer< vtkScalarBarActor > m_ScalarBarActor; + vtkSmartPointer< vtkPolyDataMapper > m_MeshMapper; + vtkSmartPointer< vtkActor > m_SurfaceActor; + + InputImageSizeType m_NumberOfSamples; + + double m_HeightScaling; + double m_MinValue; + double m_MaxValue; + + bool m_ColorValue; + +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVTKVisualize2DLevelSetAsElevationMap.hxx" +#endif + +#endif // itkVTKVisualize2DLevelSetAsElevationMap_H diff --git a/include/itkVTKVisualize2DLevelSetAsElevationMap.hxx b/include/itkVTKVisualize2DLevelSetAsElevationMap.hxx new file mode 100644 index 0000000..9a789b3 --- /dev/null +++ b/include/itkVTKVisualize2DLevelSetAsElevationMap.hxx @@ -0,0 +1,226 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkVTKVisualize2DLevelSetAsElevationMap_hxx +#define itkVTKVisualize2DLevelSetAsElevationMap_hxx + +#include "itkVTKVisualize2DLevelSetAsElevationMap.h" + +#include "itkMath.h" + +#include "vtkVersion.h" + +#include "vtkScalarsToColors.h" +#include "vtkDoubleArray.h" +#include "vtkPointData.h" +#include "vtkCellArray.h" +#include "vtkProperty.h" +#include "vtkTextProperty.h" + +namespace itk +{ + +template< typename TInputImage, typename TLevelSet > +VTKVisualize2DLevelSetAsElevationMap< TInputImage, TLevelSet > +::VTKVisualize2DLevelSetAsElevationMap() +{ + this->m_ColorValue = true; + this->m_MinValue = itk::NumericTraits< double >::max( ); + this->m_MaxValue = itk::NumericTraits< double >::min( ); + this->m_HeightScaling = 0.1; + + this->m_Mesh = vtkSmartPointer< vtkPolyData >::New(); + + this->m_ScalarBarActor = vtkSmartPointer< vtkScalarBarActor >::New(); + this->m_ScalarBarActor->SetTitle( "Level Set" ); + this->m_ScalarBarActor->GetPositionCoordinate( )->SetCoordinateSystemToNormalizedViewport( ); + this->m_ScalarBarActor->GetPositionCoordinate( )->SetValue( 0.1, 0.01 ); + this->m_ScalarBarActor->GetTitleTextProperty( )->SetColor( 0., 0., 0. ); + this->m_ScalarBarActor->GetLabelTextProperty( )->SetColor( 0., 0., 0. ); + this->m_ScalarBarActor->SetOrientationToHorizontal( ); + this->m_ScalarBarActor->SetWidth( 0.8 ); + this->m_ScalarBarActor->SetHeight( 0.17 ); + this->m_Renderer->AddActor2D( this->m_ScalarBarActor ); + + this->m_MeshMapper = vtkSmartPointer< vtkPolyDataMapper >::New(); +#if VTK_MAJOR_VERSION <= 5 + this->m_MeshMapper->SetInput( this->m_Mesh ); +#else + this->m_MeshMapper->SetInputData( this->m_Mesh ); +#endif + this->m_SurfaceActor = vtkSmartPointer< vtkActor >::New(); + this->m_SurfaceActor->SetMapper( this->m_MeshMapper ); + this->m_SurfaceActor->GetProperty( )->SetColor( 0.7, 0.7, 0.7 ); + this->m_Renderer->AddActor( this->m_SurfaceActor ); +} + +template< typename TInputImage, typename TLevelSet > +VTKVisualize2DLevelSetAsElevationMap< TInputImage, TLevelSet > +::~VTKVisualize2DLevelSetAsElevationMap() +{ +} + +template< typename TInputImage, typename TLevelSet > +void +VTKVisualize2DLevelSetAsElevationMap< TInputImage, TLevelSet > +::SetLevelSet( LevelSetType * levelSet ) +{ + this->m_LevelSet = levelSet; +} + +template< typename TInputImage, typename TLevelSet > +void +VTKVisualize2DLevelSetAsElevationMap< TInputImage, TLevelSet > +::PrepareVTKPipeline() +{ + this->GenerateElevationMap(); + + if( !this->m_ColorValue ) + { + this->m_MeshMapper->ScalarVisibilityOff( ); + } + else + { + this->m_MeshMapper->ScalarVisibilityOn( ); + this->m_MeshMapper->SetScalarRange( this->m_MinValue, this->m_MaxValue ); + vtkScalarsToColors * lookupTable = this->m_MeshMapper->GetLookupTable(); + lookupTable->SetRange( this->m_MinValue, this->m_MaxValue ); + lookupTable->Build(); + + this->m_ScalarBarActor->SetLookupTable( lookupTable ); + } +} + +template< typename TInputImage, typename TLevelSet > +void +VTKVisualize2DLevelSetAsElevationMap< TInputImage, TLevelSet > +::GenerateElevationMap() +{ + typename InputImageType::ConstPointer inputImage = this->m_InputImageConverter->GetInput(); + typename InputImageType::RegionType region = inputImage->GetLargestPossibleRegion(); + + using IndexType = typename InputImageType::IndexType; + using PointType = typename InputImageType::PointType; + + IndexType start = region.GetIndex(); + PointType itkPoint; + PointType itkPoint2; + + InputImageSizeType size = region.GetSize(); + + this->m_NumberOfSamples[0] = size[0] / 2; + this->m_NumberOfSamples[1] = size[1] / 2; + + IndexType dx; + dx[0] = static_cast< IndexValueType >( size[0] / this->m_NumberOfSamples[0] ); + dx[1] = static_cast< IndexValueType >( size[1] / this->m_NumberOfSamples[1] ); + + vtkSmartPointer< vtkPoints > vtkpoints = vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkDoubleArray > vtkpointdata = vtkSmartPointer< vtkDoubleArray >::New( ); + vtkSmartPointer< vtkCellArray > cells = vtkSmartPointer< vtkCellArray >::New( ); + + this->m_Mesh->SetPoints( vtkpoints ); + this->m_Mesh->GetPointData( )->SetScalars( vtkpointdata ); + this->m_Mesh->SetPolys( cells ); + + this->m_MinValue = itk::NumericTraits< double >::max( ); + this->m_MaxValue = itk::NumericTraits< double >::min( ); + + InputImageSizeValueType k = 0; + + IndexType index; + double p[3]; + + for( InputImageSizeValueType i = 0; i < this->m_NumberOfSamples[0]; i++ ) + { + index[0] = start[0] + i * dx[0]; + + for( InputImageSizeValueType j = 0; j < this->m_NumberOfSamples[1]; j++ ) + { + index[1] = start[1] + j * dx[1]; + + inputImage->TransformIndexToPhysicalPoint( index, itkPoint ); + + p[0] = itkPoint[0]; + p[1] = itkPoint[1]; + p[2] = static_cast< double >( this->m_LevelSet->Evaluate( index ) ); + + vtkpointdata->InsertNextTuple1( p[2] ); + + if( p[2] < m_MinValue ) + { + m_MinValue = p[2]; + } + if( p[2] > m_MaxValue ) + { + m_MaxValue = p[2]; + } + + vtkpoints->InsertPoint( k++, p ); + } + } + + double den = std::max( itk::Math::abs( m_MinValue ), + itk::Math::abs( m_MaxValue ) ); + + inputImage->TransformIndexToPhysicalPoint( start, itkPoint ); + + index = start; + + index[0] += size[0] - 1; + index[1] += size[1] - 1; + + inputImage->TransformIndexToPhysicalPoint( index, itkPoint2 ); + + double ratio = m_HeightScaling * + static_cast< double >( itkPoint.EuclideanDistanceTo( itkPoint2 ) ); + + if( den != 0. ) + { + ratio /= den; + } + + for( vtkIdType i = 0; i < vtkpoints->GetNumberOfPoints(); i++ ) + { + vtkpoints->GetPoint( i, p ); + p[2] *= ratio; + vtkpoints->SetPoint( i, p ); + } + + vtkIdType vtkId[3]; + + + for( InputImageSizeValueType i = 0; i < ( this->m_NumberOfSamples[0] -1 ); i++ ) + { + for( InputImageSizeValueType j = 0; j < ( this->m_NumberOfSamples[1] - 1 ); j++ ) + { + vtkId[0] = i * m_NumberOfSamples[1] + j; + vtkId[1] = vtkId[0] + 1; + vtkId[2] = vtkId[1] + m_NumberOfSamples[1]; + this->m_Mesh->InsertNextCell( VTK_TRIANGLE, 3, static_cast< vtkIdType* >( vtkId ) ); + + vtkId[1] = vtkId[2]; + vtkId[2] = vtkId[1] - 1; + this->m_Mesh->InsertNextCell( VTK_TRIANGLE, 3, static_cast< vtkIdType* >( vtkId ) ); + } + } +} + + +} // end namespace itk + +#endif diff --git a/include/itkVTKVisualize2DSparseLevelSetLayers.h b/include/itkVTKVisualize2DSparseLevelSetLayers.h new file mode 100644 index 0000000..bbeb46a --- /dev/null +++ b/include/itkVTKVisualize2DSparseLevelSetLayers.h @@ -0,0 +1,181 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkVTKVisualize2DSparseLevelSetLayers_h +#define itkVTKVisualize2DSparseLevelSetLayers_h + +#include "itkVTKVisualize2DSparseLevelSetLayersBase.h" + +#include "itkWhitakerSparseLevelSetImage.h" +#include "itkShiSparseLevelSetImage.h" +#include "itkMalcolmSparseLevelSetImage.h" + +namespace itk +{ +/** + * \class VTKVisualize2DSparseLevelSetLayers + * \tparam TInputImage Input Image Type + * \tparam TLevelSetImage Level Set type + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputImage, typename TLevelSet > +class ITK_TEMPLATE_EXPORT VTKVisualize2DSparseLevelSetLayers +{}; + +// ----------------------------------------------------------------------------- +/** + * \class VTKVisualize2DSparseLevelSetLayers + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputImage, typename TOutput, unsigned int VDimension > +class ITK_TEMPLATE_EXPORT VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::WhitakerSparseLevelSetImage< TOutput, VDimension > > : +public VTKVisualize2DSparseLevelSetLayersBase< + TInputImage, + itk::WhitakerSparseLevelSetImage< TOutput, VDimension > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualize2DSparseLevelSetLayers); + + using LevelSetType = itk::WhitakerSparseLevelSetImage< TOutput, VDimension >; + + using Self = VTKVisualize2DSparseLevelSetLayers; + using Superclass = VTKVisualize2DSparseLevelSetLayersBase< TInputImage, LevelSetType >; + using Pointer = itk::SmartPointer< Self >; + using ConstPointer = itk::SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(VTKVisualize2DSparseLevelSetLayers, + VTKVisualize2DSparseLevelSetLayersBase ); + + using InputImageType = typename Superclass::InputImageType; + using InputPixelType = typename Superclass::InputPixelType; + + using LevelSetPointer = typename Superclass::LevelSetPointer; + +protected: + VTKVisualize2DSparseLevelSetLayers(); + ~VTKVisualize2DSparseLevelSetLayers() override; + + void AddLayers() override; + + std::string GetLevelSetRepresentationName() const override; +}; + +// ----------------------------------------------------------------------------- +/** + * \class VTKVisualize2DSparseLevelSetLayers + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputImage, unsigned int VDimension > +class ITK_TEMPLATE_EXPORT VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::ShiSparseLevelSetImage< VDimension > > : +public VTKVisualize2DSparseLevelSetLayersBase< + TInputImage, + itk::ShiSparseLevelSetImage< VDimension > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualize2DSparseLevelSetLayers); + + using LevelSetType = itk::ShiSparseLevelSetImage< VDimension >; + + using Self = VTKVisualize2DSparseLevelSetLayers; + using Superclass = VTKVisualize2DSparseLevelSetLayersBase< TInputImage, LevelSetType >; + using Pointer = itk::SmartPointer< Self >; + using ConstPointer = itk::SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(VTKVisualize2DSparseLevelSetLayers, + VTKVisualize2DSparseLevelSetLayersBase ); + + using InputImageType = typename Superclass::InputImageType; + using InputPixelType = typename Superclass::InputPixelType; + + using LevelSetPointer = typename Superclass::LevelSetPointer; + +protected: + VTKVisualize2DSparseLevelSetLayers(); + ~VTKVisualize2DSparseLevelSetLayers() override; + + void AddLayers() override; + + std::string GetLevelSetRepresentationName() const override; +}; + +// ----------------------------------------------------------------------------- + +/** + * \class VTKVisualize2DSparseLevelSetLayers + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputImage, unsigned int VDimension > +class ITK_TEMPLATE_EXPORT VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::MalcolmSparseLevelSetImage< VDimension > > : +public VTKVisualize2DSparseLevelSetLayersBase< + TInputImage, + itk::MalcolmSparseLevelSetImage< VDimension > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualize2DSparseLevelSetLayers); + + using LevelSetType = itk::MalcolmSparseLevelSetImage< VDimension >; + + using Self = VTKVisualize2DSparseLevelSetLayers; + using Superclass = VTKVisualize2DSparseLevelSetLayersBase< TInputImage, LevelSetType >; + using Pointer = itk::SmartPointer< Self >; + using ConstPointer = itk::SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(VTKVisualize2DSparseLevelSetLayers, + VTKVisualize2DSparseLevelSetLayersBase ); + + using InputImageType = typename Superclass::InputImageType; + using InputPixelType = typename Superclass::InputPixelType; + + using LevelSetPointer = typename Superclass::LevelSetPointer; + +protected: + VTKVisualize2DSparseLevelSetLayers(); + ~VTKVisualize2DSparseLevelSetLayers() override; + + void AddLayers() override; + + std::string GetLevelSetRepresentationName() const override; +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVTKVisualize2DSparseLevelSetLayers.hxx" +#endif +#endif diff --git a/include/itkVTKVisualize2DSparseLevelSetLayers.hxx b/include/itkVTKVisualize2DSparseLevelSetLayers.hxx new file mode 100644 index 0000000..0c73f9e --- /dev/null +++ b/include/itkVTKVisualize2DSparseLevelSetLayers.hxx @@ -0,0 +1,248 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkVTKVisualize2DSparseLevelSetLayers_hxx +#define itkVTKVisualize2DSparseLevelSetLayers_hxx + +#include "itkVTKVisualize2DSparseLevelSetLayers.h" + +namespace itk +{ +template< typename TInputImage, typename TOutput, unsigned int VDimension > +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::WhitakerSparseLevelSetImage< TOutput, VDimension > > +::VTKVisualize2DSparseLevelSetLayers() : Superclass() +{} + +template< typename TInputImage, typename TOutput, unsigned int VDimension > +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::WhitakerSparseLevelSetImage< TOutput, VDimension > > +::~VTKVisualize2DSparseLevelSetLayers() +{} + +template< typename TInputImage, typename TOutput, unsigned int VDimension > +void +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::WhitakerSparseLevelSetImage< TOutput, VDimension > > +::AddLayers() +{ + using LayerType = typename LevelSetType::LayerType; + using LayerConstIterator = typename LevelSetType::LayerConstIterator; + LayerType layer = this->m_LevelSet->GetLayer( LevelSetType::MinusTwoLayer() ); + + LayerConstIterator it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 0; + vtkpixel[1] = 255; + vtkpixel[2] = 0; + ++it; + } + + layer = this->m_LevelSet->GetLayer( LevelSetType::MinusOneLayer() ); + + it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 255; + vtkpixel[1] = 255; + vtkpixel[2] = 0; + ++it; + } + + layer = this->m_LevelSet->GetLayer( LevelSetType::ZeroLayer() ); + + it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 255; + vtkpixel[1] = 0; + vtkpixel[2] = 0; + ++it; + } + + layer = this->m_LevelSet->GetLayer( LevelSetType::PlusOneLayer() ); + + it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 0; + vtkpixel[1] = 255; + vtkpixel[2] = 255; + ++it; + } + + layer = this->m_LevelSet->GetLayer( LevelSetType::PlusTwoLayer() ); + + it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 0; + vtkpixel[1] = 0; + vtkpixel[2] = 255; + ++it; + } + } + +template< typename TInputImage, typename TOutput, unsigned int VDimension > +std::string +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::WhitakerSparseLevelSetImage< TOutput, VDimension > > +::GetLevelSetRepresentationName() const + { + return std::string( "Whitaker" ); + } + +// ----------------------------------------------------------------------------- +template< typename TInputImage, unsigned int VDimension > +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::ShiSparseLevelSetImage< VDimension > > +::VTKVisualize2DSparseLevelSetLayers() : Superclass() + { + } + +template< typename TInputImage, unsigned int VDimension > +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::ShiSparseLevelSetImage< VDimension > > +::~VTKVisualize2DSparseLevelSetLayers() + { + } + +template< typename TInputImage, unsigned int VDimension > +void +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::ShiSparseLevelSetImage< VDimension > > +::AddLayers() + { + using LayerType = typename LevelSetType::LayerType; + using LayerConstIterator = typename LevelSetType::LayerConstIterator; + + LayerType layer = this->m_LevelSet->GetLayer( LevelSetType::MinusOneLayer() ); + + LayerConstIterator it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 0; + vtkpixel[1] = 255; + vtkpixel[2] = 0; + ++it; + } + + layer = this->m_LevelSet->GetLayer( LevelSetType::PlusOneLayer() ); + + it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 255; + vtkpixel[1] = 0; + vtkpixel[2] = 0; + ++it; + } + } + +template< typename TInputImage, unsigned int VDimension > +std::string +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::ShiSparseLevelSetImage< VDimension > > +::GetLevelSetRepresentationName() const + { + return std::string( "Shi" ); + } + +// ----------------------------------------------------------------------------- +template< typename TInputImage, unsigned int VDimension > +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::MalcolmSparseLevelSetImage< VDimension > > +::VTKVisualize2DSparseLevelSetLayers() : Superclass() +{} + +template< typename TInputImage, unsigned int VDimension > +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::MalcolmSparseLevelSetImage< VDimension > > +::~VTKVisualize2DSparseLevelSetLayers() +{} + +template< typename TInputImage, unsigned int VDimension > +void +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::MalcolmSparseLevelSetImage< VDimension > > +::AddLayers() +{ + + + using LayerType = typename LevelSetType::LayerType; + using LayerConstIterator = typename LevelSetType::LayerConstIterator; + + LayerType layer = this->m_LevelSet->GetLayer( LevelSetType::ZeroLayer() ); + + LayerConstIterator it = layer.begin(); + + while( it != layer.end() ) + { + typename InputImageType::IndexType idx = it->first; + auto * vtkpixel = static_cast< InputPixelType* >( this->m_VTKImage->GetScalarPointer( idx[0], idx[1], 0 ) ); + vtkpixel[0] = 255; + vtkpixel[1] = 0; + vtkpixel[2] = 0; + ++it; + } +} + +template< typename TInputImage, unsigned int VDimension > +std::string +VTKVisualize2DSparseLevelSetLayers< + TInputImage, + itk::MalcolmSparseLevelSetImage< VDimension > > +::GetLevelSetRepresentationName() const + { + return std::string( "Malcolm" ); + } +} +#endif diff --git a/include/itkVTKVisualize2DSparseLevelSetLayersBase.h b/include/itkVTKVisualize2DSparseLevelSetLayersBase.h new file mode 100644 index 0000000..5e8ee43 --- /dev/null +++ b/include/itkVTKVisualize2DSparseLevelSetLayersBase.h @@ -0,0 +1,104 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkVTKVisualize2DSparseLevelSetLayersBase_h +#define itkVTKVisualize2DSparseLevelSetLayersBase_h + +#include "itkVTKVisualizeImageLevelSet.h" + +#include "itkConceptChecking.h" + +#include "itkImageToRGBVTKImageFilter.h" + +#include "vtkCornerAnnotation.h" +#include "vtkImageData.h" +#include "vtkLookupTable.h" +#include "vtkMarchingSquares.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkImageActor.h" +#include "vtkScalarBarActor.h" +#include "vtkProperty.h" +#include "vtkRenderer.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkRenderWindow.h" +#include "vtkImageShiftScale.h" + +#include "vtkCaptureScreen.h" +#include "vtkPNGWriter.h" + +namespace itk +{ +/** + * \class VTKVisualize2DSparseLevelSetLayersBase + * \tparam TInputImage Input Image Type + * \tparam TLevelSet Level Set Type + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputImage, typename TLevelSet > +class ITK_TEMPLATE_EXPORT VTKVisualize2DSparseLevelSetLayersBase : + public VTKVisualizeImageLevelSet< TInputImage, ImageToRGBVTKImageFilter< TInputImage > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualize2DSparseLevelSetLayersBase); + + using ConverterType = ImageToRGBVTKImageFilter< TInputImage >; + using ConverterPointer = typename ConverterType::Pointer; + + using Self = VTKVisualize2DSparseLevelSetLayersBase; + using Superclass = VTKVisualizeImageLevelSet< TInputImage, ConverterType >; + using Pointer = itk::SmartPointer< Self >; + using ConstPointer = itk::SmartPointer< const Self >; + + /** Run-time type information (and related methods). */ + itkTypeMacro(VTKVisualize2DSparseLevelSetLayersBase, VTKVisualizeImageLevelSet ); + + using InputImageType = TInputImage; + using InputPixelType = typename InputImageType::PixelType; + + using LevelSetType = TLevelSet; + using LevelSetPointer = typename LevelSetType::Pointer; + + void SetInputImage( const InputImageType* image ) override; + void SetLevelSet( LevelSetType * levelSet ); + +#ifdef ITK_USE_CONCEPT_CHECKING + itkConceptMacro( Is2Dimensional, + ( Concept::SameDimension< LevelSetType::Dimension, 2 > ) ); +#endif + +protected: + VTKVisualize2DSparseLevelSetLayersBase(); + ~VTKVisualize2DSparseLevelSetLayersBase() override; + + LevelSetPointer m_LevelSet; + vtkSmartPointer< vtkImageData > m_VTKImage; + vtkSmartPointer< vtkImageActor > m_VTKImageActor; + + void PrepareVTKPipeline() override; + + virtual std::string GetLevelSetRepresentationName() const = 0; + + virtual void AddLayers() = 0; +}; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVTKVisualize2DSparseLevelSetLayersBase.hxx" +#endif +#endif diff --git a/include/itkVTKVisualize2DSparseLevelSetLayersBase.hxx b/include/itkVTKVisualize2DSparseLevelSetLayersBase.hxx new file mode 100644 index 0000000..6eeacdf --- /dev/null +++ b/include/itkVTKVisualize2DSparseLevelSetLayersBase.hxx @@ -0,0 +1,91 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#ifndef itkVTKVisualize2DSparseLevelSetLayersBase_hxx +#define itkVTKVisualize2DSparseLevelSetLayersBase_hxx + +#include "vtkVersion.h" + +#include "itkVTKVisualize2DSparseLevelSetLayersBase.h" +#include "vtkImageMapper3D.h" + +namespace itk +{ +template< typename TInputImage, typename TLevelSet > +VTKVisualize2DSparseLevelSetLayersBase< TInputImage, TLevelSet > +::VTKVisualize2DSparseLevelSetLayersBase(): Superclass() +{ + this->m_VTKImageActor = vtkSmartPointer< vtkImageActor >::New(); + this->m_VTKImageActor->InterpolateOff(); + + this->m_Renderer->AddActor2D( this->m_VTKImageActor ); +} + +template< typename TInputImage, typename TLevelSet > +VTKVisualize2DSparseLevelSetLayersBase< TInputImage, TLevelSet > +::~VTKVisualize2DSparseLevelSetLayersBase() +{ +} + +template< typename TInputImage, typename TLevelSet > +void +VTKVisualize2DSparseLevelSetLayersBase< TInputImage, TLevelSet > +::SetInputImage( const InputImageType* iImage ) +{ + this->m_InputImageConverter->SetInput( iImage ); + try + { + this->m_InputImageConverter->Update(); + } + catch( itk::ExceptionObject& e ) + { + std::cout << e << std::endl; + return; + } +} + +template< typename TInputImage, typename TLevelSet > +void +VTKVisualize2DSparseLevelSetLayersBase< TInputImage, TLevelSet > +::SetLevelSet( LevelSetType* levelSet ) +{ + this->m_LevelSet = levelSet; +} + +template< typename TInputImage, typename TLevelSet > +void +VTKVisualize2DSparseLevelSetLayersBase< TInputImage, TLevelSet > +::PrepareVTKPipeline() +{ + this->m_InputImageConverter->Update(); + this->m_VTKImage = this->m_InputImageConverter->GetOutput(); + + this->m_Renderer->RemoveActor2D( m_VTKImageActor ); + +#if VTK_MAJOR_VERSION <= 5 + this->m_VTKImageActor->SetInput( this->m_VTKImage ); +#else + this->m_VTKImageActor->GetMapper()->SetInputData( this->m_VTKImage ); +#endif + + this->AddLayers(); + + this->m_Renderer->AddActor2D( this->m_VTKImageActor ); +} +} +#endif diff --git a/include/itkVTKVisualizeImageLevelSet.h b/include/itkVTKVisualizeImageLevelSet.h new file mode 100644 index 0000000..4b55676 --- /dev/null +++ b/include/itkVTKVisualizeImageLevelSet.h @@ -0,0 +1,115 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkVTKVisualizeImageLevelSet_h +#define itkVTKVisualizeImageLevelSet_h + +#include "itkLightObject.h" +#include "itkIntTypes.h" + +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkSmartPointer.h" +#include "vtkImageShiftScale.h" +#include "vtkImageActor.h" +#include "vtkCornerAnnotation.h" + +namespace itk +{ + +/** \class VTKVisualizeImageLevelSet + * \brief Base class for visualizing level sets defined on an image with VTK. + * + * \tparam TInputImage Input image the level set evolves on. + * \tparam TInputImageConverter ITK filter to convert the input image to a VTK + * object. + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputImage, typename TInputImageConverter > +class ITK_TEMPLATE_EXPORT VTKVisualizeImageLevelSet: public LightObject +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualizeImageLevelSet); + + using Self = VTKVisualizeImageLevelSet; + using Superclass = LightObject; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Run-time type information (and related methods). */ + itkTypeMacro( VTKVisualizeImageLevelSet, LightObject ); + + /** Type of the input image the level set evolves on. */ + using InputImageType = TInputImage; + + /** Type of the ITK filter to convert the input image to a VTK object. */ + using InputImageConverterType = TInputImageConverter; + + /** Set the input image the level set is being evolved over. */ + virtual void SetInputImage( const InputImageType * inputImage ); + + /** Do a screen capture at every iteration. */ + void SetScreenCapture( const bool iCapture ); + bool GetScreenCapture() const; + + /** Set up the VTK pipeline and render. Do a screen capture if the option is + * set. */ + virtual void Update(); + + /** Get the renderer. */ + vtkRenderer * GetRenderer(); + + /** Set/Get the render window. */ + vtkRenderWindow * GetRenderWindow(); + void SetRenderWindow( vtkRenderWindow * renderWindow ); + + /** Set/Get the current iteration. Used for the filename during screen + * capture. */ + void SetCurrentIteration( const IdentifierType iteration ); + IdentifierType GetCurrentIteration() const; + + /** Set the filename prefix for screen captures. */ + void SetScreenCapturePrefix( const char * prefix ); + +protected: + VTKVisualizeImageLevelSet(); + ~VTKVisualizeImageLevelSet() override; + + /** Setup the VTK pipeline for a Render() call. */ + virtual void PrepareVTKPipeline() = 0; + + typename InputImageConverterType::Pointer m_InputImageConverter; + + vtkSmartPointer< vtkRenderer > m_Renderer; + +private: + bool m_ScreenCapture; + IdentifierType m_CurrentIteration; + std::string m_ScreenCapturePrefix; + + vtkSmartPointer< vtkRenderWindow > m_RenderWindow; + vtkSmartPointer< vtkCornerAnnotation > m_Annotation; +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVTKVisualizeImageLevelSet.hxx" +#endif + +#endif diff --git a/include/itkVTKVisualizeImageLevelSet.hxx b/include/itkVTKVisualizeImageLevelSet.hxx new file mode 100644 index 0000000..a4ba313 --- /dev/null +++ b/include/itkVTKVisualizeImageLevelSet.hxx @@ -0,0 +1,179 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkVTKVisualizeImageLevelSet_hxx +#define itkVTKVisualizeImageLevelSet_hxx + +#include "itkVTKVisualizeImageLevelSet.h" + +#include "vtkVersion.h" + +#include "vtkCaptureScreen.h" +#include "vtkPNGWriter.h" +#include "vtkImageMapper3D.h" + +namespace itk +{ + +template < typename TInputImage, typename TInputImageConverter > +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::VTKVisualizeImageLevelSet(): + m_ScreenCapture( false ), + m_ScreenCapturePrefix( "levelset_" ) +{ + this->m_CurrentIteration = 0; + + this->m_InputImageConverter = InputImageConverterType::New(); + + this->m_Renderer = vtkSmartPointer< vtkRenderer >::New(); + this->m_Renderer->SetBackground( 0.5, 0.5, 0.5 ); + this->m_RenderWindow = vtkSmartPointer< vtkRenderWindow >::New(); + this->m_RenderWindow->AddRenderer( this->m_Renderer ); + + this->m_Annotation = vtkSmartPointer< vtkCornerAnnotation >::New(); + this->m_Renderer->AddActor2D( this->m_Annotation ); +} + +template < typename TInputImage, typename TInputImageConverter > +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::~VTKVisualizeImageLevelSet() +{ +} + +template < typename TInputImage, typename TInputImageConverter > +void +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::SetInputImage( const InputImageType * inputImage ) +{ + this->m_InputImageConverter->SetInput( inputImage ); + this->m_InputImageConverter->Update(); + + vtkSmartPointer< vtkImageShiftScale > ImageShiftScale = vtkSmartPointer< vtkImageShiftScale >::New(); + ImageShiftScale->SetOutputScalarTypeToUnsignedChar(); +#if VTK_MAJOR_VERSION <= 5 + ImageShiftScale->SetInput( this->m_InputImageConverter->GetOutput() ); +#else + this->m_InputImageConverter->Update(); + ImageShiftScale->SetInputData( this->m_InputImageConverter->GetOutput() ); +#endif + ImageShiftScale->Update(); + + vtkSmartPointer< vtkImageActor > ImageActor = vtkSmartPointer< vtkImageActor >::New(); + ImageActor->InterpolateOff(); + ImageActor->GetMapper()->SetInputConnection( ImageShiftScale->GetOutputPort() ); + + this->m_Renderer->AddActor2D( ImageActor ); +} + +template < typename TInputImage, typename TInputImageConverter > +void +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::SetScreenCapture( const bool iCapture ) +{ + this->m_ScreenCapture = iCapture; +} + +template < typename TInputImage, typename TInputImageConverter > +bool +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::GetScreenCapture() const +{ + return this->m_ScreenCapture; +} + +template < typename TInputImage, typename TInputImageConverter > +vtkRenderer * +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::GetRenderer() +{ + return this->m_Renderer; +} + +template < typename TInputImage, typename TInputImageConverter > +vtkRenderWindow * +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::GetRenderWindow() +{ + return this->m_RenderWindow; +} + +template < typename TInputImage, typename TInputImageConverter > +void +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::SetRenderWindow( vtkRenderWindow * renderWindow ) +{ + this->m_RenderWindow = renderWindow; + this->m_RenderWindow->AddRenderer( this->m_Renderer ); +} + +template < typename TInputImage, typename TInputImageConverter > +void +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::SetCurrentIteration( const IdentifierType iteration ) +{ + this->m_CurrentIteration = iteration; +} + +template < typename TInputImage, typename TInputImageConverter > +IdentifierType +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::GetCurrentIteration() const +{ + return this->m_CurrentIteration; +} + +template < typename TInputImage, typename TInputImageConverter > +void +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::SetScreenCapturePrefix( const char * prefix) +{ + this->m_ScreenCapturePrefix = prefix; +} + +template < typename TInputImage, typename TInputImageConverter > +void +VTKVisualizeImageLevelSet< TInputImage, TInputImageConverter > +::Update() +{ + this->PrepareVTKPipeline(); + + std::stringstream counter; + counter << this->m_CurrentIteration; + + std::string counterString = counter.str(); + + this->m_Annotation->SetText( 0, counterString.c_str() ); + + this->m_RenderWindow->Render(); + + if( this->m_ScreenCapture ) + { + std::string filename; + std::stringstream yo; + yo << this->m_ScreenCapturePrefix << std::setfill( '0' ) << std::setw( 5 ) << this->m_CurrentIteration; + filename = yo.str(); + filename.append ( ".png" ); + + vtkCaptureScreen< vtkPNGWriter > capture ( this->m_RenderWindow ); + // begin mouse interaction + capture( filename ); + } +} + +} // end namespace itk + +#endif diff --git a/include/itkVTKVisualizeImageLevelSetIsoValues.h b/include/itkVTKVisualizeImageLevelSetIsoValues.h new file mode 100644 index 0000000..800d38d --- /dev/null +++ b/include/itkVTKVisualizeImageLevelSetIsoValues.h @@ -0,0 +1,198 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkVTKVisualizeImageLevelSetIsoValues_h +#define itkVTKVisualizeImageLevelSetIsoValues_h + +#include "itkVTKVisualizeImageLevelSet.h" + +#include "itkConceptChecking.h" +#include "itkImageToVTKImageFilter.h" +#include "itkLevelSetTovtkImageData.h" + +#include "vtkImageData.h" +#include "vtkLookupTable.h" +#include "vtkMarchingSquares.h" +#include "vtkMarchingCubes.h" +#include "vtkPolyDataMapper.h" +#include "vtkActor.h" +#include "vtkScalarBarActor.h" +#include "vtkProperty.h" +#include "vtkRenderWindowInteractor.h" + +namespace itk +{ +/** + * \class VTKVisualizeImageLevelSetIsoValues + * + * \tparam TImage Image Type + * \tparam TLevelSet Level Set Type + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TImage, typename TLevelSet > +class ITK_TEMPLATE_EXPORT VTKVisualizeImageLevelSetIsoValues +{}; + +/** + * \class VTKVisualizeImageLevelSetIsoValues + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputPixel, typename TLevelSet > +class ITK_TEMPLATE_EXPORT VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > + : public VTKVisualizeImageLevelSet< + Image< TInputPixel, 2 >, + ImageToVTKImageFilter< Image< TInputPixel, 2 > > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualizeImageLevelSetIsoValues); + + using Self = VTKVisualizeImageLevelSetIsoValues; + using Superclass = VTKVisualizeImageLevelSet< Image< TInputPixel, 2 >, + ImageToVTKImageFilter< Image< TInputPixel, 2 > > >; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(VTKVisualizeImageLevelSetIsoValues, VTKVisualizeImageLevelSet); + + using InputImageType = typename Superclass::InputImageType; + + using LevelSetType = TLevelSet; + + void SetLevelSet( LevelSetType * levelSet ); + + /** Set/Get the number of level set contours to visualize. */ + void SetNumberOfLevels( const SizeValueType numLevels ); + SizeValueType GetNumberOfLevels() const; + + /** Set/Get/ the maximum magnitude the levels contours are from the zero level + * set. */ + void SetLevelLimit( double iLimit ); + double GetLevelLimit() const; + +#ifdef ITK_USE_CONCEPT_CHECKING + itkConceptMacro( Is2Dimensional, + ( Concept::SameDimension< LevelSetType::Dimension, 2 > ) ); +#endif + +protected: + VTKVisualizeImageLevelSetIsoValues(); + ~VTKVisualizeImageLevelSetIsoValues() override; + + /** Render the visualization. */ + void PrepareVTKPipeline() override; + +private: + using LevelSetConverterType = LevelSetTovtkImageData< LevelSetType >; + using LevelSetConverterPointer = typename LevelSetConverterType::Pointer; + + LevelSetConverterPointer m_LevelSetConverter; + + vtkSmartPointer< vtkMarchingSquares > m_MarchingSquare; + vtkSmartPointer< vtkPolyDataMapper > m_ContourMapper; + vtkSmartPointer< vtkActor > m_ContourActor; + vtkSmartPointer< vtkScalarBarActor > m_ScalarBar; + vtkSmartPointer< vtkLookupTable > m_Lut; + + IdentifierType m_Count; + SizeValueType m_NumberOfLevels; + double m_LevelLimit; +}; + + +/** + * \class VTKVisualizeImageLevelSetIsoValues + * + * \ingroup ITKLevelSetsv4Visualization + */ +template< typename TInputPixel, typename TLevelSet > +class ITK_TEMPLATE_EXPORT VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > + : public VTKVisualizeImageLevelSet< + Image< TInputPixel, 3 >, + ImageToVTKImageFilter< Image< TInputPixel, 3 > > > +{ +public: + ITK_DISALLOW_COPY_AND_ASSIGN(VTKVisualizeImageLevelSetIsoValues); + + using Self = VTKVisualizeImageLevelSetIsoValues; + using Superclass = VTKVisualizeImageLevelSet< Image< TInputPixel, 3 >, + ImageToVTKImageFilter< Image< TInputPixel, 3 > > >; + using Pointer = SmartPointer< Self >; + using ConstPointer = SmartPointer< const Self >; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(VTKVisualizeImageLevelSetIsoValues, VTKVisualizeImageLevelSet); + + using InputImageType = typename Superclass::InputImageType; + + using LevelSetType = TLevelSet; + + void SetInputImage( const InputImageType * iImage ) override; + void SetLevelSet( LevelSetType * levelSet ); + + /** Set/Get the number of level set contours to visualize. */ + void SetNumberOfLevels( const SizeValueType numLevels ); + SizeValueType GetNumberOfLevels() const; + + /** Set/Get/ the maximum magnitude the levels contours are from the zero level + * set. */ + void SetLevelLimit( double iLimit ); + double GetLevelLimit() const; + +#ifdef ITK_USE_CONCEPT_CHECKING + itkConceptMacro( Is3Dimensional, + ( Concept::SameDimension< LevelSetType::Dimension, 3 > ) ); +#endif + +protected: + VTKVisualizeImageLevelSetIsoValues(); + ~VTKVisualizeImageLevelSetIsoValues() override; + + /** Render the visualization. */ + void PrepareVTKPipeline() override; + +private: + using LevelSetConverterType = LevelSetTovtkImageData< LevelSetType >; + using LevelSetConverterPointer = typename LevelSetConverterType::Pointer; + + LevelSetConverterPointer m_LevelSetConverter; + + vtkSmartPointer< vtkMarchingCubes > m_MarchingCubes; + vtkSmartPointer< vtkPolyDataMapper > m_ContourMapper; + vtkSmartPointer< vtkActor > m_ContourActor; + vtkSmartPointer< vtkScalarBarActor > m_ScalarBar; + vtkSmartPointer< vtkLookupTable > m_Lut; + + IdentifierType m_Count; + SizeValueType m_NumberOfLevels; + double m_LevelLimit; +}; +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVTKVisualizeImageLevelSetIsoValues.hxx" +#endif + +#endif diff --git a/include/itkVTKVisualizeImageLevelSetIsoValues.hxx b/include/itkVTKVisualizeImageLevelSetIsoValues.hxx new file mode 100644 index 0000000..7073065 --- /dev/null +++ b/include/itkVTKVisualizeImageLevelSetIsoValues.hxx @@ -0,0 +1,307 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkVTKVisualizeImageLevelSetIsoValues_hxx +#define itkVTKVisualizeImageLevelSetIsoValues_hxx + +#include "vtkVersion.h" + +#include "itkVTKVisualizeImageLevelSetIsoValues.h" + +namespace itk +{ +template< typename TInputPixel, typename TLevelSet > +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::VTKVisualizeImageLevelSetIsoValues(): + m_NumberOfLevels( 1 ), + m_LevelLimit( 0. ) +{ + this->m_LevelSetConverter = LevelSetConverterType::New(); + + this->m_MarchingSquare = vtkSmartPointer< vtkMarchingSquares >::New(); + + this->m_ContourMapper = vtkSmartPointer< vtkPolyDataMapper >::New(); + + this->m_Lut = vtkSmartPointer< vtkLookupTable >::New(); + this->m_Lut->SetTableRange( 0, 1 ); + this->m_Lut->SetHueRange( 0, 1 ); + this->m_Lut->SetSaturationRange( 1, 1 ); + this->m_Lut->SetValueRange( 1, 1 ); + this->m_Lut->Build(); + + this->m_ScalarBar = vtkSmartPointer< vtkScalarBarActor >::New(); + this->m_ScalarBar->SetLookupTable( this->m_Lut ); + this->m_ScalarBar->SetTitle( "Level Set Values" ); + this->m_ScalarBar->SetNumberOfLabels( this->m_NumberOfLevels ); + this->m_ContourMapper->SetScalarRange( - m_LevelLimit, m_LevelLimit ); + + this->m_Renderer->AddActor2D( this->m_ScalarBar ); + + this->m_ContourActor = vtkSmartPointer< vtkActor >::New(); + this->m_ContourActor->SetMapper( this->m_ContourMapper ); + this->m_ContourActor->GetProperty()->SetLineWidth( 2. ); + this->m_ContourActor->GetProperty()->SetColor( 1., 0., 0. ); +} + +template< typename TInputPixel, typename TLevelSet > +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::~VTKVisualizeImageLevelSetIsoValues() +{ +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::SetLevelSet( LevelSetType* iLevelSet ) +{ + this->m_LevelSetConverter->SetInput( iLevelSet ); +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::SetNumberOfLevels( const SizeValueType numLevels ) +{ + if( numLevels > 0 ) + { + this->m_NumberOfLevels = numLevels; + this->m_ScalarBar->SetNumberOfLabels( m_NumberOfLevels ); + } +} + +template< typename TInputPixel, typename TLevelSet > +SizeValueType +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::GetNumberOfLevels() const +{ + return this->m_NumberOfLevels; +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::SetLevelLimit( double levelLimit ) +{ + if( levelLimit > 0. ) + { + this->m_LevelLimit = levelLimit; + this->m_ContourMapper->SetScalarRange( - m_LevelLimit, m_LevelLimit ); + } +} + +template< typename TInputPixel, typename TLevelSet > +double +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::GetLevelLimit() const +{ + return this->m_LevelLimit; +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 2 >, TLevelSet > +::PrepareVTKPipeline() +{ + this->m_LevelSetConverter->Update(); + +#if VTK_MAJOR_VERSION <= 5 + this->m_MarchingSquare->SetInput( this->m_LevelSetConverter->GetOutput() ); +#else + this->m_LevelSetConverter->Update(); + this->m_MarchingSquare->SetInputData( this->m_LevelSetConverter->GetOutput() ); +#endif + this->m_MarchingSquare->GenerateValues( m_NumberOfLevels, - m_LevelLimit, m_LevelLimit ); + this->m_MarchingSquare->Modified(); + this->m_MarchingSquare->Update(); + + this->m_ContourMapper->SetInputConnection( this->m_MarchingSquare->GetOutputPort() ); + this->m_ContourMapper->Modified(); + + this->m_Renderer->AddActor( this->m_ContourActor ); + + vtkScalarsToColors * lookupTable = this->m_ContourMapper->GetLookupTable(); + lookupTable->SetRange( - m_LevelLimit, m_LevelLimit ); + lookupTable->Build(); + + this->m_ScalarBar->SetLookupTable( lookupTable ); + this->m_ScalarBar->Modified(); +} + +// --------------------- 3D --------------------------------------------------- +template< typename TInputPixel, typename TLevelSet > +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::VTKVisualizeImageLevelSetIsoValues(): + m_NumberOfLevels( 1 ), + m_LevelLimit( 0. ) +{ + this->m_LevelSetConverter = LevelSetConverterType::New(); + + this->m_MarchingCubes = vtkSmartPointer< vtkMarchingCubes >::New(); + + this->m_ContourMapper = vtkSmartPointer< vtkPolyDataMapper >::New(); + + this->m_Lut = vtkSmartPointer< vtkLookupTable >::New(); + this->m_Lut->SetTableRange( 0, 1 ); + this->m_Lut->SetHueRange( 0, 1 ); + this->m_Lut->SetSaturationRange( 1, 1 ); + this->m_Lut->SetValueRange( 1, 1 ); + this->m_Lut->Build(); + + this->m_ScalarBar = vtkSmartPointer< vtkScalarBarActor >::New(); + this->m_ScalarBar->SetLookupTable( this->m_Lut ); + this->m_ScalarBar->SetTitle( "Level Set Values" ); + this->m_ScalarBar->SetNumberOfLabels( this->m_NumberOfLevels ); + this->m_ContourMapper->SetScalarRange( - m_LevelLimit, m_LevelLimit ); + + this->m_Renderer->AddActor2D( this->m_ScalarBar ); + + this->m_ContourActor = vtkSmartPointer< vtkActor >::New(); + this->m_ContourActor->SetMapper( this->m_ContourMapper ); + this->m_ContourActor->GetProperty()->SetLineWidth( 2. ); + this->m_ContourActor->GetProperty()->SetColor( 1., 0., 0. ); +} + +template< typename TInputPixel, typename TLevelSet > +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::~VTKVisualizeImageLevelSetIsoValues() +{ +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::SetInputImage( const InputImageType * iImage ) +{ + this->m_InputImageConverter->SetInput( iImage ); + this->m_InputImageConverter->Update(); + + vtkSmartPointer< vtkImageShiftScale > ImageShiftScale = vtkSmartPointer< vtkImageShiftScale >::New(); + ImageShiftScale->SetOutputScalarTypeToUnsignedChar(); +#if VTK_MAJOR_VERSION <= 5 + ImageShiftScale->SetInput( this->m_InputImageConverter->GetOutput() ); +#else + this->m_InputImageConverter->Update(); + ImageShiftScale->SetInputData( this->m_InputImageConverter->GetOutput() ); +#endif + ImageShiftScale->Update(); + + int dimensions[3]; + this->m_InputImageConverter->GetOutput()->GetDimensions( dimensions ); + + vtkSmartPointer< vtkImageActor > zImageActor = vtkSmartPointer< vtkImageActor >::New(); + zImageActor->InterpolateOff(); + zImageActor->GetMapper()->SetInputConnection( ImageShiftScale->GetOutputPort() ); + zImageActor->SetDisplayExtent( 0, dimensions[0], 0, dimensions[1], dimensions[2] / 2, dimensions[2] / 2 ); + + this->m_Renderer->AddActor( zImageActor ); + + vtkSmartPointer< vtkImageActor > yImageActor = vtkSmartPointer< vtkImageActor >::New(); + yImageActor->InterpolateOff(); + yImageActor->GetMapper()->SetInputConnection( ImageShiftScale->GetOutputPort() ); + yImageActor->SetDisplayExtent( 0, dimensions[0], dimensions[1] / 2, dimensions[1] / 2, 0, dimensions[2] ); + + this->m_Renderer->AddActor( yImageActor ); + + vtkSmartPointer< vtkImageActor > xImageActor = vtkSmartPointer< vtkImageActor >::New(); + xImageActor->InterpolateOff(); + xImageActor->GetMapper()->SetInputConnection( ImageShiftScale->GetOutputPort() ); + xImageActor->SetDisplayExtent( dimensions[0] / 2, dimensions[0] / 2, 0, dimensions[1], 0, dimensions[2] ); + + this->m_Renderer->AddActor( xImageActor ); +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::SetLevelSet( LevelSetType* iLevelSet ) +{ + this->m_LevelSetConverter->SetInput( iLevelSet ); +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::SetNumberOfLevels( const SizeValueType numLevels ) +{ + if( numLevels > 0 ) + { + this->m_NumberOfLevels = numLevels; + this->m_ScalarBar->SetNumberOfLabels( m_NumberOfLevels ); + } +} + +template< typename TInputPixel, typename TLevelSet > +SizeValueType +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::GetNumberOfLevels() const +{ + return this->m_NumberOfLevels; +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::SetLevelLimit( double levelLimit ) +{ + if( levelLimit > 0. ) + { + this->m_LevelLimit = levelLimit; + this->m_ContourMapper->SetScalarRange( - m_LevelLimit, m_LevelLimit ); + } +} + +template< typename TInputPixel, typename TLevelSet > +double +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::GetLevelLimit() const +{ + return this->m_LevelLimit; +} + +template< typename TInputPixel, typename TLevelSet > +void +VTKVisualizeImageLevelSetIsoValues< Image< TInputPixel, 3 >, TLevelSet > +::PrepareVTKPipeline() +{ + this->m_LevelSetConverter->Update(); + +#if VTK_MAJOR_VERSION <= 5 + this->m_MarchingCubes->SetInput( this->m_LevelSetConverter->GetOutput() ); +#else + this->m_LevelSetConverter->Update(); + this->m_MarchingCubes->SetInputData( this->m_LevelSetConverter->GetOutput() ); +#endif + this->m_MarchingCubes->GenerateValues( m_NumberOfLevels, - m_LevelLimit, m_LevelLimit ); + this->m_MarchingCubes->ComputeNormalsOff(); + this->m_MarchingCubes->Modified(); + this->m_MarchingCubes->Update(); + + this->m_ContourMapper->SetInputConnection( this->m_MarchingCubes->GetOutputPort() ); + this->m_ContourMapper->Modified(); + + this->m_Renderer->AddActor( this->m_ContourActor ); + + vtkScalarsToColors * lookupTable = this->m_ContourMapper->GetLookupTable(); + lookupTable->SetRange( - m_LevelLimit, m_LevelLimit ); + lookupTable->Build(); + + this->m_ScalarBar->SetLookupTable( lookupTable ); + this->m_ScalarBar->Modified(); +} +} // end namespace itk + +#endif diff --git a/itk-module.cmake b/itk-module.cmake index a424164..9cdbd30 100644 --- a/itk-module.cmake +++ b/itk-module.cmake @@ -9,6 +9,7 @@ itk_module(ITKVtkGlue DEPENDS ITKCommon ITKVTK + ITKLevelSetsv4 COMPILE_DEPENDS ITKSpatialObjects ITKImageIntensity diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 966734f..e183d07 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,6 +18,18 @@ if(NOT VTK_RENDERING_BACKEND STREQUAL "None") QuickViewTest.cxx itkVtkConnectedComponentImageFilterTest.cxx itkVtkMedianFilterTest.cxx + itkVTKVisualizeLevelSetsInteractivePauseTest + itkVTKVisualize2DDenseImageLevelSetTest + itkVTKVisualize2DWhitakerLevelSetTest + itkImageToRGBVTKImageFilterTest + itkVTKVisualize2DCellsLevelSetTest + itkVTKVisualize2DCellsLevelSetSurfaceTest + itkVTKVisualize2DCellsLevelSetLayersTest + itkVTKVisualize2DWhitakerLevelSetLayersTest + itkVTKVisualize2DShiLevelSetLayersTest + itkVTKVisualize2DMalcolmLevelSetLayersTest + itkVTKVisualize3DDenseImageLevelSetTest + itkVTKVisualize3DWhitakerLevelSetTest ) endif() @@ -89,4 +101,119 @@ if(NOT VTK_RENDERING_BACKEND STREQUAL "None") itkVtkConnectedComponentImageFilterTest DATA{Input/cthead1.png} ) set_property(TEST itkVtkConnectedComponentImageFilterTest APPEND PROPERTY LABELS REQUIRES_DISPLAY) + + set(TEMP ${ITK_TEST_OUTPUT_DIR}) + + itk_add_test(NAME itkVTKVisualize2DDenseImageLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DDenseImageLevelSetTest) + + itk_add_test(NAME itkVTKVisualize2DWhitakerLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DWhitakerLevelSetTest) + + itk_add_test(NAME itkImageToRGBVTKImageFilterTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkImageToRGBVTKImageFilterTest) + + itk_add_test(NAME itkVTKVisualize2DWhitakerLevelSetLayersTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DWhitakerLevelSetLayersTest) + + itk_add_test(NAME itkVTKVisualize2DShiLevelSetLayersTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DShiLevelSetLayersTest) + + itk_add_test(NAME itkVTKVisualize2DMalcolmLevelSetLayersTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DMalcolmLevelSetLayersTest) + + itk_add_test(NAME itkVTKVisualize3DDenseImageLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize3DDenseImageLevelSetTest) + + itk_add_test(NAME itkVTKVisualize3DWhitakerLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize3DWhitakerLevelSetTest) + + itk_add_test(NAME itkVTKVisualize2DCellsDenseLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetTest + DATA{Input/cells.png} 60 Dense + ${TEMP}/itkVTKVisualize2DCellsDenseLevelSetTest.png + ) + itk_add_test(NAME itkVTKVisualize2DCellsDenseLevelSetSurfaceTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetSurfaceTest + DATA{Input/cells.png} 60 Dense + ${TEMP}/itkVTKVisualize2DCellsDenseLevelSetSurfaceTest.png + ) + + itk_add_test(NAME itkVTKVisualize2DCellsWhitakerLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetTest + DATA{Input/cells.png} 200 Whitaker + ${TEMP}/itkVTKVisualize2DCellsWhitakerLevelSetTest.png + ) + itk_add_test(NAME itkVTKVisualize2DCellsWhitakerLevelSetSurfaceTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetSurfaceTest + DATA{Input/cells.png} 200 Whitaker + ${TEMP}/itkVTKVisualize2DCellsWhitakerLevelSetSurfaceTest.png + ) + itk_add_test(NAME itkVTKVisualize2DCellsWhitakerLevelSetLayersTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetLayersTest + DATA{Input/cells.png} 200 Whitaker + ) + + itk_add_test(NAME itkVTKVisualize2DCellsShiLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetTest + DATA{Input/cells.png} 200 Shi + ${TEMP}/itkVTKVisualize2DCellsShiLevelSetTest.png + ) + itk_add_test(NAME itkVTKVisualize2DCellsShiLevelSetSurfaceTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetSurfaceTest + DATA{Input/cells.png} 200 Shi + ${TEMP}/itkVTKVisualize2DCellsShiLevelSetSurfaceTest.png + ) + itk_add_test(NAME itkVTKVisualize2DCellsShiLevelSetLayersTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetLayersTest + DATA{Input/cells.png} 200 Shi + ) + + itk_add_test(NAME itkVTKVisualize2DCellsMalcolmLevelSetTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetTest + DATA{Input/cells.png} 60 Malcolm + ${TEMP}/itkVTKVisualize2DCellsMalcolmLevelSetTest.png + ) + itk_add_test(NAME itkVTKVisualize2DCellsMalcolmLevelSetSurfaceTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetSurfaceTest + DATA{Input/cells.png} 60 Malcolm + ${TEMP}/itkVTKVisualize2DCellsMalcolmLevelSetSurfaceTest.png + ) + itk_add_test(NAME itkVTKVisualize2DCellsMalcolmLevelSetLayersTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DCellsLevelSetLayersTest + DATA{Input/cells.png} 60 Malcolm + ) + + itk_add_test(NAME itkVTKVisualizeLevelSetsInteractivePauseTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualizeLevelSetsInteractivePauseTest + DATA{Input/cells.png} 30 + ) + + itk_add_test(NAME itkVTKVisualize2DLevelSetAsElevationMapTest + COMMAND ITKLevelSetsv4VisualizationTestDriver itkVTKVisualize2DLevelSetAsElevationMapTest + ) + + set_property(TEST + itkVTKVisualize2DDenseImageLevelSetTest + itkVTKVisualize2DWhitakerLevelSetTest + itkImageToRGBVTKImageFilterTest + itkVTKVisualize2DWhitakerLevelSetLayersTest + itkVTKVisualize2DShiLevelSetLayersTest + itkVTKVisualize2DMalcolmLevelSetLayersTest + itkVTKVisualize3DDenseImageLevelSetTest + itkVTKVisualize3DWhitakerLevelSetTest + itkVTKVisualize2DCellsDenseLevelSetTest + itkVTKVisualize2DCellsDenseLevelSetSurfaceTest + itkVTKVisualize2DCellsWhitakerLevelSetTest + itkVTKVisualize2DCellsWhitakerLevelSetSurfaceTest + itkVTKVisualize2DCellsWhitakerLevelSetLayersTest + itkVTKVisualize2DCellsShiLevelSetTest + itkVTKVisualize2DCellsShiLevelSetSurfaceTest + itkVTKVisualize2DCellsShiLevelSetLayersTest + itkVTKVisualize2DCellsMalcolmLevelSetTest + itkVTKVisualize2DCellsMalcolmLevelSetSurfaceTest + itkVTKVisualize2DCellsMalcolmLevelSetLayersTest + itkVTKVisualizeLevelSetsInteractivePauseTest + itkVTKVisualize2DLevelSetAsElevationMapTest + APPEND PROPERTY LABELS REQUIRES_DISPLAY) endif() diff --git a/test/Input/cells.png.md5 b/test/Input/cells.png.md5 new file mode 100644 index 0000000..e6f51eb --- /dev/null +++ b/test/Input/cells.png.md5 @@ -0,0 +1 @@ +fdbf8aac724f9424eb1dd1de60c5661d diff --git a/test/Input/cells.png.sha512 b/test/Input/cells.png.sha512 new file mode 100644 index 0000000..31ffa47 --- /dev/null +++ b/test/Input/cells.png.sha512 @@ -0,0 +1 @@ +f71e898ed8a70d0af71b6f9d87ae3a355ac728e49aa36bc043372df25239af3ce47fd1f949f4a6af700448858b7915ee2c7e8213a96c2cffc1b0e44b97029808 diff --git a/test/itkBoxSpatialObjectToVTKPolyDataFilterTest.cxx b/test/itkBoxSpatialObjectToVTKPolyDataFilterTest.cxx index 08cc160..5a5d256 100644 --- a/test/itkBoxSpatialObjectToVTKPolyDataFilterTest.cxx +++ b/test/itkBoxSpatialObjectToVTKPolyDataFilterTest.cxx @@ -45,7 +45,7 @@ int itkBoxSpatialObjectToVTKPolyDataFilterTest(int argc, char *argv[]) size[0] = 1.3; size[1] = 2.2; size[2] = 3.8; - spatialObject->SetSize( size ); + spatialObject->SetSizeInObjectSpace( size ); using TransformType = SpatialObjectType::TransformType; TransformType * transform = spatialObject->GetModifiableObjectToWorldTransform(); @@ -59,7 +59,7 @@ int itkBoxSpatialObjectToVTKPolyDataFilterTest(int argc, char *argv[]) translation[2] = 3.0; transform->Translate( translation ); - spatialObject->ComputeLocalBoundingBox(); + spatialObject->Update(); spatialObject->Print( std::cout ); using ConverterType = itk::BoxSpatialObjectToVTKPolyDataFilter< Dimension >; diff --git a/test/itkImageToRGBVTKImageFilterTest.cxx b/test/itkImageToRGBVTKImageFilterTest.cxx new file mode 100644 index 0000000..383ba49 --- /dev/null +++ b/test/itkImageToRGBVTKImageFilterTest.cxx @@ -0,0 +1,126 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "vtkVersion.h" + +#include "vtkSmartPointer.h" +#include "vtkImageData.h" +#include "vtkImageActor.h" +#include "vtkImageMapper3D.h" +#include "vtkRenderer.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" + +#include "itkImage.h" +#include "itkImageToRGBVTKImageFilter.h" +#include "itkImageRegionIterator.h" + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } +} + +int itkImageToRGBVTKImageFilterTest( int argc, char* argv[] ) +{ + (void) argc; + (void) argv; + + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using RGBConvertType = itk::ImageToRGBVTKImageFilter< ImageType >; + RGBConvertType::Pointer converter = RGBConvertType::New(); + converter->SetInput( image ); + converter->Update(); + + vtkSmartPointer< vtkImageData > VTKImage = converter->GetOutput(); + + for( int i = 0; i < 50; i++ ) + { + auto * vtkpixel = static_cast< PixelType* >( VTKImage->GetScalarPointer( i, i, 0 ) ); + vtkpixel[0] = 255; + vtkpixel[1] = 0; + vtkpixel[2] = 0; + + vtkpixel = + static_cast< PixelType* >( VTKImage->GetScalarPointer( i, 49-i, 0 ) ); + vtkpixel[0] = 0; + vtkpixel[1] = 0; + vtkpixel[2] = 255; + } + + vtkSmartPointer< vtkImageActor > input_Actor = + vtkSmartPointer< vtkImageActor >::New(); +#if VTK_MAJOR_VERSION <= 5 + input_Actor->SetInput( VTKImage ); +#else + input_Actor->GetMapper()->SetInputData( VTKImage ); +#endif + vtkSmartPointer< vtkRenderer > ren = + vtkSmartPointer< vtkRenderer >::New(); + ren->SetBackground( 0.5, 0.5, 0.5 ); + + vtkSmartPointer< vtkRenderWindowInteractor > iren = + vtkSmartPointer< vtkRenderWindowInteractor >::New(); + + vtkSmartPointer< vtkRenderWindow > renWin = + vtkSmartPointer< vtkRenderWindow >::New(); + + ren->AddActor ( input_Actor ); + + iren->SetRenderWindow( renWin ); + + renWin->AddRenderer( ren ); + renWin->Render(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DCellsLevelSetLayersTest.cxx b/test/itkVTKVisualize2DCellsLevelSetLayersTest.cxx new file mode 100644 index 0000000..edd36bc --- /dev/null +++ b/test/itkVTKVisualize2DCellsLevelSetLayersTest.cxx @@ -0,0 +1,252 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkBinaryImageToLevelSetImageAdaptor.h" +#include "itkImageFileReader.h" +#include "itkLevelSetIterationUpdateCommand.h" +#include "itkLevelSetContainer.h" +#include "itkLevelSetEquationChanAndVeseInternalTerm.h" +#include "itkLevelSetEquationChanAndVeseExternalTerm.h" +#include "itkLevelSetEquationContainer.h" +#include "itkLevelSetEquationTermContainer.h" +#include "itkLevelSetEvolution.h" +#include "itkLevelSetEvolutionNumberOfIterationsStoppingCriterion.h" +#include "itkLevelSetDenseImage.h" +#include "itkVTKVisualize2DSparseLevelSetLayers.h" +#include "itkSinRegularizedHeavisideStepFunction.h" + +template< typename TInputImage, typename TLevelSetType > +void +visualizeLevelSet( TInputImage * inputImage, + const int numberOfIterations, + double epsilon ) +{ + // Basic type alias + using InputImageType = TInputImage; + + using LevelSetType = TLevelSetType; + using LevelSetOutputType = typename LevelSetType::OutputType; + using LevelSetRealType = typename LevelSetType::OutputRealType; + + // Generate a binary mask that will be used as initialization for the level + // set evolution. + using BinaryImageType = typename itk::Image< LevelSetOutputType, InputImageType::ImageDimension >; + typename BinaryImageType::Pointer binary = BinaryImageType::New(); + binary->SetRegions( inputImage->GetLargestPossibleRegion() ); + binary->CopyInformation( inputImage ); + binary->Allocate(); + binary->FillBuffer( itk::NumericTraits< LevelSetOutputType >::ZeroValue() ); + + typename BinaryImageType::RegionType region; + typename BinaryImageType::IndexType index; + typename BinaryImageType::SizeType size; + + index.Fill( 5 ); + size.Fill( 120 ); + + region.SetIndex( index ); + region.SetSize( size ); + + using InputIteratorType = itk::ImageRegionIteratorWithIndex< BinaryImageType >; + InputIteratorType iIt( binary, region ); + iIt.GoToBegin(); + while( !iIt.IsAtEnd() ) + { + iIt.Set( itk::NumericTraits< LevelSetOutputType >::OneValue() ); + ++iIt; + } + + using BinaryImageToLevelSetType = itk::BinaryImageToLevelSetImageAdaptor< BinaryImageType, + LevelSetType >; + + typename BinaryImageToLevelSetType::Pointer adaptor = BinaryImageToLevelSetType::New(); + adaptor->SetInputImage( binary ); + adaptor->Initialize(); + typename LevelSetType::Pointer levelSet = adaptor->GetModifiableLevelSet(); + std::cout << "Finished converting to sparse format" << std::endl; + + // The Heaviside function + using HeavisideFunctionType = typename itk::SinRegularizedHeavisideStepFunction< LevelSetRealType, LevelSetRealType >; + typename HeavisideFunctionType::Pointer heaviside = HeavisideFunctionType::New(); + heaviside->SetEpsilon( epsilon ); + std::cout << "Heaviside function created" << std::endl; + + // Create the level set container + using LevelSetContainerType = typename itk::LevelSetContainer< itk::IdentifierType, LevelSetType >; + typename LevelSetContainerType::Pointer levelSetContainer = LevelSetContainerType::New(); + levelSetContainer->SetHeaviside( heaviside ); + levelSetContainer->AddLevelSet( 0, levelSet ); + std::cout << "LevelSetContainer created" << std::endl; + + // Create the terms. + // + // // Chan and Vese internal term + using ChanAndVeseInternalTermType = itk::LevelSetEquationChanAndVeseInternalTerm< InputImageType, LevelSetContainerType >; + typename ChanAndVeseInternalTermType::Pointer cvInternalTerm = ChanAndVeseInternalTermType::New(); + cvInternalTerm->SetInput( inputImage ); + cvInternalTerm->SetCoefficient( 0.5 ); + std::cout << "Chan and Vese internal term created" << std::endl; + + // // Chan and Vese external term + using ChanAndVeseExternalTermType = typename itk::LevelSetEquationChanAndVeseExternalTerm< InputImageType, LevelSetContainerType >; + typename ChanAndVeseExternalTermType::Pointer cvExternalTerm = ChanAndVeseExternalTermType::New(); + cvExternalTerm->SetInput( inputImage ); + std::cout << "Chan and Vese external term created" << std::endl; + + // Create term container (equation rhs) + using TermContainerType = typename itk::LevelSetEquationTermContainer< InputImageType, LevelSetContainerType >; + typename TermContainerType::Pointer termContainer = TermContainerType::New(); + termContainer->SetLevelSetContainer( levelSetContainer ); + termContainer->SetInput( inputImage ); + termContainer->AddTerm( 0, cvInternalTerm ); + termContainer->AddTerm( 1, cvExternalTerm ); + std::cout << "Term container created" << std::endl; + + // Create equation container + using EquationContainerType = typename itk::LevelSetEquationContainer< TermContainerType >; + typename EquationContainerType::Pointer equationContainer = EquationContainerType::New(); + equationContainer->SetLevelSetContainer( levelSetContainer ); + equationContainer->AddEquation( 0, termContainer ); + std::cout << "Equation container created" << std::endl; + + // Create stopping criteria + using StoppingCriterionType = typename itk::LevelSetEvolutionNumberOfIterationsStoppingCriterion< LevelSetContainerType >; + typename StoppingCriterionType::Pointer criterion = StoppingCriterionType::New(); + criterion->SetNumberOfIterations( numberOfIterations ); + std::cout << "Stopping criteria created" << std::endl; + + // Create the visualizer + using VisualizationType = itk::VTKVisualize2DSparseLevelSetLayers< InputImageType, LevelSetType >; + typename VisualizationType::Pointer visualizer = VisualizationType::New(); + //! \todo the visualizer should get the input image from the level set + visualizer->SetInputImage( inputImage ); + visualizer->SetLevelSet( levelSet ); + visualizer->SetScreenCapture( true ); + std::cout << "Visualizer created" << std::endl; + + // Create evolution class + using LevelSetEvolutionType = typename itk::LevelSetEvolution< EquationContainerType, LevelSetType >; + typename LevelSetEvolutionType::Pointer evolution = LevelSetEvolutionType::New(); + evolution->SetEquationContainer( equationContainer ); + evolution->SetStoppingCriterion( criterion ); + evolution->SetLevelSetContainer( levelSetContainer ); + std::cout << "Evolution class created" << std::endl; + + using IterationUpdateCommandType = typename itk::LevelSetIterationUpdateCommand< LevelSetEvolutionType, VisualizationType >; + typename IterationUpdateCommandType::Pointer iterationUpdateCommand = IterationUpdateCommandType::New(); + iterationUpdateCommand->SetFilterToUpdate( visualizer ); + iterationUpdateCommand->SetUpdatePeriod( 4 ); + evolution->AddObserver( itk::IterationEvent(), iterationUpdateCommand ); + std::cout << "Visualization IterationUpdateCommand created" << std::endl; + + std::cout << "Evolving the level set..." << std::endl; + evolution->Update(); + + //! \todo Write out the final visualization image. +} + +int itkVTKVisualize2DCellsLevelSetLayersTest( int argc, char* argv[] ) +{ + if( argc != 4 ) + { + std::cerr << "Missing Arguments" << std::endl; + std::cerr << argv[0] << std::endl; + std::cerr << "1- Input Image" << std::endl; + std::cerr << "2- Number of Iterations" << std::endl; + std::cerr << "3- LevelSet Representation (Dense, Whitaker, Shi, Malcolm)" << std::endl; + + return EXIT_FAILURE; + } + + // Image Dimension + constexpr unsigned int Dimension = 2; + + using InputPixelType = unsigned char; + using InputImageType = itk::Image< InputPixelType, Dimension >; + + // Read input image (to be processed). + using ReaderType = itk::ImageFileReader< InputImageType >; + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName( argv[1] ); + reader->Update(); + InputImageType::Pointer input = reader->GetOutput(); + std::cout << "Input image read" << std::endl; + + // Convert the binary mask into a level set function. + // Here the output level-set will be a "Whitaker" sparse level-set; + // i.e. only few layers {-2, -1, 0, +1, +2 } around the zero-set are + // maintained, the rest of the domain is either -3 or +3. + + int numberOfIterations; + std::istringstream istrm( argv[2] ); + istrm >> numberOfIterations; + + std::string levelSetRepresentation = argv[3]; + if( levelSetRepresentation.compare( "Whitaker" ) == 0 ) + { + using LevelSetType = itk::WhitakerSparseLevelSetImage< double, 2 >; + try + { + visualizeLevelSet< InputImageType, LevelSetType >( input, + numberOfIterations, + 1.5 ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Shi" ) == 0 ) + { + using LevelSetType = itk::ShiSparseLevelSetImage< 2 >; + try + { + visualizeLevelSet< InputImageType, LevelSetType >( input, + numberOfIterations, + 1.5 ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Malcolm" ) == 0 ) + { + using LevelSetType = itk::MalcolmSparseLevelSetImage< 2 >; + try + { + visualizeLevelSet< InputImageType, LevelSetType >( input, + numberOfIterations, + 1.5); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else + { + std::cerr << "Unknown level set representation " << levelSetRepresentation << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DCellsLevelSetSurfaceTest.cxx b/test/itkVTKVisualize2DCellsLevelSetSurfaceTest.cxx new file mode 100644 index 0000000..ec6d3ad --- /dev/null +++ b/test/itkVTKVisualize2DCellsLevelSetSurfaceTest.cxx @@ -0,0 +1,262 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkBinaryImageToLevelSetImageAdaptor.h" +#include "itkImageFileReader.h" +#include "itkLevelSetIterationUpdateCommand.h" +#include "itkLevelSetContainer.h" +#include "itkLevelSetEquationChanAndVeseInternalTerm.h" +#include "itkLevelSetEquationChanAndVeseExternalTerm.h" +#include "itkLevelSetEquationContainer.h" +#include "itkLevelSetEquationTermContainer.h" +#include "itkLevelSetEvolution.h" +#include "itkLevelSetEvolutionNumberOfIterationsStoppingCriterion.h" +#include "itkLevelSetDenseImage.h" +#include "itkVTKVisualize2DLevelSetAsElevationMap.h" +#include "itkSinRegularizedHeavisideStepFunction.h" + +template< typename TInputImage, typename TLevelSetType > +void +VisualizeLevelSetSurface( TInputImage * inputImage, const int numberOfIterations, const char * ) +{ + // Basic type alias + using InputImageType = TInputImage; + + using LevelSetType = TLevelSetType; + using LevelSetOutputType = typename LevelSetType::OutputType; + using LevelSetRealType = typename LevelSetType::OutputRealType; + + // Generate a binary mask that will be used as initialization for the level + // set evolution. + using BinaryImageType = typename itk::Image< LevelSetOutputType, InputImageType::ImageDimension >; + typename BinaryImageType::Pointer binary = BinaryImageType::New(); + binary->SetRegions( inputImage->GetLargestPossibleRegion() ); + binary->CopyInformation( inputImage ); + binary->Allocate(); + binary->FillBuffer( itk::NumericTraits< LevelSetOutputType >::ZeroValue() ); + + typename BinaryImageType::RegionType region; + typename BinaryImageType::IndexType index; + typename BinaryImageType::SizeType size; + + index.Fill( 5 ); + size.Fill( 120 ); + + region.SetIndex( index ); + region.SetSize( size ); + + using InputIteratorType = itk::ImageRegionIteratorWithIndex< BinaryImageType >; + InputIteratorType iIt( binary, region ); + iIt.GoToBegin(); + while( !iIt.IsAtEnd() ) + { + iIt.Set( itk::NumericTraits< LevelSetOutputType >::OneValue() ); + ++iIt; + } + + using BinaryImageToLevelSetType = itk::BinaryImageToLevelSetImageAdaptor< BinaryImageType, + LevelSetType >; + + typename BinaryImageToLevelSetType::Pointer adaptor = BinaryImageToLevelSetType::New(); + adaptor->SetInputImage( binary ); + adaptor->Initialize(); + typename LevelSetType::Pointer levelSet = adaptor->GetModifiableLevelSet(); + std::cout << "Finished converting to sparse format" << std::endl; + + // The Heaviside function + using HeavisideFunctionType = typename itk::SinRegularizedHeavisideStepFunction< LevelSetRealType, LevelSetRealType >; + typename HeavisideFunctionType::Pointer heaviside = HeavisideFunctionType::New(); + heaviside->SetEpsilon( 1.5 ); + std::cout << "Heaviside function created" << std::endl; + + // Create the level set container + using LevelSetContainerType = typename itk::LevelSetContainer< itk::IdentifierType, LevelSetType >; + typename LevelSetContainerType::Pointer levelSetContainer = LevelSetContainerType::New(); + levelSetContainer->SetHeaviside( heaviside ); + levelSetContainer->AddLevelSet( 0, levelSet ); + std::cout << "LevelSetContainer created" << std::endl; + + // Create the terms. + // + // // Chan and Vese internal term + using ChanAndVeseInternalTermType = itk::LevelSetEquationChanAndVeseInternalTerm< InputImageType, LevelSetContainerType >; + typename ChanAndVeseInternalTermType::Pointer cvInternalTerm = ChanAndVeseInternalTermType::New(); + cvInternalTerm->SetInput( inputImage ); + cvInternalTerm->SetCoefficient( 0.5 ); + std::cout << "Chan and Vese internal term created" << std::endl; + + // // Chan and Vese external term + using ChanAndVeseExternalTermType = typename itk::LevelSetEquationChanAndVeseExternalTerm< InputImageType, LevelSetContainerType >; + typename ChanAndVeseExternalTermType::Pointer cvExternalTerm = ChanAndVeseExternalTermType::New(); + cvExternalTerm->SetInput( inputImage ); + std::cout << "Chan and Vese external term created" << std::endl; + + // Create term container (equation rhs) + using TermContainerType = typename itk::LevelSetEquationTermContainer< InputImageType, LevelSetContainerType >; + typename TermContainerType::Pointer termContainer = TermContainerType::New(); + termContainer->SetLevelSetContainer( levelSetContainer ); + termContainer->SetInput( inputImage ); + termContainer->AddTerm( 0, cvInternalTerm ); + termContainer->AddTerm( 1, cvExternalTerm ); + std::cout << "Term container created" << std::endl; + + // Create equation container + using EquationContainerType = typename itk::LevelSetEquationContainer< TermContainerType >; + typename EquationContainerType::Pointer equationContainer = EquationContainerType::New(); + equationContainer->SetLevelSetContainer( levelSetContainer ); + equationContainer->AddEquation( 0, termContainer ); + std::cout << "Equation container created" << std::endl; + + // Create stopping criteria + using StoppingCriterionType = typename itk::LevelSetEvolutionNumberOfIterationsStoppingCriterion< LevelSetContainerType >; + typename StoppingCriterionType::Pointer criterion = StoppingCriterionType::New(); + criterion->SetNumberOfIterations( numberOfIterations ); + std::cout << "Stopping criteria created" << std::endl; + + // Create the visualizer + using VisualizationType = itk::VTKVisualize2DLevelSetAsElevationMap< InputImageType, LevelSetType >; + typename VisualizationType::Pointer visualizer = VisualizationType::New(); + //! \todo the visualizer should get the input image from the level set + visualizer->SetInputImage( inputImage ); + visualizer->SetLevelSet( levelSet ); + std::cout << "Visualizer created" << std::endl; + + // Create evolution class + using LevelSetEvolutionType = typename itk::LevelSetEvolution< EquationContainerType, LevelSetType >; + typename LevelSetEvolutionType::Pointer evolution = LevelSetEvolutionType::New(); + evolution->SetEquationContainer( equationContainer ); + evolution->SetStoppingCriterion( criterion ); + evolution->SetLevelSetContainer( levelSetContainer ); + std::cout << "Evolution class created" << std::endl; + + using IterationUpdateCommandType = typename itk::LevelSetIterationUpdateCommand< LevelSetEvolutionType, VisualizationType >; + typename IterationUpdateCommandType::Pointer iterationUpdateCommand = IterationUpdateCommandType::New(); + iterationUpdateCommand->SetFilterToUpdate( visualizer ); + iterationUpdateCommand->SetUpdatePeriod( 5 ); + evolution->AddObserver( itk::IterationEvent(), iterationUpdateCommand ); + std::cout << "Visualization IterationUpdateCommand created" << std::endl; + + std::cout << "Evolving the level set..." << std::endl; + evolution->Update(); + + //! \todo Write out the final visualization image. +} + +int itkVTKVisualize2DCellsLevelSetSurfaceTest( int argc, char* argv[] ) +{ + if( argc < 5 ) + { + std::cerr << "Missing Arguments" << std::endl; + std::cerr << argv[0] << std::endl; + std::cerr << "1- Input Image" << std::endl; + std::cerr << "2- Number of Iterations" << std::endl; + std::cerr << "3- LevelSet Representation (Dense, Whitaker, Shi, Malcolm)" << std::endl; + std::cerr << "4- Output Image" << std::endl; + + return EXIT_FAILURE; + } + + // Image Dimension + constexpr unsigned int Dimension = 2; + + using InputPixelType = unsigned char; + using InputImageType = itk::Image< InputPixelType, Dimension >; + + // Read input image (to be processed). + using ReaderType = itk::ImageFileReader< InputImageType >; + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName( argv[1] ); + reader->Update(); + InputImageType::Pointer input = reader->GetOutput(); + std::cout << "Input image read" << std::endl; + + int numberOfIterations; + std::istringstream istrm( argv[2] ); + istrm >> numberOfIterations; + + std::string levelSetRepresentation = argv[3]; + if( levelSetRepresentation.compare( "Dense" ) == 0 ) + { + using LevelSetPixelType = float; + using LevelSetImageType = itk::Image< LevelSetPixelType, Dimension >; + using LevelSetType = itk::LevelSetDenseImage< LevelSetImageType >; + try + { + VisualizeLevelSetSurface< InputImageType, LevelSetType >( input, + numberOfIterations, + argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Whitaker" ) == 0 ) + { + using LevelSetType = itk::WhitakerSparseLevelSetImage< double, Dimension >; + try + { + VisualizeLevelSetSurface< InputImageType, LevelSetType >( input, + numberOfIterations, + argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Shi" ) == 0 ) + { + using LevelSetType = itk::ShiSparseLevelSetImage< Dimension >; + try + { + VisualizeLevelSetSurface< InputImageType, LevelSetType >( input, + numberOfIterations, + argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Malcolm" ) == 0 ) + { + using LevelSetType = itk::MalcolmSparseLevelSetImage< Dimension >; + try + { + VisualizeLevelSetSurface< InputImageType, LevelSetType >( input, + numberOfIterations, + argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else + { + std::cerr << "Unknown level set representation " << levelSetRepresentation << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DCellsLevelSetTest.cxx b/test/itkVTKVisualize2DCellsLevelSetTest.cxx new file mode 100644 index 0000000..094a8c5 --- /dev/null +++ b/test/itkVTKVisualize2DCellsLevelSetTest.cxx @@ -0,0 +1,260 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkBinaryImageToLevelSetImageAdaptor.h" +#include "itkImageFileReader.h" +#include "itkLevelSetIterationUpdateCommand.h" +#include "itkLevelSetContainer.h" +#include "itkLevelSetEquationChanAndVeseInternalTerm.h" +#include "itkLevelSetEquationChanAndVeseExternalTerm.h" +#include "itkLevelSetEquationContainer.h" +#include "itkLevelSetEquationTermContainer.h" +#include "itkLevelSetEvolution.h" +#include "itkLevelSetEvolutionNumberOfIterationsStoppingCriterion.h" +#include "itkLevelSetDenseImage.h" +#include "itkVTKVisualizeImageLevelSetIsoValues.h" +#include "itkSinRegularizedHeavisideStepFunction.h" + +template< typename TInputImage, typename TLevelSetType > +void +visualizeLevelSet( TInputImage * inputImage, const int numberOfIterations, const char * ) +{ + // Basic type alias + using InputImageType = TInputImage; + + using LevelSetType = TLevelSetType; + using LevelSetOutputType = typename LevelSetType::OutputType; + using LevelSetRealType = typename LevelSetType::OutputRealType; + + // Generate a binary mask that will be used as initialization for the level + // set evolution. + using BinaryImageType = typename itk::Image< LevelSetOutputType, InputImageType::ImageDimension >; + typename BinaryImageType::Pointer binary = BinaryImageType::New(); + binary->SetRegions( inputImage->GetLargestPossibleRegion() ); + binary->CopyInformation( inputImage ); + binary->Allocate(); + binary->FillBuffer( itk::NumericTraits< LevelSetOutputType >::ZeroValue() ); + + typename BinaryImageType::RegionType region; + typename BinaryImageType::IndexType index; + typename BinaryImageType::SizeType size; + + index.Fill( 5 ); + size.Fill( 120 ); + + region.SetIndex( index ); + region.SetSize( size ); + + using InputIteratorType = itk::ImageRegionIteratorWithIndex< BinaryImageType >; + InputIteratorType iIt( binary, region ); + iIt.GoToBegin(); + while( !iIt.IsAtEnd() ) + { + iIt.Set( itk::NumericTraits< LevelSetOutputType >::OneValue() ); + ++iIt; + } + + using BinaryImageToLevelSetType = itk::BinaryImageToLevelSetImageAdaptor< BinaryImageType, + LevelSetType >; + + typename BinaryImageToLevelSetType::Pointer adaptor = BinaryImageToLevelSetType::New(); + adaptor->SetInputImage( binary ); + adaptor->Initialize(); + typename LevelSetType::Pointer levelSet = adaptor->GetModifiableLevelSet(); + std::cout << "Finished converting to sparse format" << std::endl; + + // The Heaviside function + using HeavisideFunctionType = typename itk::SinRegularizedHeavisideStepFunction< LevelSetRealType, LevelSetRealType >; + typename HeavisideFunctionType::Pointer heaviside = HeavisideFunctionType::New(); + heaviside->SetEpsilon( 1.5 ); + std::cout << "Heaviside function created" << std::endl; + + // Create the level set container + using LevelSetContainerType = typename itk::LevelSetContainer< itk::IdentifierType, LevelSetType >; + typename LevelSetContainerType::Pointer levelSetContainer = LevelSetContainerType::New(); + levelSetContainer->SetHeaviside( heaviside ); + levelSetContainer->AddLevelSet( 0, levelSet ); + std::cout << "LevelSetContainer created" << std::endl; + + // Create the terms. + // + // // Chan and Vese internal term + using ChanAndVeseInternalTermType = itk::LevelSetEquationChanAndVeseInternalTerm< InputImageType, LevelSetContainerType >; + typename ChanAndVeseInternalTermType::Pointer cvInternalTerm = ChanAndVeseInternalTermType::New(); + cvInternalTerm->SetInput( inputImage ); + cvInternalTerm->SetCoefficient( 0.5 ); + std::cout << "Chan and Vese internal term created" << std::endl; + + // // Chan and Vese external term + using ChanAndVeseExternalTermType = typename itk::LevelSetEquationChanAndVeseExternalTerm< InputImageType, LevelSetContainerType >; + typename ChanAndVeseExternalTermType::Pointer cvExternalTerm = ChanAndVeseExternalTermType::New(); + cvExternalTerm->SetInput( inputImage ); + std::cout << "Chan and Vese external term created" << std::endl; + + // Create term container (equation rhs) + using TermContainerType = typename itk::LevelSetEquationTermContainer< InputImageType, LevelSetContainerType >; + typename TermContainerType::Pointer termContainer = TermContainerType::New(); + termContainer->SetLevelSetContainer( levelSetContainer ); + termContainer->SetInput( inputImage ); + termContainer->AddTerm( 0, cvInternalTerm ); + termContainer->AddTerm( 1, cvExternalTerm ); + std::cout << "Term container created" << std::endl; + + // Create equation container + using EquationContainerType = typename itk::LevelSetEquationContainer< TermContainerType >; + typename EquationContainerType::Pointer equationContainer = EquationContainerType::New(); + equationContainer->SetLevelSetContainer( levelSetContainer ); + equationContainer->AddEquation( 0, termContainer ); + std::cout << "Equation container created" << std::endl; + + // Create stopping criteria + using StoppingCriterionType = typename itk::LevelSetEvolutionNumberOfIterationsStoppingCriterion< LevelSetContainerType >; + typename StoppingCriterionType::Pointer criterion = StoppingCriterionType::New(); + criterion->SetNumberOfIterations( numberOfIterations ); + std::cout << "Stopping criteria created" << std::endl; + + // Create the visualizer + using VisualizationType = typename itk::VTKVisualizeImageLevelSetIsoValues< InputImageType, LevelSetType >; + typename VisualizationType::Pointer visualizer = VisualizationType::New(); + //! \todo the visualizer should get the input image from the level set + visualizer->SetInputImage( inputImage ); + visualizer->SetLevelSet( levelSet ); + std::cout << "Visualizer created" << std::endl; + + // Create evolution class + using LevelSetEvolutionType = typename itk::LevelSetEvolution< EquationContainerType, LevelSetType >; + typename LevelSetEvolutionType::Pointer evolution = LevelSetEvolutionType::New(); + evolution->SetEquationContainer( equationContainer ); + evolution->SetStoppingCriterion( criterion ); + evolution->SetLevelSetContainer( levelSetContainer ); + std::cout << "Evolution class created" << std::endl; + + using IterationUpdateCommandType = typename itk::LevelSetIterationUpdateCommand< LevelSetEvolutionType, VisualizationType >; + typename IterationUpdateCommandType::Pointer iterationUpdateCommand = IterationUpdateCommandType::New(); + iterationUpdateCommand->SetFilterToUpdate( visualizer ); + iterationUpdateCommand->SetUpdatePeriod( 4 ); + evolution->AddObserver( itk::IterationEvent(), iterationUpdateCommand ); + std::cout << "Visualization IterationUpdateCommand created" << std::endl; + + std::cout << "Evolving the level set..." << std::endl; + evolution->Update(); + + //! \todo Write out the final visualization image. +} + +int itkVTKVisualize2DCellsLevelSetTest( int argc, char* argv[] ) +{ + if( argc < 5 ) + { + std::cerr << "Missing Arguments" << std::endl; + std::cerr << argv[0] << std::endl; + std::cerr << "1- Input Image" << std::endl; + std::cerr << "2- Number of Iterations" << std::endl; + std::cerr << "3- LevelSet Representation (Dense, Whitaker, Shi, Malcolm)" << std::endl; + std::cerr << "4- Output Image" << std::endl; + + return EXIT_FAILURE; + } + + // Image Dimension + constexpr unsigned int Dimension = 2; + + using InputPixelType = unsigned char; + using InputImageType = itk::Image< InputPixelType, Dimension >; + + // Read input image (to be processed). + using ReaderType = itk::ImageFileReader< InputImageType >; + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName( argv[1] ); + reader->Update(); + InputImageType::Pointer input = reader->GetOutput(); + std::cout << "Input image read" << std::endl; + + int numberOfIterations; + std::istringstream istrm( argv[2] ); + istrm >> numberOfIterations; + + std::string levelSetRepresentation = argv[3]; + if( levelSetRepresentation.compare( "Dense" ) == 0 ) + { + using LevelSetPixelType = float; + using LevelSetImageType = itk::Image< LevelSetPixelType, Dimension >; + using LevelSetType = itk::LevelSetDenseImage< LevelSetImageType >; + try + { + visualizeLevelSet< InputImageType, LevelSetType >( input, numberOfIterations, argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Whitaker" ) == 0 ) + { + using LevelSetType = itk::WhitakerSparseLevelSetImage< double, Dimension >; + try + { + visualizeLevelSet< InputImageType, LevelSetType >( input, + numberOfIterations, + argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Shi" ) == 0 ) + { + using LevelSetType = itk::ShiSparseLevelSetImage< Dimension >; + try + { + visualizeLevelSet< InputImageType, LevelSetType >( input, + numberOfIterations, + argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else if( levelSetRepresentation.compare( "Malcolm" ) == 0 ) + { + using LevelSetType = itk::MalcolmSparseLevelSetImage< Dimension >; + try + { + visualizeLevelSet< InputImageType, LevelSetType >( input, + numberOfIterations, + argv[4] ); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + } + else + { + std::cerr << "Unknown level set representation " << levelSetRepresentation << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DDenseImageLevelSetTest.cxx b/test/itkVTKVisualize2DDenseImageLevelSetTest.cxx new file mode 100644 index 0000000..b2c0a11 --- /dev/null +++ b/test/itkVTKVisualize2DDenseImageLevelSetTest.cxx @@ -0,0 +1,107 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkVTKVisualizeImageLevelSetIsoValues.h" + +#include "itkLevelSetImage.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } + +} + +int itkVTKVisualize2DDenseImageLevelSetTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetOutputType = double; + + using LevelSetImageType = itk::Image< LevelSetOutputType, Dimension >; + + using LevelSetType = itk::LevelSetDenseImage< LevelSetImageType >; + + LevelSetImageType::Pointer LevelSetImage = LevelSetImageType::New(); + GenerateImage< LevelSetImageType >( LevelSetImage ); + + using IteratorType = itk::ImageRegionIteratorWithIndex< LevelSetImageType >; + IteratorType it( LevelSetImage, LevelSetImage->GetLargestPossibleRegion() ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + LevelSetImageType::IndexType idx = it.GetIndex(); + auto value = static_cast< LevelSetOutputType >( ( idx[0] - 25 ) * ( idx[0] - 25 ) + + ( idx[1] - 25 ) * ( idx[1] - 25 ) ); + value = std::sqrt( value ) - 20; + it.Set( value ); + ++it; + } + + LevelSetType::Pointer levelset = LevelSetType::New(); + levelset->SetImage( LevelSetImage ); + + using VisualizationType = itk::VTKVisualizeImageLevelSetIsoValues< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( levelset ); + viewer->SetScreenCapture( true ); + viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DLevelSetAsElevationMapTest.cxx b/test/itkVTKVisualize2DLevelSetAsElevationMapTest.cxx new file mode 100644 index 0000000..39c6c97 --- /dev/null +++ b/test/itkVTKVisualize2DLevelSetAsElevationMapTest.cxx @@ -0,0 +1,135 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkLevelSetImage.h" +#include "itkLevelSetDenseImage.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" +#include "itkVTKVisualize2DLevelSetAsElevationMap.h" + +#include "vtkPolyData.h" +#include "vtkMassProperties.h" +#include "vtkSmartPointer.h" + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size[0]=50; + size[1]=49; + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } + +} + +int itkVTKVisualize2DLevelSetAsElevationMapTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetOutputType = double; + + using LevelSetImageType = itk::Image< LevelSetOutputType, Dimension >; + + using LevelSetType = itk::LevelSetDenseImage< LevelSetImageType >; + + LevelSetImageType::Pointer LevelSetImage = LevelSetImageType::New(); + GenerateImage< LevelSetImageType >( LevelSetImage ); + + using IteratorType = itk::ImageRegionIteratorWithIndex< LevelSetImageType >; + IteratorType it( LevelSetImage, LevelSetImage->GetLargestPossibleRegion() ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + LevelSetImageType::IndexType idx = it.GetIndex(); + auto value = static_cast< LevelSetOutputType >( ( idx[0] - 25 ) * ( idx[0] - 25 ) + + ( idx[1] - 25 ) * ( idx[1] - 25 ) ); + value = std::sqrt( value ) - 20; + it.Set( value ); + ++it; + } + + LevelSetType::Pointer levelset = LevelSetType::New(); + levelset->SetImage( LevelSetImage ); + + using VisualizationType = itk::VTKVisualize2DLevelSetAsElevationMap< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( levelset ); + viewer->SetScreenCapture( true ); + viewer->SetHeightScaling( 0.1 ); + viewer->Update(); + + vtkPolyData* levelsetSurface = viewer->GetElevationMapMesh(); + vtkCellArray* cells = levelsetSurface->GetPolys(); + + vtkSmartPointer massProperty = vtkSmartPointer::New(); +#if VTK_MAJOR_VERSION <= 5 + massProperty->SetInput( levelsetSurface ); +#else + massProperty->SetInputData( levelsetSurface ); +#endif + double averageSurfaceAreaPerCell = massProperty->GetSurfaceArea()/cells->GetNumberOfCells(); + + if ( averageSurfaceAreaPerCell > 2.5 ) + { + std::cerr << "Average surface area per cell too high." << std::endl; + return EXIT_FAILURE; + } + + if ( viewer->GetHeightScaling() != 0.1) + { + std::cerr << "HeightScaling not set correctly." << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DMalcolmLevelSetLayersTest.cxx b/test/itkVTKVisualize2DMalcolmLevelSetLayersTest.cxx new file mode 100644 index 0000000..94a58f4 --- /dev/null +++ b/test/itkVTKVisualize2DMalcolmLevelSetLayersTest.cxx @@ -0,0 +1,92 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkVTKVisualize2DSparseLevelSetLayers.h" + +#include "itkMalcolmSparseLevelSetImage.h" +#include "itkBinaryImageToLevelSetImageAdaptor.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } + +} + +int itkVTKVisualize2DMalcolmLevelSetLayersTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetType = itk::MalcolmSparseLevelSetImage< Dimension >; + using BinaryToSparseAdaptorType = itk::BinaryImageToLevelSetImageAdaptor< + ImageType, LevelSetType >; + + BinaryToSparseAdaptorType::Pointer adaptor = BinaryToSparseAdaptorType::New(); + adaptor->SetInputImage( image ); + adaptor->Initialize(); + + LevelSetType::Pointer LevelSet = adaptor->GetModifiableLevelSet(); + + using VisualizationType = itk::VTKVisualize2DSparseLevelSetLayers< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( LevelSet ); + viewer->SetScreenCapture( true ); + viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DMalcolmLevelSetTest.cxx b/test/itkVTKVisualize2DMalcolmLevelSetTest.cxx new file mode 100644 index 0000000..0d18318 --- /dev/null +++ b/test/itkVTKVisualize2DMalcolmLevelSetTest.cxx @@ -0,0 +1,93 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "vtkVisualize2DLevelSetImage.h" + +#include "itkMalcolmSparseLevelSetImage.h" +#include "itkBinaryImageToLevelSetImageAdaptor.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } + +} + +int vtkVisualize2DMalcolmLevelSetTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetType = itk::MalcolmSparseLevelSetImage< Dimension >; + using BinaryToSparseAdaptorType = itk::BinaryImageToLevelSetImageAdaptor< + ImageType, LevelSetType >; + + BinaryToSparseAdaptorType::Pointer adaptor = BinaryToSparseAdaptorType::New(); + adaptor->SetInputImage( image ); + adaptor->Initialize(); + + LevelSetType::Pointer LevelSet = adaptor->GetLevelSet(); + +// using VisualizationType = vtkVisualize2DLevelSetImage< ImageType, SparseLevelSetType::ImageType >; +// VisualizationType::Pointer viewer = VisualizationType::New(); +// viewer->SetInputImage( image ); +// viewer->SetLevelSet( LevelSet ); +// viewer->SetNumberOfLevels( 3 ); +// viewer->SetLevelLimit( 1. ); +// viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DShiLevelSetLayersTest.cxx b/test/itkVTKVisualize2DShiLevelSetLayersTest.cxx new file mode 100644 index 0000000..49fa265 --- /dev/null +++ b/test/itkVTKVisualize2DShiLevelSetLayersTest.cxx @@ -0,0 +1,93 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkVTKVisualize2DSparseLevelSetLayers.h" + +#include "itkShiSparseLevelSetImage.h" +#include "itkBinaryImageToLevelSetImageAdaptor.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } +} + +int itkVTKVisualize2DShiLevelSetLayersTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetType = itk::ShiSparseLevelSetImage< Dimension >; + + using BinaryToLevelSetAdaptorType = itk::BinaryImageToLevelSetImageAdaptor< ImageType, + LevelSetType >; + + BinaryToLevelSetAdaptorType::Pointer adaptor = BinaryToLevelSetAdaptorType::New(); + adaptor->SetInputImage( image ); + adaptor->Initialize(); + + using SparseLevelSetType = BinaryToLevelSetAdaptorType::LevelSetType; + SparseLevelSetType::Pointer LevelSet = adaptor->GetModifiableLevelSet(); + + using VisualizationType = itk::VTKVisualize2DSparseLevelSetLayers< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( LevelSet ); + viewer->SetScreenCapture( true ); + viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DWhitakerLevelSetLayersTest.cxx b/test/itkVTKVisualize2DWhitakerLevelSetLayersTest.cxx new file mode 100644 index 0000000..bfdbbaf --- /dev/null +++ b/test/itkVTKVisualize2DWhitakerLevelSetLayersTest.cxx @@ -0,0 +1,97 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkVTKVisualize2DSparseLevelSetLayers.h" + +#include "itkWhitakerSparseLevelSetImage.h" +#include "itkBinaryImageToLevelSetImageAdaptor.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } + +} + +int itkVTKVisualize2DWhitakerLevelSetLayersTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetOutputType = double; + + using LevelSetType = + itk::WhitakerSparseLevelSetImage< LevelSetOutputType, Dimension >; + + using BinaryToSparseAdaptorType = + itk::BinaryImageToLevelSetImageAdaptor< ImageType, LevelSetType >; + + BinaryToSparseAdaptorType::Pointer adaptor = BinaryToSparseAdaptorType::New(); + adaptor->SetInputImage( image ); + adaptor->Initialize(); + + LevelSetType::Pointer LevelSet = adaptor->GetModifiableLevelSet(); + + using VisualizationType = + itk::VTKVisualize2DSparseLevelSetLayers< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( LevelSet ); + viewer->SetScreenCapture( true ); + viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize2DWhitakerLevelSetTest.cxx b/test/itkVTKVisualize2DWhitakerLevelSetTest.cxx new file mode 100644 index 0000000..86e70fc --- /dev/null +++ b/test/itkVTKVisualize2DWhitakerLevelSetTest.cxx @@ -0,0 +1,99 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkVTKVisualizeImageLevelSetIsoValues.h" + +#include "itkWhitakerSparseLevelSetImage.h" +#include "itkBinaryImageToLevelSetImageAdaptor.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 10 ); + region.SetIndex( index ); + + size.Fill( 30 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } + +} + +int itkVTKVisualize2DWhitakerLevelSetTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 2; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetOutputType = double; + + using LevelSetType = + itk::WhitakerSparseLevelSetImage< LevelSetOutputType, Dimension >; + + using BinaryToSparseAdaptorType = + itk::BinaryImageToLevelSetImageAdaptor< ImageType, LevelSetType >; + + BinaryToSparseAdaptorType::Pointer adaptor = BinaryToSparseAdaptorType::New(); + adaptor->SetInputImage( image ); + adaptor->Initialize(); + + LevelSetType::Pointer LevelSet = adaptor->GetModifiableLevelSet(); + + using VisualizationType = + itk::VTKVisualizeImageLevelSetIsoValues< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( LevelSet ); + viewer->SetLevelLimit( 3. ); + viewer->SetNumberOfLevels( 7 ); + viewer->SetScreenCapture( true ); + viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize3DDenseImageLevelSetTest.cxx b/test/itkVTKVisualize3DDenseImageLevelSetTest.cxx new file mode 100644 index 0000000..0e44e74 --- /dev/null +++ b/test/itkVTKVisualize3DDenseImageLevelSetTest.cxx @@ -0,0 +1,107 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkVTKVisualizeImageLevelSetIsoValues.h" + +#include "itkLevelSetDenseImage.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 5 ); + region.SetIndex( index ); + + size.Fill( 40 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } +} + +int itkVTKVisualize3DDenseImageLevelSetTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 3; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetOutputType = double; + + using LevelSetImageType = itk::Image< LevelSetOutputType, Dimension >; + + using LevelSetType = itk::LevelSetDenseImage< LevelSetImageType >; + + LevelSetImageType::Pointer LevelSetImage = LevelSetImageType::New(); + GenerateImage< LevelSetImageType >( LevelSetImage ); + + using IteratorType = itk::ImageRegionIteratorWithIndex< LevelSetImageType >; + IteratorType it( LevelSetImage, LevelSetImage->GetLargestPossibleRegion() ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + LevelSetImageType::IndexType idx = it.GetIndex(); + auto value = static_cast< LevelSetOutputType >( ( idx[0] - 25 ) * ( idx[0] - 25 ) + + ( idx[1] - 25 ) * ( idx[1] - 25 ) + + ( idx[2] - 25 ) * ( idx[2] - 25 ) ); + value = std::sqrt( value ) - 20; + it.Set( value ); + ++it; + } + + LevelSetType::Pointer levelset = LevelSetType::New(); + levelset->SetImage( LevelSetImage ); + + using VisualizationType = itk::VTKVisualizeImageLevelSetIsoValues< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( levelset ); + viewer->SetScreenCapture( true ); + viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualize3DWhitakerLevelSetTest.cxx b/test/itkVTKVisualize3DWhitakerLevelSetTest.cxx new file mode 100644 index 0000000..b3f422d --- /dev/null +++ b/test/itkVTKVisualize3DWhitakerLevelSetTest.cxx @@ -0,0 +1,97 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include "itkVTKVisualizeImageLevelSetIsoValues.h" + +#include "itkWhitakerSparseLevelSetImage.h" +#include "itkBinaryImageToLevelSetImageAdaptor.h" + +#include "itkImage.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionIteratorWithIndex.h" + + +template< typename TImage > +void GenerateImage( typename TImage::Pointer ioImage ) +{ + typename TImage::IndexType index; + index.Fill( 0 ); + + typename TImage::SizeType size; + size.Fill( 50 ); + + typename TImage::RegionType region; + region.SetIndex( index ); + region.SetSize( size ); + + using PixelType = typename TImage::PixelType; + + ioImage->SetRegions( region ); + ioImage->Allocate(); + ioImage->FillBuffer( itk::NumericTraits< PixelType >::ZeroValue() ); + + index.Fill( 5 ); + region.SetIndex( index ); + + size.Fill( 40 ); + region.SetSize( size ); + + typename itk::ImageRegionIterator< TImage > it( ioImage, region ); + it.GoToBegin(); + + while( !it.IsAtEnd() ) + { + it.Set( itk::NumericTraits< PixelType >::max() ); + ++it; + } + +} + +int itkVTKVisualize3DWhitakerLevelSetTest( int , char* [] ) +{ + using PixelType = unsigned char; + constexpr unsigned int Dimension = 3; + using ImageType = itk::Image< PixelType, Dimension >; + + ImageType::Pointer image = ImageType::New(); + GenerateImage< ImageType >( image ); + + using LevelSetOutputType = double; + + using LevelSetType = + itk::WhitakerSparseLevelSetImage< LevelSetOutputType, Dimension >; + + using BinaryToSparseAdaptorType = + itk::BinaryImageToLevelSetImageAdaptor< ImageType, LevelSetType >; + + BinaryToSparseAdaptorType::Pointer adaptor = BinaryToSparseAdaptorType::New(); + adaptor->SetInputImage( image ); + adaptor->Initialize(); + + LevelSetType::Pointer levelSet = adaptor->GetModifiableLevelSet(); + + using VisualizationType = + itk::VTKVisualizeImageLevelSetIsoValues< ImageType, LevelSetType >; + VisualizationType::Pointer viewer = VisualizationType::New(); + viewer->SetInputImage( image ); + viewer->SetLevelSet( levelSet ); + viewer->SetScreenCapture( true ); + viewer->Update(); + + return EXIT_SUCCESS; +} diff --git a/test/itkVTKVisualizeLevelSetsInteractivePauseTest.cxx b/test/itkVTKVisualizeLevelSetsInteractivePauseTest.cxx new file mode 100644 index 0000000..aa020a4 --- /dev/null +++ b/test/itkVTKVisualizeLevelSetsInteractivePauseTest.cxx @@ -0,0 +1,407 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#include "itkBinaryImageToLevelSetImageAdaptor.h" +#include "itkImageFileReader.h" +#include "itkCommand.h" +#include "itkLevelSetContainer.h" +#include "itkLevelSetEquationChanAndVeseInternalTerm.h" +#include "itkLevelSetEquationChanAndVeseExternalTerm.h" +#include "itkLevelSetEquationContainer.h" +#include "itkLevelSetEquationTermContainer.h" +#include "itkLevelSetEvolution.h" +#include "itkLevelSetEvolutionNumberOfIterationsStoppingCriterion.h" +#include "itkLevelSetDenseImage.h" +#include +#include +#include "itkVTKVisualizeImageLevelSetIsoValues.h" +#include "itkSinRegularizedHeavisideStepFunction.h" + +#include "vtkCommand.h" +#include "vtkRenderWindow.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkInteractorStyleImage.h" + +#include + +struct NeedToPauseInformation +{ + std::mutex m_Mutex; + std::condition_variable m_ConditionVariable; + bool m_NeedToPause = false; + bool m_NeedToUpdateViz = false; +}; + +/** \class ProcessingPauseCommand + * Pause level sets processing so that the user can examine it or to render the + * data. */ +class ProcessingPauseCommand: public itk::Command +{ +public: + using Self = ProcessingPauseCommand; + using Superclass = Command; + using Pointer = itk::SmartPointer< Self >; + + itkNewMacro( Self ); + + ProcessingPauseCommand(){} + + void Execute( const itk::Object* caller, const itk::EventObject& event ) override + { + this->Execute( const_cast< itk::Object* >( caller ), event ); + } + + void Execute( itk::Object* itkNotUsed(caller), const itk::EventObject& event ) override + { + if( itk::IterationEvent().CheckEvent( &event )) + { + std::unique_lock< std::mutex > mutexHolder( this->m_NeedToPauseInformation->m_Mutex ); + std::cout << "An iteration occurred, checking if we need to pause...." << std::endl; + if( this->m_NeedToPauseInformation->m_NeedToPause || this->m_NeedToPauseInformation->m_NeedToUpdateViz ) + { + this->m_NeedToPauseInformation->m_ConditionVariable.wait( mutexHolder ); + std::cout << "Done pausing..." << std::endl; + } + } + } + + void SetNeedToPauseInformation( NeedToPauseInformation * pauseInfo ) + { + this->m_NeedToPauseInformation = pauseInfo; + } + +private: + NeedToPauseInformation * m_NeedToPauseInformation; +}; + +/** \class KeypressPauseCommand + * The VTK class to detect the keypress and signal that a pause is needed. + * */ +template +class KeypressPauseCommand: public vtkCommand +{ +public: + using LevelSetPixelType = float; + static constexpr unsigned int Dimension = TInputImage::ImageDimension; + using LevelSetImageType = itk::Image< LevelSetPixelType, Dimension >; + using LevelSetType = itk::LevelSetDenseImage< LevelSetImageType >; + using VisualizationType = itk::VTKVisualizeImageLevelSetIsoValues< TInputImage, LevelSetType >; + + KeypressPauseCommand(){} + + static KeypressPauseCommand * New() + { + // Create the visualizer + auto * keypressPauseCommand = new KeypressPauseCommand; + keypressPauseCommand->m_Visualizer = VisualizationType::New(); + keypressPauseCommand->m_Visualizer->SetNumberOfLevels( 5 ); + keypressPauseCommand->m_Visualizer->SetLevelLimit( 4.0 ); + + std::cout << "Visualizer created" << std::endl; + return keypressPauseCommand; + } + + void Execute( vtkObject * vtkNotUsed(caller), unsigned long eventId, void * vtkNotUsed(callData) ) override + { + if( vtkCommand::TimerEvent == eventId ) + { + bool weArePaused; + bool weWantToUpdateViz; + this->m_NeedToPauseInformation->m_Mutex.lock(); + //std::cout << "We got a timer event" << std::endl; + weArePaused = this->m_NeedToPauseInformation->m_NeedToPause; + weWantToUpdateViz = this->m_NeedToPauseInformation->m_NeedToUpdateViz; + if( !weArePaused || (weArePaused && weWantToUpdateViz) ) + { + // do a render + // of the modified level set + if( weWantToUpdateViz ) + { + std::cout << "Updating the Visualization.." << std::endl; + this->m_Visualizer->Update(); + this->m_Visualizer->GetRenderer()->ResetCamera(); + this->m_NeedToPauseInformation->m_NeedToUpdateViz = false; + this->m_NeedToPauseInformation->m_ConditionVariable.notify_one(); + } + else // do it the next time around + { + this->m_NeedToPauseInformation->m_NeedToUpdateViz = true; + } + } + this->m_NeedToPauseInformation->m_Mutex.unlock(); + } + else if( vtkCommand::KeyPressEvent == eventId ) + { + this->m_NeedToPauseInformation->m_Mutex.lock(); + std::cout << "Got a keypress event..." << std::endl; + bool weArePaused = this->m_NeedToPauseInformation->m_NeedToPause; + if( weArePaused ) + { + this->m_NeedToPauseInformation->m_NeedToPause = false; + this->m_NeedToPauseInformation->m_ConditionVariable.notify_one(); + } + else + { + this->m_NeedToPauseInformation->m_NeedToPause = true; + } + this->m_NeedToPauseInformation->m_Mutex.unlock(); + } + } + + void SetNeedToPauseInformation( NeedToPauseInformation * pauseInfo ) + { + this->m_NeedToPauseInformation = pauseInfo; + } + + VisualizationType * GetVisualizer() + { + return this->m_Visualizer.GetPointer(); + } + +private: + NeedToPauseInformation * m_NeedToPauseInformation; + typename VisualizationType::Pointer m_Visualizer; +}; + +template< typename TInputImage > +void +visualizeLevelSet( TInputImage * inputImage, + const int numberOfIterations, + ProcessingPauseCommand * pauseCommand, + KeypressPauseCommand * keypressCommand ) +{ + using LevelSetType = typename KeypressPauseCommand::LevelSetType; + using LevelSetOutputType = typename LevelSetType::OutputType; + using LevelSetRealType = typename LevelSetType::OutputRealType; + + // Generate a binary mask that will be used as initialization for the level + // set evolution. + using BinaryImageType = typename itk::Image< LevelSetOutputType, TInputImage::ImageDimension >; + typename BinaryImageType::Pointer binary = BinaryImageType::New(); + binary->SetRegions( inputImage->GetLargestPossibleRegion() ); + binary->CopyInformation( inputImage ); + binary->Allocate(); + binary->FillBuffer( itk::NumericTraits< LevelSetOutputType >::ZeroValue() ); + + typename BinaryImageType::RegionType region; + typename BinaryImageType::IndexType index; + typename BinaryImageType::SizeType size; + + index.Fill( 5 ); + size.Fill( 120 ); + + region.SetIndex( index ); + region.SetSize( size ); + + using InputIteratorType = itk::ImageRegionIteratorWithIndex< BinaryImageType >; + InputIteratorType iIt( binary, region ); + iIt.GoToBegin(); + while( !iIt.IsAtEnd() ) + { + iIt.Set( itk::NumericTraits< LevelSetOutputType >::OneValue() ); + ++iIt; + } + + using BinaryImageToLevelSetType = itk::BinaryImageToLevelSetImageAdaptor< BinaryImageType, + LevelSetType >; + + typename BinaryImageToLevelSetType::Pointer adaptor = BinaryImageToLevelSetType::New(); + adaptor->SetInputImage( binary ); + adaptor->Initialize(); + typename LevelSetType::Pointer levelSet = adaptor->GetModifiableLevelSet(); + std::cout << "Finished converting to sparse format" << std::endl; + + // The Heaviside function + using HeavisideFunctionType = typename itk::SinRegularizedHeavisideStepFunction< LevelSetRealType, LevelSetRealType >; + typename HeavisideFunctionType::Pointer heaviside = HeavisideFunctionType::New(); + heaviside->SetEpsilon( 1.5 ); + std::cout << "Heaviside function created" << std::endl; + + // Create the level set container + using LevelSetContainerType = typename itk::LevelSetContainer< itk::IdentifierType, LevelSetType >; + typename LevelSetContainerType::Pointer levelSetContainer = LevelSetContainerType::New(); + levelSetContainer->SetHeaviside( heaviside ); + levelSetContainer->AddLevelSet( 0, levelSet ); + std::cout << "LevelSetContainer created" << std::endl; + + // Create the terms. + // + // // Chan and Vese internal term + using ChanAndVeseInternalTermType = itk::LevelSetEquationChanAndVeseInternalTerm< TInputImage, LevelSetContainerType >; + typename ChanAndVeseInternalTermType::Pointer cvInternalTerm = ChanAndVeseInternalTermType::New(); + cvInternalTerm->SetInput( inputImage ); + cvInternalTerm->SetCoefficient( 0.5 ); + std::cout << "Chan and Vese internal term created" << std::endl; + + // // Chan and Vese external term + using ChanAndVeseExternalTermType = typename itk::LevelSetEquationChanAndVeseExternalTerm< TInputImage, LevelSetContainerType >; + typename ChanAndVeseExternalTermType::Pointer cvExternalTerm = ChanAndVeseExternalTermType::New(); + cvExternalTerm->SetInput( inputImage ); + std::cout << "Chan and Vese external term created" << std::endl; + + // Create term container (equation rhs) + using TermContainerType = typename itk::LevelSetEquationTermContainer< TInputImage, LevelSetContainerType >; + typename TermContainerType::Pointer termContainer = TermContainerType::New(); + termContainer->SetLevelSetContainer( levelSetContainer ); + termContainer->SetInput( inputImage ); + termContainer->AddTerm( 0, cvInternalTerm ); + termContainer->AddTerm( 1, cvExternalTerm ); + std::cout << "Term container created" << std::endl; + + // Create equation container + using EquationContainerType = typename itk::LevelSetEquationContainer< TermContainerType >; + typename EquationContainerType::Pointer equationContainer = EquationContainerType::New(); + equationContainer->SetLevelSetContainer( levelSetContainer ); + equationContainer->AddEquation( 0, termContainer ); + std::cout << "Equation container created" << std::endl; + + // Create stopping criteria + using StoppingCriterionType = typename itk::LevelSetEvolutionNumberOfIterationsStoppingCriterion< LevelSetContainerType >; + typename StoppingCriterionType::Pointer criterion = StoppingCriterionType::New(); + criterion->SetNumberOfIterations( numberOfIterations ); + std::cout << "Stopping criteria created" << std::endl; + + + // Create evolution class + using LevelSetEvolutionType = typename itk::LevelSetEvolution< EquationContainerType, LevelSetType >; + typename LevelSetEvolutionType::Pointer evolution = LevelSetEvolutionType::New(); + evolution->SetEquationContainer( equationContainer ); + evolution->SetStoppingCriterion( criterion ); + evolution->SetLevelSetContainer( levelSetContainer ); + std::cout << "Evolution class created" << std::endl; + evolution->AddObserver( itk::IterationEvent(), pauseCommand ); + keypressCommand->GetVisualizer()->SetLevelSet( levelSet ); + //! \todo the visualizer should get the input image from the level set + keypressCommand->GetVisualizer()->SetInputImage( inputImage ); + std::cout << "ProcessingPauseCommand observing" << std::endl; + + std::cout << "Evolving the level set..." << std::endl; + evolution->Update(); +} + + +class ExitOnTimer: public vtkCommand +{ +public: + ExitOnTimer(){} + + static ExitOnTimer * New() + { + return new ExitOnTimer; + } + + void Execute( vtkObject * caller, unsigned long eventId, void * callData ) override + { + if( vtkCommand::TimerEvent == eventId ) + { + int timerId = * static_cast( callData ); + if( timerId == this->m_TimerId ) + { + vtkRenderWindowInteractor * renderWindowInteractor = vtkRenderWindowInteractor::SafeDownCast( caller ); + renderWindowInteractor->ExitCallback(); + } + } + } + + void SetTimerId( const int id ) + { + this->m_TimerId = id; + } + +private: + int m_TimerId; +}; + +int itkVTKVisualizeLevelSetsInteractivePauseTest( int argc, char* argv[] ) +{ + if( argc < 3 ) + { + std::cerr << "Missing Arguments" << std::endl; + std::cerr << argv[0] << std::endl; + std::cerr << "1- Input Image" << std::endl; + std::cerr << "2- Number of Iterations" << std::endl; + + return EXIT_FAILURE; + } + + // Image Dimension + constexpr unsigned int Dimension = 2; + using InputPixelType = unsigned char; + using InputImageType = itk::Image< InputPixelType, Dimension >; + + + // Read input image (to be processed). + using ReaderType = itk::ImageFileReader< InputImageType >; + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName( argv[1] ); + reader->Update(); + InputImageType::Pointer input = reader->GetOutput(); + std::cout << "Input image read" << std::endl; + + int numberOfIterations; + std::istringstream istrm( argv[2] ); + istrm >> numberOfIterations; + + NeedToPauseInformation needToPauseInformation; + + ProcessingPauseCommand::Pointer processingPauseCommand = ProcessingPauseCommand::New(); + processingPauseCommand->SetNeedToPauseInformation( &needToPauseInformation ); + + using KPCType = KeypressPauseCommand; + vtkSmartPointer< KPCType > keypressPauseCommand = vtkSmartPointer< KPCType >::New(); + keypressPauseCommand->SetNeedToPauseInformation( &needToPauseInformation ); + vtkSmartPointer< vtkRenderWindow > renderWindow = vtkSmartPointer< vtkRenderWindow >::New(); + keypressPauseCommand->GetVisualizer()->SetRenderWindow( renderWindow ); + + vtkSmartPointer< vtkRenderWindowInteractor > renderWindowInteractor = vtkSmartPointer< vtkRenderWindowInteractor >::New(); + renderWindowInteractor->SetRenderWindow( renderWindow ); + renderWindowInteractor->Initialize(); + renderWindowInteractor->CreateRepeatingTimer( 50 ); + + vtkSmartPointer< vtkInteractorStyleImage > interactorStyle = vtkSmartPointer< vtkInteractorStyleImage >::New(); + renderWindowInteractor->SetInteractorStyle( interactorStyle ); + + int timerId = renderWindowInteractor->CreateOneShotTimer( 10000 ); + vtkSmartPointer< ExitOnTimer > exitOnTimer = vtkSmartPointer< ExitOnTimer >::New(); + exitOnTimer->SetTimerId( timerId ); + + renderWindowInteractor->AddObserver( vtkCommand::TimerEvent, exitOnTimer ); + renderWindowInteractor->AddObserver( vtkCommand::TimerEvent, keypressPauseCommand ); + renderWindowInteractor->AddObserver( vtkCommand::KeyPressEvent, keypressPauseCommand ); + + try + { + std::thread visThread( + visualizeLevelSet< InputImageType >, + input.GetPointer(), + numberOfIterations, + processingPauseCommand.GetPointer(), + keypressPauseCommand.GetPointer() + ); + renderWindowInteractor->Start(); + std::cout << "The spawned thread was: " << visThread.get_id() << std::endl; + std::cout << "TerminatingThread..." << std::endl; + visThread.join(); + } + catch ( itk::ExceptionObject& err ) + { + std::cerr << err << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +}