diff --git a/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp b/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp index 3bc01722ad..0f044a368d 100644 --- a/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp +++ b/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp @@ -1,135 +1,147 @@ /*============================================================================ 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 "mitkShapeBasedInterpolationAlgorithm.h" #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include #include #include #include #include mitk::Image::Pointer mitk::ShapeBasedInterpolationAlgorithm::Interpolate( Image::ConstPointer lowerSlice, unsigned int lowerSliceIndex, Image::ConstPointer upperSlice, unsigned int upperSliceIndex, unsigned int requestedIndex, unsigned int /*sliceDimension*/, // commented variables are not used Image::Pointer resultImage, unsigned int /*timeStep*/, Image::ConstPointer /*referenceImage*/) { - mitk::Image::Pointer lowerDistanceImage = mitk::Image::New(); - AccessFixedDimensionByItk_1(lowerSlice, ComputeDistanceMap, 2, lowerDistanceImage); - - mitk::Image::Pointer upperDistanceImage = mitk::Image::New(); - AccessFixedDimensionByItk_1(upperSlice, ComputeDistanceMap, 2, upperDistanceImage); + auto lowerDistanceImage = this->ComputeDistanceMap(lowerSliceIndex, lowerSlice); + auto upperDistanceImage = this->ComputeDistanceMap(upperSliceIndex, upperSlice); // calculate where the current slice is in comparison to the lower and upper neighboring slices float ratio = (float)(requestedIndex - lowerSliceIndex) / (float)(upperSliceIndex - lowerSliceIndex); - AccessFixedDimensionByItk_3( - resultImage, InterpolateIntermediateSlice, 2, upperDistanceImage, lowerDistanceImage, ratio); + AccessFixedDimensionByItk_3(resultImage, InterpolateIntermediateSlice, 2, upperDistanceImage, lowerDistanceImage, ratio); return resultImage; } +mitk::Image::Pointer mitk::ShapeBasedInterpolationAlgorithm::ComputeDistanceMap(unsigned int sliceIndex, Image::ConstPointer slice) +{ + if (0 != m_DistanceImageCache.count(sliceIndex)) + return m_DistanceImageCache[sliceIndex]; + + if (2 < m_DistanceImageCache.size()) + m_DistanceImageCache.clear(); + + auto distanceImage = mitk::Image::New(); + AccessFixedDimensionByItk_1(slice, ComputeDistanceMap, 2, distanceImage); + + m_DistanceImageCache[sliceIndex] = distanceImage; + + return distanceImage; +} + template void mitk::ShapeBasedInterpolationAlgorithm::ComputeDistanceMap(const itk::Image *binaryImage, mitk::Image::Pointer &result) { typedef itk::Image DistanceFilterInputImageType; typedef itk::FastChamferDistanceImageFilter DistanceFilterType; typedef itk::IsoContourDistanceImageFilter IsoContourType; typedef itk::InvertIntensityImageFilter InvertIntensityImageFilterType; typedef itk::SubtractImageFilter SubtractImageFilterType; typename DistanceFilterType::Pointer distanceFilter = DistanceFilterType::New(); typename DistanceFilterType::Pointer distanceFilterInverted = DistanceFilterType::New(); typename IsoContourType::Pointer isoContourFilter = IsoContourType::New(); typename IsoContourType::Pointer isoContourFilterInverted = IsoContourType::New(); typename InvertIntensityImageFilterType::Pointer invertFilter = InvertIntensityImageFilterType::New(); typename SubtractImageFilterType::Pointer subtractImageFilter = SubtractImageFilterType::New(); // arbitrary maximum distance int maximumDistance = 100; // this assumes the image contains only 1 and 0 invertFilter->SetInput(binaryImage); invertFilter->SetMaximum(1); // do the processing on the image and the inverted image to get inside and outside distance isoContourFilter->SetInput(binaryImage); isoContourFilter->SetFarValue(maximumDistance + 1); isoContourFilter->SetLevelSetValue(0); isoContourFilterInverted->SetInput(invertFilter->GetOutput()); isoContourFilterInverted->SetFarValue(maximumDistance + 1); isoContourFilterInverted->SetLevelSetValue(0); distanceFilter->SetInput(isoContourFilter->GetOutput()); distanceFilter->SetMaximumDistance(maximumDistance); distanceFilterInverted->SetInput(isoContourFilterInverted->GetOutput()); distanceFilterInverted->SetMaximumDistance(maximumDistance); // inside distance should be negative, outside distance positive subtractImageFilter->SetInput2(distanceFilter->GetOutput()); subtractImageFilter->SetInput1(distanceFilterInverted->GetOutput()); subtractImageFilter->Update(); result = mitk::GrabItkImageMemory(subtractImageFilter->GetOutput()); } template void mitk::ShapeBasedInterpolationAlgorithm::InterpolateIntermediateSlice(itk::Image *result, const mitk::Image::Pointer &lower, const mitk::Image::Pointer &upper, float ratio) { typename DistanceFilterImageType::Pointer lowerITK = DistanceFilterImageType::New(); typename DistanceFilterImageType::Pointer upperITK = DistanceFilterImageType::New(); CastToItkImage(lower, lowerITK); CastToItkImage(upper, upperITK); itk::ImageRegionConstIteratorWithIndex lowerIter(lowerITK, lowerITK->GetLargestPossibleRegion()); lowerIter.GoToBegin(); if (!lowerITK->GetLargestPossibleRegion().IsInside(upperITK->GetLargestPossibleRegion()) || !lowerITK->GetLargestPossibleRegion().IsInside(result->GetLargestPossibleRegion())) { // TODO Exception etc. MITK_ERROR << "The regions of the slices for the 2D interpolation are not equally sized!"; return; } float weight[2] = {1.0f - ratio, ratio}; while (!lowerIter.IsAtEnd()) { typename DistanceFilterImageType::PixelType lowerPixelVal = lowerIter.Get(); typename DistanceFilterImageType::PixelType upperPixelVal = upperITK->GetPixel(lowerIter.GetIndex()); typename DistanceFilterImageType::PixelType intermediatePixelVal = (weight[0] * upperPixelVal + weight[1] * lowerPixelVal > 0 ? 0 : 1); result->SetPixel(lowerIter.GetIndex(), static_cast(intermediatePixelVal)); ++lowerIter; } } diff --git a/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.h b/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.h index 934271b89b..92f44810b9 100644 --- a/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.h +++ b/Modules/Segmentation/Algorithms/mitkShapeBasedInterpolationAlgorithm.h @@ -1,65 +1,71 @@ /*============================================================================ 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 mitkShapeBasedInterpolationAlgorithm_h_Included #define mitkShapeBasedInterpolationAlgorithm_h_Included #include "mitkSegmentationInterpolationAlgorithm.h" #include +#include + namespace mitk { /** * \brief Shape-based binary image interpolation. * * This class uses legacy code from ipSegmentation to implement * the shape-based interpolation algorithm described in * * G.T. Herman, J. Zheng, C.A. Bucholtz: "Shape-based interpolation" * IEEE Computer Graphics & Applications, pp. 69-79,May 1992 * * Last contributor: * $Author:$ */ class MITKSEGMENTATION_EXPORT ShapeBasedInterpolationAlgorithm : public SegmentationInterpolationAlgorithm { public: mitkClassMacro(ShapeBasedInterpolationAlgorithm, SegmentationInterpolationAlgorithm); itkFactorylessNewMacro(Self); itkCloneMacro(Self); Image::Pointer Interpolate(Image::ConstPointer lowerSlice, unsigned int lowerSliceIndex, Image::ConstPointer upperSlice, unsigned int upperSliceIndex, unsigned int requestedIndex, unsigned int sliceDimension, Image::Pointer resultImage, unsigned int timeStep, Image::ConstPointer referenceImage) override; private: typedef itk::Image DistanceFilterImageType; template void ComputeDistanceMap(const itk::Image *, mitk::Image::Pointer &result); + Image::Pointer ComputeDistanceMap(unsigned int sliceIndex, Image::ConstPointer slice); + template void InterpolateIntermediateSlice(itk::Image *result, const mitk::Image::Pointer &lowerDistanceImage, const mitk::Image::Pointer &upperDistanceImage, float ratio); + + std::map m_DistanceImageCache; }; } // namespace #endif