diff --git a/Modules/Multilabel/files.cmake b/Modules/Multilabel/files.cmake index 61b61ab602..65d7bca1f7 100644 --- a/Modules/Multilabel/files.cmake +++ b/Modules/Multilabel/files.cmake @@ -1,18 +1,19 @@ set(CPP_FILES mitkLabel.cpp mitkLabelSet.cpp mitkLabelSetImage.cpp mitkLabelSetImageConverter.cpp mitkLabelSetImageIO.cpp mitkLabelSetImageSerializer.cpp mitkLabelSetImageSource.cpp mitkLabelSetImageToSurfaceFilter.cpp mitkLabelSetImageToSurfaceThreadedFilter.cpp mitkLabelSetImageVtkMapper2D.cpp mitkMultilabelActivator.cpp mitkMultilabelObjectFactory.cpp + mitkLabelSetSurfaceStamp.cpp ) set(RESOURCE_FILES ) diff --git a/Modules/Multilabel/mitkLabelSetSurfaceStamp.cpp b/Modules/Multilabel/mitkLabelSetSurfaceStamp.cpp new file mode 100644 index 0000000000..ebbe3b3d6b --- /dev/null +++ b/Modules/Multilabel/mitkLabelSetSurfaceStamp.cpp @@ -0,0 +1,195 @@ +/*=================================================================== + +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 "mitkLabelSetSurfaceStamp.h" +#include +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" + +#include +#include +#include +#include +#include +#include +#include + +mitk::LabelSetSurfaceStamp::LabelSetSurfaceStamp() +{ + this->SetNumberOfIndexedInputs(1); + this->SetNumberOfRequiredInputs(1); +} + +mitk::LabelSetSurfaceStamp::~LabelSetSurfaceStamp() +{ +} + +void mitk::LabelSetSurfaceStamp::GenerateData() +{ + this->SetOutput(0,this->GetInput(0)); + + mitk::Image::Pointer inputImage = this->GetInput(0); + + if (m_Surface.IsNull()) + { + MITK_ERROR << "Input surface is NULL."; + return; + } + if ( (inputImage->GetDimension() > 4) || (inputImage->GetDimension() < 2) ) + { + MITK_ERROR << "mitk::LabelSetSurfaceStamp:GenerateData works only with 2D, 2D+t, 3D, 3D+t and 4D images, sorry."; + return; + } + + // This is necessary because only these dimensions are supported from the corresponding filter. + switch(inputImage->GetDimension()) + { + case 2: + { + //AccessFixedDimensionByItk_1(inputImage, ItkImageProcessing, 2, m_Surface); break; + } + case 3: + { + AccessFixedDimensionByItk_1(inputImage, ItkImageProcessing, 3, m_Surface); break; + } + case 4: + { + AccessFixedDimensionByItk_1(inputImage, ItkImageProcessing, 4, m_Surface); break; + } + default: break; + } +} + +template +void mitk::LabelSetSurfaceStamp::ItkImageProcessing( itk::Image* itkImage, mitk::Surface::Pointer surface ) +{ + typedef itk::Image ImageType; + mitk::LabelSetImage::Pointer LabelSetInputImage = dynamic_cast(GetInput()); + try + { + vtkPolyData *polydata = surface->GetVtkPolyData(); + + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->SetMatrix(surface->GetGeometry()->GetVtkTransform()->GetMatrix()); + transform->Update(); + + vtkSmartPointer transformer = vtkSmartPointer::New(); + transformer->SetInputData(polydata); + transformer->SetTransform(transform); + transformer->Update(); + + typedef double Coord; + typedef itk::QuadEdgeMesh< Coord, VImageDimension > MeshType; + + MeshType::Pointer mesh = MeshType::New(); + mesh->SetCellsAllocationMethod(MeshType::CellsAllocatedDynamicallyCellByCell); + int numberOfPoints = polydata->GetNumberOfPoints(); + mesh->GetPoints()->Reserve(numberOfPoints); + + vtkPoints* points = polydata->GetPoints(); + + MeshType::PointType point; + for (int i = 0; i < numberOfPoints; i++) + { + double* aux = points->GetPoint(i); + point[0] = aux[0]; + point[1] = aux[1]; + point[2] = aux[2]; + mesh->SetPoint(i, point); + } + + // Load the polygons into the itk::Mesh + typedef MeshType::CellAutoPointer CellAutoPointerType; + typedef MeshType::CellType CellType; + typedef itk::TriangleCell< CellType > TriangleCellType; + typedef MeshType::PointIdentifier PointIdentifierType; + typedef MeshType::CellIdentifier CellIdentifierType; + + // Read the number of polygons + CellIdentifierType numberOfPolygons = 0; + numberOfPolygons = polydata->GetNumberOfPolys(); + + PointIdentifierType numberOfCellPoints = 3; + + for (CellIdentifierType i = 0; i < numberOfPolygons; i++) + { + vtkIdList *cellIds; + vtkCell *vcell = polydata->GetCell(i); + cellIds = vcell->GetPointIds(); + + CellAutoPointerType cell; + auto triangleCell = new TriangleCellType; + PointIdentifierType k; + for (k = 0; k < numberOfCellPoints; k++) + { + triangleCell->SetPointId(k, cellIds->GetId(k)); + } + + cell.TakeOwnership(triangleCell); + mesh->SetCell(i, cell); + } + + typedef itk::TriangleMeshToBinaryImageFilter TriangleMeshToBinaryImageFilterType; + + TriangleMeshToBinaryImageFilterType::Pointer filter = TriangleMeshToBinaryImageFilterType::New(); + filter->SetInput(mesh); + filter->SetInfoImage(itkImage); + filter->SetInsideValue(1); + filter->SetOutsideValue(0); + filter->Update(); + + //GoTrough + auto resultImage = filter->GetOutput(); + resultImage->DisconnectPipeline(); + + typedef itk::ImageRegionConstIterator< ImageType > SourceIteratorType; + typedef itk::ImageRegionIterator< ImageType > TargetIteratorType; + + SourceIteratorType sourceIter(resultImage, resultImage->GetLargestPossibleRegion()); + sourceIter.GoToBegin(); + + TargetIteratorType targetIter(itkImage, itkImage->GetLargestPossibleRegion()); + targetIter.GoToBegin(); + + int activeLabel = (LabelSetInputImage->GetActiveLabel(LabelSetInputImage->GetActiveLayer()))->GetValue(); + + while (!sourceIter.IsAtEnd()) + { + int sourceValue = static_cast(sourceIter.Get()); + int targetValue = static_cast(targetIter.Get()); + + if ((sourceValue != 0) && (m_ForceOverwrite || !LabelSetInputImage->GetLabel(targetValue)->GetLocked())) // skip exterior and locked labels + { + targetIter.Set(activeLabel); + } + ++sourceIter; + ++targetIter; + } + } + catch (itk::ExceptionObject& e) + { + mitkThrow() << e.GetDescription(); + } + this->Modified(); +} + +void mitk::LabelSetSurfaceStamp::GenerateOutputInformation() +{ + mitk::Image::Pointer inputImage = (mitk::Image*) this->GetInput(); + mitk::Image::Pointer output = this->GetOutput(); + itkDebugMacro(<<"GenerateOutputInformation()"); + if(inputImage.IsNull()) return; +} \ No newline at end of file diff --git a/Modules/Multilabel/mitkLabelSetSurfaceStamp.h b/Modules/Multilabel/mitkLabelSetSurfaceStamp.h new file mode 100644 index 0000000000..75106c0d4a --- /dev/null +++ b/Modules/Multilabel/mitkLabelSetSurfaceStamp.h @@ -0,0 +1,71 @@ +/*=================================================================== + +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 __mitkLabelSetSurfaceStamp_h +#define __mitkLabelSetSurfaceStamp_h + +#include "MitkMultilabelExports.h" + +//MITK +#include +#include "mitkImageToImageFilter.h" +#include +#include + +namespace mitk +{ + class MITKMULTILABEL_EXPORT LabelSetSurfaceStamp : public ImageToImageFilter + { + public: + + mitkClassMacro( LabelSetSurfaceStamp , ImageToImageFilter ); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + itkGetConstMacro(Surface,Surface::Pointer); + itkSetMacro(Surface,Surface::Pointer); + itkGetConstMacro(ForceOverwrite,bool); + itkSetMacro(ForceOverwrite,bool); + private: + /*! + \brief standard constructor + */ + LabelSetSurfaceStamp(); + /*! + \brief standard destructor + */ + ~LabelSetSurfaceStamp(); + /*! + \brief Method generating the output information of this filter (e.g. image dimension, image type, etc.). + The interface ImageToImageFilter requires this implementation. Everything is taken from the input image. + */ + virtual void GenerateOutputInformation() override; + /*! + \brief Method generating the output of this filter. Called in the updated process of the pipeline. + This method generates the smoothed output image. + */ + virtual void GenerateData() override; + + /*! + \brief Internal templated method calling the ITK bilteral filter. Here the actual filtering is performed. + */ + template + void ItkImageProcessing( itk::Image* itkImage, mitk::Surface::Pointer surface); + + Surface::Pointer m_Surface; + bool m_ForceOverwrite; + }; +} //END mitk namespace +#endif