diff --git a/Modules/AlgorithmsExt/include/mitkMaskAndCutRoiImageFilter.h b/Modules/AlgorithmsExt/include/mitkMaskAndCutRoiImageFilter.h index be17583bbb..195fa6675b 100644 --- a/Modules/AlgorithmsExt/include/mitkMaskAndCutRoiImageFilter.h +++ b/Modules/AlgorithmsExt/include/mitkMaskAndCutRoiImageFilter.h @@ -1,77 +1,72 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkMaskAndCutRoiImageFilter_h #define mitkMaskAndCutRoiImageFilter_h #include "MitkAlgorithmsExtExports.h" #include "mitkImageToImageFilter.h" #include "itkRegionOfInterestImageFilter.h" #include "mitkAutoCropImageFilter.h" #include "mitkBoundingObject.h" #include "mitkDataNode.h" #include "mitkMaskImageFilter.h" namespace mitk { /** \brief Cuts a region of interest (ROI) out of an image In the first step, this filter reduces the image region of the given ROI to a minimum. Using this region, a subvolume ist cut out of the given input image. The ROI is then used to mask the subvolume. Pixel inside the ROI will have their original value, pixel outside will be replaced by m_OutsideValue */ class MITKALGORITHMSEXT_EXPORT MaskAndCutRoiImageFilter : public ImageToImageFilter { typedef itk::Image<short, 3> ItkImageType; typedef itk::Image<unsigned char, 3> ItkMaskType; typedef itk::ImageRegion<3> RegionType; typedef itk::RegionOfInterestImageFilter<ItkImageType, ItkImageType> ROIFilterType; public: mitkClassMacro(MaskAndCutRoiImageFilter, ImageToImageFilter); itkFactorylessNewMacro(Self); itkCloneMacro(Self); - itkGetMacro(MaxValue, mitk::ScalarType); - itkGetMacro(MinValue, mitk::ScalarType); void SetRegionOfInterest(mitk::BaseData *roi); // void SetRegionOfInterest(Image::Pointer image); // void SetRegionOfInterest(BoundingObject::Pointer boundingObject); // void SetRegionOfInterestByNode(mitk::DataNode::Pointer node); // temporary fix for bug # mitk::Image::Pointer GetOutput(); protected: MaskAndCutRoiImageFilter(); ~MaskAndCutRoiImageFilter() override; void GenerateData() override; ROIFilterType::Pointer m_RoiFilter; mitk::AutoCropImageFilter::Pointer m_CropFilter; mitk::MaskImageFilter::Pointer m_MaskFilter; // needed for temporary fix mitk::Image::Pointer m_outputImage; - mitk::ScalarType m_MaxValue; - mitk::ScalarType m_MinValue; - }; // class } // namespace #endif diff --git a/Modules/AlgorithmsExt/include/mitkMaskImageFilter.h b/Modules/AlgorithmsExt/include/mitkMaskImageFilter.h index ced7d4cb2b..9a8e1b1482 100644 --- a/Modules/AlgorithmsExt/include/mitkMaskImageFilter.h +++ b/Modules/AlgorithmsExt/include/mitkMaskImageFilter.h @@ -1,111 +1,93 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkMaskImageFilter_h #define mitkMaskImageFilter_h #include "MitkAlgorithmsExtExports.h" #include "mitkCommon.h" -#include "mitkImageTimeSelector.h" #include "mitkImageToImageFilter.h" #include "itkImage.h" namespace mitk { //##Documentation //## @brief //## @ingroup Process class MITKALGORITHMSEXT_EXPORT MaskImageFilter : public ImageToImageFilter { public: mitkClassMacro(MaskImageFilter, ImageToImageFilter); itkFactorylessNewMacro(Self); itkCloneMacro(Self); - void SetMask(const mitk::Image *mask); - const mitk::Image *GetMask() const; - - /** - * get/set the min Value of the original image in the masked area - **/ - itkGetMacro(MinValue, mitk::ScalarType); - itkSetMacro(MinValue, mitk::ScalarType); - - /** - * get/set the max Value of the original image in the masked area - **/ - itkGetMacro(MaxValue, mitk::ScalarType); - itkSetMacro(MaxValue, mitk::ScalarType); + void SetMask(const mitk::Image *mask); + const Image *GetMask() const; + Image* GetMask(); /** * This value is used as outside value. This only works * if OverrideOutsideValue is set to true. Default is 0. **/ itkSetMacro(OutsideValue, mitk::ScalarType); /** * This value is used as outside value. This only works * if OverrideOutsideValue is set to true. Default is 0. */ itkGetMacro(OutsideValue, mitk::ScalarType); /** * If OverrideOutsideValue is set to false, this minimum * of the pixel type of the output image is taken as outside * value. If set to true, the value set via SetOutsideValue is * used as background. */ itkSetMacro(OverrideOutsideValue, bool); /** * If OverrideOutsideValue is set to false, this minimum * of the pixel type of the output image is taken as outside * value. If set to true, the value set via SetOutsideValue is * used as background. */ itkGetMacro(OverrideOutsideValue, bool); itkBooleanMacro(OverrideOutsideValue); protected: MaskImageFilter(); ~MaskImageFilter() override; void GenerateInputRequestedRegion() override; void GenerateOutputInformation() override; void GenerateData() override; - template <typename TPixel, unsigned int VImageDimension> - void InternalComputeMask(itk::Image<TPixel, VImageDimension> *itkImage); - - mitk::Image::Pointer m_Mask; - mitk::ImageTimeSelector::Pointer m_InputTimeSelector; - mitk::ImageTimeSelector::Pointer m_MaskTimeSelector; - mitk::ImageTimeSelector::Pointer m_OutputTimeSelector; + template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2> + void InternalComputeMask(itk::Image<TPixel1, VImageDimension1>* itkInput, itk::Image<TPixel2, VImageDimension2>* itkMask); //##Description //## @brief Time when Header was last initialized itk::TimeStamp m_TimeOfHeaderInitialization; mitk::ScalarType m_OutsideValue; - mitk::ScalarType m_MinValue; - mitk::ScalarType m_MaxValue; + TimeStepType m_CurrentOutputTS; bool m_OverrideOutsideValue; }; } // namespace mitk #endif diff --git a/Modules/AlgorithmsExt/src/mitkMaskAndCutRoiImageFilter.cpp b/Modules/AlgorithmsExt/src/mitkMaskAndCutRoiImageFilter.cpp index 255d1316e1..eb3490c4a7 100644 --- a/Modules/AlgorithmsExt/src/mitkMaskAndCutRoiImageFilter.cpp +++ b/Modules/AlgorithmsExt/src/mitkMaskAndCutRoiImageFilter.cpp @@ -1,92 +1,90 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkMaskAndCutRoiImageFilter.h" #include "mitkBoundingObjectToSegmentationFilter.h" #include "mitkImageCast.h" mitk::MaskAndCutRoiImageFilter::MaskAndCutRoiImageFilter() { this->SetNumberOfRequiredInputs(2); m_CropFilter = mitk::AutoCropImageFilter::New(); m_RoiFilter = ROIFilterType::New(); m_MaskFilter = mitk::MaskImageFilter::New(); } mitk::MaskAndCutRoiImageFilter::~MaskAndCutRoiImageFilter() { } void mitk::MaskAndCutRoiImageFilter::SetRegionOfInterest(mitk::BaseData *roi) { mitk::Image::Pointer image = dynamic_cast<mitk::Image *>(roi); if (image.IsNotNull()) { this->SetInput(1, image); return; } mitk::BoundingObject::Pointer boundingObject = dynamic_cast<mitk::BoundingObject *>(roi); if (boundingObject.IsNotNull() && this->GetInput(0) != nullptr) { mitk::BoundingObjectToSegmentationFilter::Pointer filter = mitk::BoundingObjectToSegmentationFilter::New(); filter->SetBoundingObject(boundingObject); filter->SetInput(this->GetInput(0)); filter->Update(); this->SetInput(1, filter->GetOutput()); return; } } mitk::Image::Pointer mitk::MaskAndCutRoiImageFilter::GetOutput() { return m_outputImage; } void mitk::MaskAndCutRoiImageFilter::GenerateData() { mitk::Image::ConstPointer inputImage = this->GetInput(0); mitk::Image::ConstPointer maskImage = this->GetInput(1); // mitk::Image::Pointer outputImage = this->GetOutput(); // temporary fix for bug # m_outputImage = this->GetOutput(); ItkImageType::Pointer itkImage = ItkImageType::New(); mitk::Image::Pointer tmpImage = mitk::Image::New(); m_CropFilter->SetInput(maskImage); m_CropFilter->SetBackgroundValue(0); m_CropFilter->Update(); RegionType region = m_CropFilter->GetCroppingRegion(); mitk::CastToItkImage(inputImage, itkImage); m_RoiFilter->SetInput(itkImage); m_RoiFilter->SetRegionOfInterest(region); m_RoiFilter->Update(); mitk::CastToMitkImage(m_RoiFilter->GetOutput(), tmpImage); m_MaskFilter->SetInput(0, tmpImage); m_MaskFilter->SetMask(m_CropFilter->GetOutput()); m_MaskFilter->SetOutsideValue(-32765); m_MaskFilter->Update(); - m_MaxValue = m_MaskFilter->GetMaxValue(); - m_MinValue = m_MaskFilter->GetMinValue(); // temporary fix for bug # m_outputImage = m_MaskFilter->GetOutput(); m_outputImage->DisconnectPipeline(); } diff --git a/Modules/AlgorithmsExt/src/mitkMaskImageFilter.cpp b/Modules/AlgorithmsExt/src/mitkMaskImageFilter.cpp index c4d13bff6c..1aac4cb4b8 100644 --- a/Modules/AlgorithmsExt/src/mitkMaskImageFilter.cpp +++ b/Modules/AlgorithmsExt/src/mitkMaskImageFilter.cpp @@ -1,241 +1,132 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkMaskImageFilter.h" #include "mitkImageTimeSelector.h" #include "mitkProperties.h" #include "mitkTimeHelper.h" +#include "mitkImageTimeSelector.h" #include "mitkImageAccessByItk.h" #include "mitkImageToItk.h" -#include "itkImageRegionConstIterator.h" -#include "itkImageRegionIteratorWithIndex.h" +#include "itkMaskImageFilter.h" #include <limits> -mitk::MaskImageFilter::MaskImageFilter() : m_Mask(nullptr) +mitk::MaskImageFilter::MaskImageFilter() { this->SetNumberOfIndexedInputs(2); this->SetNumberOfRequiredInputs(2); - m_InputTimeSelector = mitk::ImageTimeSelector::New(); - m_MaskTimeSelector = mitk::ImageTimeSelector::New(); - m_OutputTimeSelector = mitk::ImageTimeSelector::New(); m_OverrideOutsideValue = false; m_OutsideValue = 0; + m_CurrentOutputTS = 0; } mitk::MaskImageFilter::~MaskImageFilter() { } void mitk::MaskImageFilter::SetMask(const mitk::Image *mask) { // Process object is not const-correct so the const_cast is required here - m_Mask = const_cast<mitk::Image *>(mask); - this->ProcessObject::SetNthInput(1, m_Mask); + auto nonconstMask = const_cast<mitk::Image *>(mask); + this->ProcessObject::SetNthInput(1, nonconstMask); } const mitk::Image *mitk::MaskImageFilter::GetMask() const { - return m_Mask; + return this->GetInput(1); +} + +mitk::Image* mitk::MaskImageFilter::GetMask() +{ + return this->GetInput(1); } void mitk::MaskImageFilter::GenerateInputRequestedRegion() { Superclass::GenerateInputRequestedRegion(); mitk::Image *output = this->GetOutput(); mitk::Image *input = this->GetInput(); - mitk::Image *mask = m_Mask; + mitk::Image *mask = this->GetMask(); if ((output->IsInitialized() == false) || (mask == nullptr) || (mask->GetTimeGeometry()->CountTimeSteps() == 0)) return; input->SetRequestedRegionToLargestPossibleRegion(); mask->SetRequestedRegionToLargestPossibleRegion(); GenerateTimeInInputRegion(output, input); - GenerateTimeInInputRegion(output, mask); } void mitk::MaskImageFilter::GenerateOutputInformation() { mitk::Image::ConstPointer input = this->GetInput(); mitk::Image::Pointer output = this->GetOutput(); if ((output->IsInitialized()) && (this->GetMTime() <= m_TimeOfHeaderInitialization.GetMTime())) return; itkDebugMacro(<< "GenerateOutputInformation()"); output->Initialize(input->GetPixelType(), *input->GetTimeGeometry()); output->SetPropertyList(input->GetPropertyList()->Clone()); m_TimeOfHeaderInitialization.Modified(); } -template <typename TPixel, unsigned int VImageDimension> -void mitk::MaskImageFilter::InternalComputeMask(itk::Image<TPixel, VImageDimension> *inputItkImage) +template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2> +void mitk::MaskImageFilter::InternalComputeMask(itk::Image<TPixel1, VImageDimension1>* itkInput, itk::Image<TPixel2,VImageDimension2>* itkMask) { - // dirty quick fix, duplicating code so both unsigned char and unsigned short are supported - // this should be changed once unsigned char segmentations can be converted to unsigned short - mitk::PixelType pixelType = - m_MaskTimeSelector->GetOutput()->GetImageDescriptor()->GetChannelDescriptor().GetPixelType(); - if (pixelType.GetComponentType() == itk::IOComponentEnum::UCHAR) - { - typedef itk::Image<TPixel, VImageDimension> ItkInputImageType; - typedef itk::Image<unsigned char, VImageDimension> ItkMaskImageType; - typedef itk::Image<TPixel, VImageDimension> ItkOutputImageType; - - typedef itk::ImageRegionConstIterator<ItkInputImageType> ItkInputImageIteratorType; - typedef itk::ImageRegionConstIterator<ItkMaskImageType> ItkMaskImageIteratorType; - typedef itk::ImageRegionIteratorWithIndex<ItkOutputImageType> ItkOutputImageIteratorType; - - typename mitk::ImageToItk<ItkMaskImageType>::Pointer maskimagetoitk = mitk::ImageToItk<ItkMaskImageType>::New(); - maskimagetoitk->SetInput(m_MaskTimeSelector->GetOutput()); - maskimagetoitk->Update(); - typename ItkMaskImageType::Pointer maskItkImage = maskimagetoitk->GetOutput(); - - typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk = - mitk::ImageToItk<ItkOutputImageType>::New(); - outputimagetoitk->SetInput(m_OutputTimeSelector->GetOutput()); - outputimagetoitk->Update(); - typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput(); - - // create the iterators - typename ItkInputImageType::RegionType inputRegionOfInterest = inputItkImage->GetLargestPossibleRegion(); - ItkInputImageIteratorType inputIt(inputItkImage, inputRegionOfInterest); - ItkMaskImageIteratorType maskIt(maskItkImage, inputRegionOfInterest); - ItkOutputImageIteratorType outputIt(outputItkImage, inputRegionOfInterest); - - // typename ItkOutputImageType::PixelType outsideValue = itk::NumericTraits<typename - // ItkOutputImageType::PixelType>::min(); - if (!m_OverrideOutsideValue) - m_OutsideValue = itk::NumericTraits<typename ItkOutputImageType::PixelType>::min(); - - m_MinValue = std::numeric_limits<mitk::ScalarType>::max(); - m_MaxValue = std::numeric_limits<mitk::ScalarType>::min(); - - for (inputIt.GoToBegin(), maskIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd() && !maskIt.IsAtEnd(); - ++inputIt, ++maskIt, ++outputIt) - { - if (maskIt.Get() > itk::NumericTraits<typename ItkMaskImageType::PixelType>::Zero) - { - outputIt.Set(inputIt.Get()); - m_MinValue = std::min((float)inputIt.Get(), (float)m_MinValue); - m_MaxValue = std::max((float)inputIt.Get(), (float)m_MaxValue); - } - else - { - outputIt.Set(m_OutsideValue); - } - } - } - else - { - { - typedef itk::Image<TPixel, VImageDimension> ItkInputImageType; - typedef itk::Image<unsigned short, VImageDimension> ItkMaskImageType; - typedef itk::Image<TPixel, VImageDimension> ItkOutputImageType; - - typedef itk::ImageRegionConstIterator<ItkInputImageType> ItkInputImageIteratorType; - typedef itk::ImageRegionConstIterator<ItkMaskImageType> ItkMaskImageIteratorType; - typedef itk::ImageRegionIteratorWithIndex<ItkOutputImageType> ItkOutputImageIteratorType; - - typename mitk::ImageToItk<ItkMaskImageType>::Pointer maskimagetoitk = mitk::ImageToItk<ItkMaskImageType>::New(); - maskimagetoitk->SetInput(m_MaskTimeSelector->GetOutput()); - maskimagetoitk->Update(); - typename ItkMaskImageType::Pointer maskItkImage = maskimagetoitk->GetOutput(); - - typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk = - mitk::ImageToItk<ItkOutputImageType>::New(); - outputimagetoitk->SetInput(m_OutputTimeSelector->GetOutput()); - outputimagetoitk->Update(); - typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput(); - - // create the iterators - typename ItkInputImageType::RegionType inputRegionOfInterest = inputItkImage->GetLargestPossibleRegion(); - ItkInputImageIteratorType inputIt(inputItkImage, inputRegionOfInterest); - ItkMaskImageIteratorType maskIt(maskItkImage, inputRegionOfInterest); - ItkOutputImageIteratorType outputIt(outputItkImage, inputRegionOfInterest); - - // typename ItkOutputImageType::PixelType outsideValue = itk::NumericTraits<typename - // ItkOutputImageType::PixelType>::min(); - if (!m_OverrideOutsideValue) - m_OutsideValue = itk::NumericTraits<typename ItkOutputImageType::PixelType>::min(); - - m_MinValue = std::numeric_limits<mitk::ScalarType>::max(); - m_MaxValue = std::numeric_limits<mitk::ScalarType>::min(); - - for (inputIt.GoToBegin(), maskIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd() && !maskIt.IsAtEnd(); - ++inputIt, ++maskIt, ++outputIt) - { - if (maskIt.Get() > itk::NumericTraits<typename ItkMaskImageType::PixelType>::Zero) - { - outputIt.Set(inputIt.Get()); - m_MinValue = std::min((float)inputIt.Get(), (float)m_MinValue); - m_MaxValue = std::max((float)inputIt.Get(), (float)m_MaxValue); - } - else - { - outputIt.Set(m_OutsideValue); - } - } - } - } + using MaskFilterType = itk::MaskImageFilter< itk::Image<TPixel1, VImageDimension1>, itk::Image<TPixel2, VImageDimension2>>; + + auto maskFilter = MaskFilterType::New(); + maskFilter->SetInput(itkInput); + maskFilter->SetMaskImage(itkMask); + maskFilter->SetOutsideValue(m_OutsideValue); + maskFilter->Update(); + + auto output = maskFilter->GetOutput(); + + // re-import to MITK + auto mitkOutput = this->GetOutput(); + mitkOutput->SetVolume(output->GetBufferPointer(), m_CurrentOutputTS); } void mitk::MaskImageFilter::GenerateData() { - mitk::Image::ConstPointer input = this->GetInput(); - mitk::Image::Pointer mask = m_Mask; + auto input = this->GetInput(); + auto mask = this->GetMask(); mitk::Image::Pointer output = this->GetOutput(); - if ((output->IsInitialized() == false) || (mask.IsNull()) || (mask->GetTimeGeometry()->CountTimeSteps() == 0)) + if ((output->IsInitialized() == false) || (nullptr == mask) || (mask->GetTimeGeometry()->CountTimeSteps() == 0)) return; - m_InputTimeSelector->SetInput(input); - m_MaskTimeSelector->SetInput(mask); - m_OutputTimeSelector->SetInput(this->GetOutput()); - mitk::Image::RegionType outputRegion = output->GetRequestedRegion(); const mitk::TimeGeometry *outputTimeGeometry = output->GetTimeGeometry(); const mitk::TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); const mitk::TimeGeometry *maskTimeGeometry = mask->GetTimeGeometry(); - ScalarType timeInMS; - int timestep = 0; - int tstart = outputRegion.GetIndex(3); - int tmax = tstart + outputRegion.GetSize(3); - - int t; - for (t = tstart; t < tmax; ++t) + for (TimeStepType t = 0; t < inputTimeGeometry->CountTimeSteps(); ++t) { - timeInMS = outputTimeGeometry->TimeStepToTimePoint(t); - - timestep = inputTimeGeometry->TimePointToTimeStep(timeInMS); - - m_InputTimeSelector->SetTimeNr(timestep); - m_InputTimeSelector->UpdateLargestPossibleRegion(); - m_OutputTimeSelector->SetTimeNr(t); - m_OutputTimeSelector->UpdateLargestPossibleRegion(); - - timestep = maskTimeGeometry->TimePointToTimeStep(timeInMS); - m_MaskTimeSelector->SetTimeNr(timestep); - m_MaskTimeSelector->UpdateLargestPossibleRegion(); + auto timeInMS = outputTimeGeometry->TimeStepToTimePoint(t); - AccessByItk(m_InputTimeSelector->GetOutput(), InternalComputeMask); + m_CurrentOutputTS = t; + auto inputFrame = SelectImageByTimePoint(input, timeInMS); + auto maskFrame = SelectImageByTimePoint(mask, timeInMS); + AccessTwoImagesFixedDimensionByItk(inputFrame, maskFrame, InternalComputeMask, 3); } m_TimeOfHeaderInitialization.Modified(); }