diff --git a/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.cpp b/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.cpp index 8456529a5e..0a4155237e 100644 --- a/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.cpp +++ b/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.cpp @@ -1,270 +1,282 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceInterpolationController.h" #include "mitkMemoryUtilities.h" +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" + +#include "mitkImageToSurfaceFilter.h" mitk::SurfaceInterpolationController::SurfaceInterpolationController() :m_SelectedSegmentation(0) { m_ReduceFilter = ReduceContourSetFilter::New(); m_NormalsFilter = ComputeContourSetNormalsFilter::New(); m_InterpolateSurfaceFilter = CreateDistanceImageFromSurfaceFilter::New(); m_ReduceFilter->SetUseProgressBar(false); m_NormalsFilter->SetUseProgressBar(false); m_InterpolateSurfaceFilter->SetUseProgressBar(false); m_Contours = Surface::New(); m_PolyData = vtkSmartPointer::New(); m_PolyData->SetPoints(vtkPoints::New()); m_InterpolationResult = 0; m_CurrentNumberOfReducedContours = 0; } mitk::SurfaceInterpolationController::~SurfaceInterpolationController() { for (ContourListMap::iterator it = m_MapOfContourLists.begin(); it != m_MapOfContourLists.end(); it++) { for (unsigned int j = 0; j < m_MapOfContourLists[(*it).first].size(); ++j) { delete(m_MapOfContourLists[(*it).first].at(j).position); } m_MapOfContourLists.erase(it); } } mitk::SurfaceInterpolationController* mitk::SurfaceInterpolationController::GetInstance() { static mitk::SurfaceInterpolationController* m_Instance; if ( m_Instance == 0) { m_Instance = new SurfaceInterpolationController(); } return m_Instance; } void mitk::SurfaceInterpolationController::AddNewContour (mitk::Surface::Pointer newContour ,RestorePlanePositionOperation* op) { AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform = op->GetTransform(); mitk::Vector3D direction = op->GetDirectionVector(); int pos (-1); for (unsigned int i = 0; i < m_MapOfContourLists[m_SelectedSegmentation].size(); i++) { itk::Matrix diffM = transform->GetMatrix()-m_MapOfContourLists[m_SelectedSegmentation].at(i).position->GetTransform()->GetMatrix(); bool isSameMatrix(true); for (unsigned int j = 0; j < 3; j++) { if (fabs(diffM[j][0]) > 0.0001 && fabs(diffM[j][1]) > 0.0001 && fabs(diffM[j][2]) > 0.0001) { isSameMatrix = false; break; } } itk::Vector diffV = m_MapOfContourLists[m_SelectedSegmentation].at(i).position->GetTransform()->GetOffset()-transform->GetOffset(); if ( isSameMatrix && m_MapOfContourLists[m_SelectedSegmentation].at(i).position->GetPos() == op->GetPos() && (fabs(diffV[0]) < 0.0001 && fabs(diffV[1]) < 0.0001 && fabs(diffV[2]) < 0.0001) ) { pos = i; break; } } //Don't save a new empty contour if (pos == -1 && newContour->GetVtkPolyData()->GetNumberOfPoints() > 0) { mitk::RestorePlanePositionOperation* newOp = new mitk::RestorePlanePositionOperation (OpRESTOREPLANEPOSITION, op->GetWidth(), op->GetHeight(), op->GetSpacing(), op->GetPos(), direction, transform); ContourPositionPair newData; newData.contour = newContour; newData.position = newOp; m_ReduceFilter->SetInput(m_MapOfContourLists[m_SelectedSegmentation].size(), newContour); m_MapOfContourLists[m_SelectedSegmentation].push_back(newData); } //Edit a existing contour. If the contour is empty, edit it anyway so that the interpolation will always be consistent else if (pos != -1) { m_MapOfContourLists[m_SelectedSegmentation].at(pos).contour = newContour; m_ReduceFilter->SetInput(pos, newContour); } m_ReduceFilter->Update(); m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs(); for (unsigned int i = 0; i < m_CurrentNumberOfReducedContours; i++) { m_NormalsFilter->SetInput(i, m_ReduceFilter->GetOutput(i)); m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i)); } this->Modified(); } void mitk::SurfaceInterpolationController::Interpolate() { if (m_CurrentNumberOfReducedContours< 2) { //If no interpolation is possible reset the interpolation result m_InterpolationResult = 0; return; } //Setting up progress bar /* * Removed due to bug 12441. ProgressBar messes around with Qt event queue which is fatal for segmentation */ //mitk::ProgressBar::GetInstance()->AddStepsToDo(8); + // update the filter and get teh resulting distance-image m_InterpolateSurfaceFilter->Update(); - Image::Pointer distanceImage = m_InterpolateSurfaceFilter->GetOutput(); - vtkSmartPointer mcFilter = vtkSmartPointer::New(); - mcFilter->SetInput(distanceImage->GetVtkImageData()); - mcFilter->SetValue(0,0); - mcFilter->Update(); + // create a surface from the distance-image + mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New(); + imageToSurfaceFilter->SetInput( distanceImage ); + imageToSurfaceFilter->SetThreshold( 0 ); + imageToSurfaceFilter->Update(); + m_InterpolationResult = imageToSurfaceFilter->GetOutput(); - m_InterpolationResult = 0; - m_InterpolationResult = mitk::Surface::New(); - m_InterpolationResult->SetVtkPolyData(mcFilter->GetOutput()); - m_InterpolationResult->GetGeometry()->SetOrigin(distanceImage->GetGeometry()->GetOrigin()); vtkSmartPointer polyDataAppender = vtkSmartPointer::New(); for (unsigned int i = 0; i < m_ReduceFilter->GetNumberOfOutputs(); i++) { polyDataAppender->AddInput(m_ReduceFilter->GetOutput(i)->GetVtkPolyData()); } polyDataAppender->Update(); m_Contours->SetVtkPolyData(polyDataAppender->GetOutput()); //Last progress step /* * Removed due to bug 12441. ProgressBar messes around with Qt event queue which is fatal for segmentation */ //mitk::ProgressBar::GetInstance()->Progress(8); m_InterpolationResult->DisconnectPipeline(); } mitk::Surface::Pointer mitk::SurfaceInterpolationController::GetInterpolationResult() { return m_InterpolationResult; } mitk::Surface* mitk::SurfaceInterpolationController::GetContoursAsSurface() { return m_Contours; } void mitk::SurfaceInterpolationController::SetDataStorage(DataStorage &ds) { m_DataStorage = &ds; } void mitk::SurfaceInterpolationController::SetMinSpacing(double minSpacing) { m_ReduceFilter->SetMinSpacing(minSpacing); } void mitk::SurfaceInterpolationController::SetMaxSpacing(double maxSpacing) { m_ReduceFilter->SetMaxSpacing(maxSpacing); m_NormalsFilter->SetMaxSpacing(maxSpacing); } void mitk::SurfaceInterpolationController::SetDistanceImageVolume(unsigned int distImgVolume) { m_InterpolateSurfaceFilter->SetDistanceImageVolume(distImgVolume); } void mitk::SurfaceInterpolationController::SetSegmentationImage(Image* workingImage) { m_NormalsFilter->SetSegmentationBinaryImage(workingImage); } mitk::Image* mitk::SurfaceInterpolationController::GetImage() { return m_InterpolateSurfaceFilter->GetOutput(); } double mitk::SurfaceInterpolationController::EstimatePortionOfNeededMemory() { double numberOfPointsAfterReduction = m_ReduceFilter->GetNumberOfPointsAfterReduction()*3; double sizeOfPoints = pow(numberOfPointsAfterReduction,2)*sizeof(double); double totalMem = mitk::MemoryUtilities::GetTotalSizeOfPhysicalRam(); double percentage = sizeOfPoints/totalMem; return percentage; } +template +void mitk::SurfaceInterpolationController::GetImageBase(itk::Image* input, itk::ImageBase<3>::Pointer& result) +{ + result = input; +} + void mitk::SurfaceInterpolationController::SetCurrentSegmentationInterpolationList(mitk::Image* segmentation) { if (segmentation == m_SelectedSegmentation) return; if (segmentation == 0) return; ContourListMap::iterator it = m_MapOfContourLists.find(segmentation); m_SelectedSegmentation = segmentation; m_ReduceFilter->Reset(); m_NormalsFilter->Reset(); m_InterpolateSurfaceFilter->Reset(); + itk::ImageBase<3>::Pointer itkImage; + AccessFixedDimensionByItk_1( m_SelectedSegmentation, GetImageBase, 3, itkImage ); + m_InterpolateSurfaceFilter->SetReferenceImage( itkImage.GetPointer() ); + if (it == m_MapOfContourLists.end()) { ContourPositionPairList newList; m_MapOfContourLists.insert(std::pair(segmentation, newList)); m_InterpolationResult = 0; m_CurrentNumberOfReducedContours = 0; } else { for (unsigned int i = 0; i < m_MapOfContourLists[m_SelectedSegmentation].size(); i++) { m_ReduceFilter->SetInput(i, m_MapOfContourLists[m_SelectedSegmentation].at(i).contour); } m_ReduceFilter->Update(); m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs(); for (unsigned int i = 0; i < m_CurrentNumberOfReducedContours; i++) { m_NormalsFilter->SetInput(i, m_ReduceFilter->GetOutput(i)); m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i)); } } Modified(); } void mitk::SurfaceInterpolationController::RemoveSegmentationFromContourList(mitk::Image *segmentation) { if (segmentation != 0) { m_MapOfContourLists.erase(segmentation); } } diff --git a/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.h b/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.h index 648393952e..f7b8b5a02e 100644 --- a/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.h +++ b/Modules/Segmentation/Controllers/mitkSurfaceInterpolationController.h @@ -1,167 +1,169 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkSurfaceInterpolationController_h_Included #define mitkSurfaceInterpolationController_h_Included #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkRestorePlanePositionOperation.h" #include "mitkSurface.h" #include "mitkInteractionConst.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkCreateDistanceImageFromSurfaceFilter.h" #include "mitkReduceContourSetFilter.h" #include "mitkComputeContourSetNormalsFilter.h" #include "mitkDataNode.h" #include "mitkDataStorage.h" #include "mitkWeakPointer.h" #include "vtkPolygon.h" #include "vtkPoints.h" #include "vtkCellArray.h" #include "vtkPolyData.h" #include "vtkSmartPointer.h" #include "vtkAppendPolyData.h" #include "vtkMarchingCubes.h" #include "vtkImageData.h" #include "mitkVtkRepresentationProperty.h" #include "vtkProperty.h" #include "mitkProgressBar.h" namespace mitk { class Segmentation_EXPORT SurfaceInterpolationController : public itk::Object { public: mitkClassMacro(SurfaceInterpolationController, itk::Object) itkNewMacro(Self) static SurfaceInterpolationController* GetInstance(); /** * Adds a new extracted contour to the list */ void AddNewContour(Surface::Pointer newContour, RestorePlanePositionOperation *op); /** * Interpolates the 3D surface from the given extracted contours */ void Interpolate (); mitk::Surface::Pointer GetInterpolationResult(); /** * Sets the minimum spacing of the current selected segmentation * This is needed since the contour points we reduced before they are used to interpolate the surface */ void SetMinSpacing(double minSpacing); /** * Sets the minimum spacing of the current selected segmentation * This is needed since the contour points we reduced before they are used to interpolate the surface */ void SetMaxSpacing(double maxSpacing); /** * Sets the volume i.e. the number of pixels that the distance image should have * By evaluation we found out that 50.000 pixel delivers a good result */ void SetDistanceImageVolume(unsigned int distImageVolume); /** * Sets the current segmentation which is used by the interpolation * This is needed because the calculation of the normals needs to now wheather a normal points inside a segmentation or not */ void SetSegmentationImage(Image* workingImage); Surface* GetContoursAsSurface(); void SetDataStorage(DataStorage &ds); /** * Sets the current list of contourpoints which is used for the surface interpolation * @param segmentation The current selected segmentation */ void SetCurrentSegmentationInterpolationList(mitk::Image* segmentation); /** * Removes the segmentation and all its contours from the list * @param segmentation The segmentation to be removed */ void RemoveSegmentationFromContourList(mitk::Image* segmentation); mitk::Image* GetImage(); /** * Estimates the memory which is needed to build up the equationsystem for the interpolation. * \returns The percentage of the real memory which will be used by the interpolation */ double EstimatePortionOfNeededMemory(); protected: SurfaceInterpolationController(); ~SurfaceInterpolationController(); + template void GetImageBase(itk::Image* input, itk::ImageBase<3>::Pointer& result); + private: struct ContourPositionPair { Surface::Pointer contour; RestorePlanePositionOperation* position; }; typedef std::vector ContourPositionPairList; typedef std::map ContourListMap; ContourPositionPairList::iterator m_Iterator; ReduceContourSetFilter::Pointer m_ReduceFilter; ComputeContourSetNormalsFilter::Pointer m_NormalsFilter; CreateDistanceImageFromSurfaceFilter::Pointer m_InterpolateSurfaceFilter; double m_MinSpacing; double m_MaxSpacing; const Image* m_WorkingImage; Surface::Pointer m_Contours; vtkSmartPointer m_PolyData; unsigned int m_DistImageVolume; mitk::WeakPointer m_DataStorage; ContourListMap m_MapOfContourLists; mitk::Surface::Pointer m_InterpolationResult; unsigned int m_CurrentNumberOfReducedContours; mitk::Image* m_SelectedSegmentation; }; } #endif