diff --git a/Modules/Multilabel/mitkLabelSetImage.cpp b/Modules/Multilabel/mitkLabelSetImage.cpp index 7e5c0c530b..315b8a28fa 100644 --- a/Modules/Multilabel/mitkLabelSetImage.cpp +++ b/Modules/Multilabel/mitkLabelSetImage.cpp @@ -1,1073 +1,957 @@ /*=================================================================== 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 "mitkLabelSetImage.h" #include "mitkImageAccessByItk.h" #include "mitkInteractionConst.h" #include "mitkRenderingManager.h" #include "mitkImageCast.h" #include "mitkImageReadAccessor.h" #include "mitkLookupTableProperty.h" #include "mitkPadImageFilter.h" #include #include #include #include #include #include //#include #include mitk::LabelSetImage::LabelSetImage() : mitk::Image(), m_ActiveLayer(0), m_ExteriorLabel(nullptr) { // Iniitlaize Background Label mitk::Color color; color.Set(0,0,0); m_ExteriorLabel = mitk::Label::New(); m_ExteriorLabel->SetColor(color); m_ExteriorLabel->SetName("Exterior"); m_ExteriorLabel->SetOpacity(0.0); m_ExteriorLabel->SetLocked(false); m_ExteriorLabel->SetValue(0); } mitk::LabelSetImage::LabelSetImage(const mitk::LabelSetImage & other): Image(other), m_ActiveLayer(other.GetActiveLayer()), m_ExteriorLabel(other.GetExteriorLabel()->Clone()) { for(unsigned int i = 0 ; i < other.GetNumberOfLayers(); i++) { // Clone LabelSet data mitk::LabelSet::Pointer lsClone = other.GetLabelSet(i)->Clone(); // add modified event listener to LabelSet (listen to LabelSet changes) itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this,&mitk::LabelSetImage::OnLabelSetModified); lsClone->AddObserver(itk::ModifiedEvent(), command); m_LabelSetContainer.push_back( lsClone ); // clone layer Image data mitk::Image::Pointer liClone = other.GetLayerImage(i)->Clone(); m_LayerContainer.push_back( liClone ); } } void mitk::LabelSetImage::OnLabelSetModified() { Superclass::Modified(); } void mitk::LabelSetImage::SetExteriorLabel(mitk::Label * label) { m_ExteriorLabel = label; } mitk::Label* mitk::LabelSetImage::GetExteriorLabel() { return m_ExteriorLabel; } const mitk::Label* mitk::LabelSetImage::GetExteriorLabel() const { return m_ExteriorLabel; } void mitk::LabelSetImage::Initialize(const mitk::Image* other) { mitk::PixelType pixelType(mitk::MakeScalarPixelType() ); if (other->GetDimension() == 2) { const unsigned int dimensions[] = { other->GetDimension(0), other->GetDimension(1), 1 }; Superclass::Initialize(pixelType, 3, dimensions); } else { Superclass::Initialize(pixelType, other->GetDimension(), other->GetDimensions()); } mitk::TimeGeometry::Pointer originalGeometry = other->GetTimeGeometry()->Clone(); this->SetTimeGeometry( originalGeometry ); // Add a inital LabelSet ans corresponding image data to the stack AddLayer(); } mitk::LabelSetImage::~LabelSetImage() { m_LabelSetContainer.clear(); } mitk::Image* mitk::LabelSetImage::GetLayerImage(unsigned int layer) { return m_LayerContainer[layer]; } const mitk::Image* mitk::LabelSetImage::GetLayerImage(unsigned int layer) const { return m_LayerContainer[layer]; } unsigned int mitk::LabelSetImage::GetActiveLayer() const { return m_ActiveLayer; } unsigned int mitk::LabelSetImage::GetNumberOfLayers() const { return m_LabelSetContainer.size(); } -mitk::LabelSetImage::VectorImageType::Pointer mitk::LabelSetImage::GetVectorImage(bool forceUpdate) const -{ - try - { - if (forceUpdate) - { - AccessByItk_1(this, ImageToLayerContainerProcessing, GetActiveLayer()); - } - - LabelSetImageType::Pointer itkImage; - mitk::CastToItkImage(this,itkImage); - - VectorImageType::Pointer newVectorImage = VectorImageType::New(); - newVectorImage->SetSpacing( itkImage->GetSpacing() ); - newVectorImage->SetOrigin( itkImage->GetOrigin() ); - newVectorImage->SetDirection( itkImage->GetDirection() ); - newVectorImage->SetRegions( itkImage->GetLargestPossibleRegion()); - newVectorImage->SetNumberOfComponentsPerPixel( m_LayerContainer.size() ); - newVectorImage->Allocate(); - - itkImage = nullptr; - - // fill inside - VariableVectorType defaultValue; - defaultValue.SetSize( m_LayerContainer.size()); - defaultValue.Fill(0); - newVectorImage->FillBuffer(defaultValue); - - ImageAdaptorType::Pointer targetAdaptor = ImageAdaptorType::New(); - targetAdaptor->SetImage( newVectorImage ); - - // transfer layers to a vector image. - for (unsigned int lidx = 0; lidx < m_LayerContainer.size(); ++lidx) - { - MITK_INFO << lidx ; - LabelSetImageType::Pointer itkImageLayer; - mitk::CastToItkImage(m_LayerContainer[lidx],itkImageLayer); - - targetAdaptor->SetExtractComponentIndex(lidx); - targetAdaptor->Update(); - - typedef itk::ImageRegionConstIterator< LabelSetImageType > SourceIteratorType; - typedef itk::ImageRegionIterator< ImageAdaptorType > TargetIteratorType; - - SourceIteratorType sourceIter( itkImageLayer, itkImageLayer->GetLargestPossibleRegion() ); - sourceIter.GoToBegin(); - - TargetIteratorType targetIter( targetAdaptor, targetAdaptor->GetLargestPossibleRegion() ); - targetIter.GoToBegin(); - - while(!sourceIter.IsAtEnd()) - { - targetIter.Set( sourceIter.Get() ); - ++sourceIter; - ++targetIter; - } - } - return newVectorImage; - } - catch(itk::ExceptionObject& e) - { - mitkThrow() << e.GetDescription(); - return nullptr; - } -} - -void mitk::LabelSetImage::SetVectorImage(VectorImageType::Pointer vectorImage ) -{ - try - { - int numberOfLayers = vectorImage->GetNumberOfComponentsPerPixel(); - - MITK_INFO << numberOfLayers; - - ImageAdaptorType::Pointer vectorAdaptor = ImageAdaptorType::New(); - vectorAdaptor->SetImage( vectorImage ); - - for (int lidx = 0; lidx < numberOfLayers; ++lidx) - { - LabelSetImageType::Pointer auxImg = LabelSetImageType::New(); - auxImg->SetSpacing( vectorImage->GetSpacing() ); - auxImg->SetOrigin( vectorImage->GetOrigin() ); - auxImg->SetDirection( vectorImage->GetDirection() ); - auxImg->SetRegions( vectorImage->GetLargestPossibleRegion() ); - auxImg->Allocate(); - - vectorAdaptor->SetExtractComponentIndex(lidx); - - typedef itk::ImageRegionConstIterator< ImageAdaptorType > SourceIteratorType; - typedef itk::ImageRegionIterator< LabelSetImageType > TargetIteratorType; - - SourceIteratorType sourceIter( vectorAdaptor, vectorAdaptor->GetLargestPossibleRegion() ); - sourceIter.GoToBegin(); - - TargetIteratorType targetIter( auxImg, auxImg->GetLargestPossibleRegion() ); - targetIter.GoToBegin(); - - while(!sourceIter.IsAtEnd()) - { - targetIter.Set( sourceIter.Get() ); - ++sourceIter; - ++targetIter; - } - - mitk::Image::Pointer newLayerImage = mitk::Image::New(); - newLayerImage->Initialize(this); - newLayerImage->SetVolume(auxImg->GetBufferPointer()); - m_LayerContainer[lidx] = newLayerImage; - AccessByItk_1(this, LayerContainerToImageProcessing, lidx); - } - // reset active layer - SetActiveLayer(0); - - } - catch(itk::ExceptionObject& e) - { - mitkThrow() << e.GetDescription(); - } - this->Modified(); -} - void mitk::LabelSetImage::RemoveLayer() { int layerToDelete = GetActiveLayer(); // remove all observers from active label set GetLabelSet(layerToDelete)->RemoveAllObservers(); - // set the active layer to one belo, if exists. + // set the active layer to one below, if exists. SetActiveLayer(layerToDelete-1); // remove labelset and image data m_LabelSetContainer.erase( m_LabelSetContainer.begin() + layerToDelete); m_LayerContainer.erase( m_LayerContainer.begin() + layerToDelete); this->Modified(); } unsigned int mitk::LabelSetImage::AddLayer(mitk::LabelSet::Pointer lset) { mitk::Image::Pointer newImage = mitk::Image::New(); newImage->Initialize( this->GetPixelType(), this->GetDimension(), this->GetDimensions(), this->GetImageDescriptor()->GetNumberOfChannels() ); LabelSetImageType::Pointer itkImage; mitk::CastToItkImage(newImage, itkImage); itkImage->FillBuffer(0); - // get upcoming new labelset id + unsigned int newLabelSetId = this->AddLayer(newImage, lset); + + // important to release the itk image + itkImage = nullptr; + return newLabelSetId; +} + +unsigned int mitk::LabelSetImage::AddLayer(mitk::Image::Pointer layerImage, mitk::LabelSet::Pointer lset) +{ unsigned int newLabelSetId = m_LayerContainer.size(); // Add labelset to layer mitk::LabelSet::Pointer ls; if (lset.IsNotNull()) { ls = lset; } else { ls = mitk::LabelSet::New(); ls->AddLabel(GetExteriorLabel()); ls->SetActiveLabel(0 /*Exterior Label*/); } ls->SetLayer(newLabelSetId); // Add exterior Label to label set //mitk::Label::Pointer exteriorLabel = CreateExteriorLabel(); // push a new working image for the new layer - m_LayerContainer.push_back(newImage); + m_LayerContainer.push_back(layerImage); // push a new labelset for the new layer m_LabelSetContainer.push_back(ls); // add modified event listener to LabelSet (listen to LabelSet changes) itk::SimpleMemberCommand::Pointer command = itk::SimpleMemberCommand::New(); - command->SetCallbackFunction(this,&mitk::LabelSetImage::OnLabelSetModified); + command->SetCallbackFunction(this, &mitk::LabelSetImage::OnLabelSetModified); ls->AddObserver(itk::ModifiedEvent(), command); - // important to release the itk image - itkImage = nullptr; - SetActiveLayer(newLabelSetId); //MITK_INFO << GetActiveLayer(); this->Modified(); return newLabelSetId; } void mitk::LabelSetImage::SetActiveLayer(unsigned int layer) { try { if ( (layer != GetActiveLayer()) && (layerGetNumberOfLayers()) ) { BeforeChangeLayerEvent.Send(); AccessByItk_1(this, ImageToLayerContainerProcessing, GetActiveLayer()); m_ActiveLayer = layer; // only at this place m_ActiveLayer should be manipulated!!! Use Getter and Setter AccessByItk_1(this, LayerContainerToImageProcessing, GetActiveLayer()); AfterchangeLayerEvent.Send(); } } catch(itk::ExceptionObject& e) { mitkThrow() << e.GetDescription(); } this->Modified(); } void mitk::LabelSetImage::Concatenate(mitk::LabelSetImage* other) { const unsigned int* otherDims = other->GetDimensions(); const unsigned int* thisDims = this->GetDimensions(); if ( (otherDims[0] != thisDims[0]) || (otherDims[1] != thisDims[1]) || (otherDims[2] != thisDims[2]) ) mitkThrow() << "Dimensions do not match."; try { int numberOfLayers = other->GetNumberOfLayers(); for (int layer=0; layerSetActiveLayer(layer); AccessByItk_1(this, ConcatenateProcessing, other); mitk::LabelSet * ls = other->GetLabelSet(layer); auto it = ls->IteratorConstBegin(); auto end = ls->IteratorConstEnd(); it++;// skip exterior while(it != end) { GetLabelSet()->AddLabel((it->second)); //AddLabelEvent.Send(); it++; } } } catch(itk::ExceptionObject& e) { mitkThrow() << e.GetDescription(); } this->Modified(); } void mitk::LabelSetImage::ClearBuffer() { try { AccessByItk(this, ClearBufferProcessing); this->Modified(); } catch(itk::ExceptionObject& e) { mitkThrow() << e.GetDescription(); } } bool mitk::LabelSetImage::ExistLabel(PixelType pixelValue) const { bool exist = false; for(unsigned int lidx = 0 ; lidx < GetNumberOfLayers(); lidx++) exist |= m_LabelSetContainer[lidx]->ExistLabel(pixelValue); return exist; } bool mitk::LabelSetImage::ExistLabel(PixelType pixelValue, unsigned int layer) const { bool exist = m_LabelSetContainer[layer]->ExistLabel(pixelValue); return exist; } bool mitk::LabelSetImage::ExistLabelSet(unsigned int layer) const { return layer < m_LabelSetContainer.size(); } void mitk::LabelSetImage::MergeLabel(PixelType pixelValue, unsigned int /*layer*/) { int targetPixelValue = GetActiveLabel()->GetValue(); try { AccessByItk_2(this, MergeLabelProcessing, targetPixelValue, pixelValue); } catch(itk::ExceptionObject& e) { mitkThrow() << e.GetDescription(); } Modified(); } void mitk::LabelSetImage::MergeLabels(std::vector &VectorOfLablePixelValues, PixelType pixelValue, unsigned int layer) { GetLabelSet(layer)->SetActiveLabel(pixelValue); try { for (unsigned int idx=0; idx& VectorOfLabelPixelValues, unsigned int layer) { for (unsigned int idx=0; idxRemoveLabel(VectorOfLabelPixelValues[idx]); EraseLabel(VectorOfLabelPixelValues[idx],layer); } } void mitk::LabelSetImage::EraseLabels(std::vector &VectorOfLabelPixelValues, unsigned int layer) { for (unsigned int i=0; iEraseLabel(VectorOfLabelPixelValues[i], layer); } } void mitk::LabelSetImage::EraseLabel(PixelType pixelValue, unsigned int layer) { try { AccessByItk_2(this, EraseLabelProcessing, pixelValue, layer); } catch(itk::ExceptionObject& e) { mitkThrow() << e.GetDescription(); } Modified(); } mitk::Label *mitk::LabelSetImage::GetActiveLabel(unsigned int layer) { if (m_LabelSetContainer.size() > layer) return m_LabelSetContainer[layer]->GetActiveLabel(); else return nullptr; } mitk::Label *mitk::LabelSetImage::GetLabel(PixelType pixelValue, unsigned int layer) const { if(m_LabelSetContainer.size() <= layer) return nullptr; else return m_LabelSetContainer[layer]->GetLabel(pixelValue); } mitk::LabelSet* mitk::LabelSetImage::GetLabelSet(unsigned int layer) { if(m_LabelSetContainer.size() <= layer) return nullptr; else return m_LabelSetContainer[layer].GetPointer(); } const mitk::LabelSet* mitk::LabelSetImage::GetLabelSet(unsigned int layer) const { if(m_LabelSetContainer.size() <= layer) return nullptr; else return m_LabelSetContainer[layer].GetPointer(); } mitk::LabelSet* mitk::LabelSetImage::GetActiveLabelSet() { return m_LabelSetContainer[GetActiveLayer()].GetPointer(); } void mitk::LabelSetImage::UpdateCenterOfMass(PixelType pixelValue, unsigned int layer) { AccessByItk_2( this, CalculateCenterOfMassProcessing, pixelValue, layer ); } unsigned int mitk::LabelSetImage::GetNumberOfLabels(unsigned int layer) const { return m_LabelSetContainer[layer]->GetNumberOfLabels(); } unsigned int mitk::LabelSetImage::GetTotalNumberOfLabels() const { unsigned int totalLabels(0); auto layerIter = m_LabelSetContainer.begin(); for (; layerIter != m_LabelSetContainer.end(); ++layerIter) totalLabels += (*layerIter)->GetNumberOfLabels(); return totalLabels; } void mitk::LabelSetImage::MaskStamp(mitk::Image* mask, bool forceOverwrite) { try { mitk::PadImageFilter::Pointer padImageFilter = mitk::PadImageFilter::New(); padImageFilter->SetInput(0, mask); padImageFilter->SetInput(1, this); padImageFilter->SetPadConstant(0); padImageFilter->SetBinaryFilter(false); padImageFilter->SetLowerThreshold(0); padImageFilter->SetUpperThreshold(1); padImageFilter->Update(); mitk::Image::Pointer paddedMask = padImageFilter->GetOutput(); if (paddedMask.IsNull()) return; AccessByItk_2(this, MaskStampProcessing, paddedMask, forceOverwrite); } catch(...) { mitkThrow() << "Could not stamp the provided mask on the selected label."; } } mitk::Image::Pointer mitk::LabelSetImage::CreateLabelMask(PixelType index) { mitk::Image::Pointer mask = mitk::Image::New(); try { mask->Initialize(this); unsigned int byteSize = sizeof(LabelSetImage::PixelType); for (unsigned int dim = 0; dim < mask->GetDimension(); ++dim) { byteSize *= mask->GetDimension(dim); } mitk::ImageWriteAccessor* accessor = new mitk::ImageWriteAccessor(static_cast(mask)); memset( accessor->GetData(), 0, byteSize ); delete accessor; mitk::SlicedGeometry3D::Pointer geometry = this->GetSlicedGeometry()->Clone(); mask->SetGeometry( geometry ); AccessByItk_2(this, CreateLabelMaskProcessing, mask, index); } catch(...) { mitkThrow() << "Could not create a mask out of the selected label."; } return mask; } void mitk::LabelSetImage::SurfaceStamp(mitk::Surface* surface, bool forceOverwrite) { if (!surface) { MITK_ERROR << "Input surface is NULL."; return; } try { LabelSetImageType::Pointer itkImage; mitk::CastToItkImage(this, itkImage); 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, 3 > 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; iGetCell(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(); LabelSetImageType::Pointer resultImage = filter->GetOutput(); resultImage->DisconnectPipeline(); typedef itk::ImageRegionConstIterator< LabelSetImageType > SourceIteratorType; typedef itk::ImageRegionIterator< LabelSetImageType > TargetIteratorType; SourceIteratorType sourceIter( resultImage, resultImage->GetLargestPossibleRegion() ); sourceIter.GoToBegin(); TargetIteratorType targetIter( itkImage, itkImage->GetLargestPossibleRegion() ); targetIter.GoToBegin(); int activeLabel = GetActiveLabel(GetActiveLayer())->GetValue(); while ( !sourceIter.IsAtEnd() ) { int sourceValue = static_cast(sourceIter.Get()); int targetValue = static_cast(targetIter.Get()); if ( (sourceValue != 0) && (forceOverwrite || !this->GetLabel(targetValue)->GetLocked()) ) // skip exterior and locked labels { targetIter.Set( activeLabel ); } ++sourceIter; ++targetIter; } } catch(itk::ExceptionObject& e) { mitkThrow() << e.GetDescription(); } this->Modified(); } void mitk::LabelSetImage::InitializeByLabeledImage(mitk::Image::Pointer image) { if (image.IsNull() || image->IsEmpty() || !image->IsInitialized()) mitkThrow() << "Invalid labeled image."; try { this->Initialize(image); unsigned int byteSize = sizeof(LabelSetImage::PixelType); for (unsigned int dim = 0; dim < image->GetDimension(); ++dim) { byteSize *= image->GetDimension(dim); } mitk::ImageWriteAccessor* accessor = new mitk::ImageWriteAccessor(static_cast(this)); memset( accessor->GetData(), 0, byteSize ); delete accessor; mitk::SlicedGeometry3D::Pointer geometry = image->GetSlicedGeometry()->Clone(); this->SetGeometry( geometry ); AccessTwoImagesFixedDimensionByItk(this, image, InitializeByLabeledImageProcessing,3); } catch(...) { mitkThrow() << "Could not intialize by provided labeled image."; } this->Modified(); } template < typename ImageType1, typename ImageType2 > void mitk::LabelSetImage::InitializeByLabeledImageProcessing(ImageType1* output, ImageType2* input) { typedef itk::ImageRegionConstIterator< ImageType2 > SourceIteratorType; typedef itk::ImageRegionIterator< ImageType1 > TargetIteratorType; // typedef itk::RelabelComponentImageFilter FilterType; TargetIteratorType targetIter( output, output->GetLargestPossibleRegion() ); targetIter.GoToBegin(); //SourceIteratorType sourceIter( relabelFilter->GetOutput(), relabelFilter->GetOutput()->GetLargestPossibleRegion() ); SourceIteratorType sourceIter( input, input->GetLargestPossibleRegion() ); sourceIter.GoToBegin(); while ( !sourceIter.IsAtEnd() ) { PixelType sourceValue = static_cast(sourceIter.Get()); targetIter.Set( sourceValue ); if(!ExistLabel(sourceValue)) { std::stringstream name; name << "object-" << sourceValue; mitk::Label::Pointer label = mitk::Label::New(); label->SetName( name.str().c_str() ); double rgba[4]; m_LabelSetContainer[GetActiveLayer()]->GetLookupTable()->GetTableValue(sourceValue, rgba ); mitk::Color newColor; newColor.SetRed(rgba[0]); newColor.SetGreen(rgba[1]); newColor.SetBlue(rgba[2]); label->SetColor( newColor ); label->SetOpacity( rgba[3] ); label->SetValue( sourceValue ); GetLabelSet()->AddLabel(label); if(GetActiveLabelSet()->GetNumberOfLabels() >= mitk::Label::MAX_LABEL_VALUE || sourceValue >= mitk::Label::MAX_LABEL_VALUE) { AddLayer(); } } ++sourceIter; ++targetIter; } } template < typename ImageType > void mitk::LabelSetImage::MaskStampProcessing(ImageType* itkImage, mitk::Image* mask, bool forceOverwrite) { typename ImageType::Pointer itkMask; mitk::CastToItkImage(mask, itkMask); typedef itk::ImageRegionConstIterator< ImageType > SourceIteratorType; typedef itk::ImageRegionIterator< ImageType > TargetIteratorType; SourceIteratorType sourceIter( itkMask, itkMask->GetLargestPossibleRegion() ); sourceIter.GoToBegin(); TargetIteratorType targetIter( itkImage, itkImage->GetLargestPossibleRegion() ); targetIter.GoToBegin(); int activeLabel = this->GetActiveLabel(GetActiveLayer())->GetValue(); while ( !sourceIter.IsAtEnd() ) { PixelType sourceValue = sourceIter.Get(); PixelType targetValue = targetIter.Get(); if ( (sourceValue != 0) && (forceOverwrite || !this->GetLabel(targetValue)->GetLocked()) ) // skip exterior and locked labels { targetIter.Set( activeLabel ); } ++sourceIter; ++targetIter; } this->Modified(); } template < typename ImageType > void mitk::LabelSetImage::CreateLabelMaskProcessing(ImageType* itkImage, mitk::Image* mask, PixelType index) { typename ImageType::Pointer itkMask; mitk::CastToItkImage(mask, itkMask); typedef itk::ImageRegionConstIterator< ImageType > SourceIteratorType; typedef itk::ImageRegionIterator< ImageType > TargetIteratorType; SourceIteratorType sourceIter( itkImage, itkImage->GetLargestPossibleRegion() ); sourceIter.GoToBegin(); TargetIteratorType targetIter( itkMask, itkMask->GetLargestPossibleRegion() ); targetIter.GoToBegin(); while ( !sourceIter.IsAtEnd() ) { PixelType sourceValue = sourceIter.Get(); if ( sourceValue == index ) { targetIter.Set( 1 ); } ++sourceIter; ++targetIter; } } template < typename ImageType > void mitk::LabelSetImage::CalculateCenterOfMassProcessing(ImageType* itkImage, PixelType pixelValue, unsigned int layer) { // for now, we just retrieve the voxel in the middle typedef itk::ImageRegionConstIterator< ImageType > IteratorType; IteratorType iter( itkImage, itkImage->GetLargestPossibleRegion() ); iter.GoToBegin(); std::vector< typename ImageType::IndexType > indexVector; while ( !iter.IsAtEnd() ) { // TODO fix comparison warning more effective if ( iter.Get() == pixelValue ) { indexVector.push_back(iter.GetIndex()); } ++iter; } mitk::Point3D pos; pos.Fill(0.0); if (!indexVector.empty()) { typename itk::ImageRegionConstIteratorWithIndex< ImageType >::IndexType centerIndex; centerIndex = indexVector.at(indexVector.size()/2); if (centerIndex.GetIndexDimension() == 3) { pos[0] = centerIndex[0]; pos[1] = centerIndex[1]; pos[2] = centerIndex[2]; } else return; } GetLabelSet(layer)->GetLabel(pixelValue)->SetCenterOfMassIndex(pos); this->GetSlicedGeometry()->IndexToWorld(pos, pos); GetLabelSet(layer)->GetLabel(pixelValue)->SetCenterOfMassCoordinates(pos); } template < typename ImageType > void mitk::LabelSetImage::ClearBufferProcessing(ImageType* itkImage) { itkImage->FillBuffer(0); } // todo: concatenate all layers and not just the active one template < typename ImageType > void mitk::LabelSetImage::ConcatenateProcessing(ImageType* itkTarget, mitk::LabelSetImage* other) { typename ImageType::Pointer itkSource = ImageType::New(); mitk::CastToItkImage( other, itkSource ); typedef itk::ImageRegionConstIterator< ImageType > ConstIteratorType; typedef itk::ImageRegionIterator< ImageType > IteratorType; ConstIteratorType sourceIter( itkSource, itkSource->GetLargestPossibleRegion() ); IteratorType targetIter( itkTarget, itkTarget->GetLargestPossibleRegion() ); int numberOfTargetLabels = this->GetNumberOfLabels(GetActiveLayer()) - 1; // skip exterior sourceIter.GoToBegin(); targetIter.GoToBegin(); while (!sourceIter.IsAtEnd()) { PixelType sourceValue = sourceIter.Get(); PixelType targetValue = targetIter.Get(); if ( (sourceValue != 0) && !this->GetLabel(targetValue)->GetLocked() ) // skip exterior and locked labels { targetIter.Set( sourceValue + numberOfTargetLabels ); } ++sourceIter; ++targetIter; } } template < typename ImageType > void mitk::LabelSetImage::LayerContainerToImageProcessing(ImageType* target, unsigned int layer) { typename ImageType::Pointer itkSource; mitk::CastToItkImage(m_LayerContainer[layer], itkSource); typedef itk::ImageRegionConstIterator< ImageType > SourceIteratorType; typedef itk::ImageRegionIterator< ImageType > TargetIteratorType; SourceIteratorType sourceIter( itkSource, itkSource->GetLargestPossibleRegion() ); sourceIter.GoToBegin(); TargetIteratorType targetIter( target, target->GetLargestPossibleRegion() ); targetIter.GoToBegin(); while(!sourceIter.IsAtEnd()) { targetIter.Set( sourceIter.Get() ); ++sourceIter; ++targetIter; } } template < typename ImageType > void mitk::LabelSetImage::ImageToLayerContainerProcessing(ImageType* source, unsigned int layer) const { typename ImageType::Pointer itkTarget; mitk::CastToItkImage(m_LayerContainer[layer], itkTarget); typedef itk::ImageRegionConstIterator< ImageType > SourceIteratorType; typedef itk::ImageRegionIterator< ImageType > TargetIteratorType; SourceIteratorType sourceIter( source, source->GetLargestPossibleRegion() ); sourceIter.GoToBegin(); TargetIteratorType targetIter( itkTarget, itkTarget->GetLargestPossibleRegion() ); targetIter.GoToBegin(); while(!sourceIter.IsAtEnd()) { targetIter.Set( sourceIter.Get() ); ++sourceIter; ++targetIter; } } template < typename ImageType > void mitk::LabelSetImage::EraseLabelProcessing(ImageType* itkImage, PixelType pixelValue, unsigned int /*layer*/) { typedef itk::ImageRegionIterator< ImageType > IteratorType; IteratorType iter( itkImage, itkImage->GetLargestPossibleRegion() ); iter.GoToBegin(); while (!iter.IsAtEnd()) { PixelType value = iter.Get(); if (value == pixelValue) { iter.Set( 0 ); } ++iter; } } template < typename ImageType > void mitk::LabelSetImage::MergeLabelProcessing(ImageType* itkImage, PixelType pixelValue, PixelType index) { typedef itk::ImageRegionIterator< ImageType > IteratorType; IteratorType iter( itkImage, itkImage->GetLargestPossibleRegion() ); iter.GoToBegin(); while (!iter.IsAtEnd()) { if (iter.Get() == index) { iter.Set( pixelValue ); } ++iter; } } bool mitk::Equal(const mitk::LabelSetImage& leftHandSide, const mitk::LabelSetImage& rightHandSide, ScalarType eps, bool verbose) { bool returnValue = true; /* LabelSetImage members */ MITK_INFO(verbose) << "--- LabelSetImage Equal ---"; // number layers returnValue = leftHandSide.GetNumberOfLayers() == rightHandSide.GetNumberOfLayers(); if(!returnValue) { MITK_INFO(verbose) << "Number of layers not equal."; return false; } // total number labels returnValue = leftHandSide.GetTotalNumberOfLabels() == rightHandSide.GetTotalNumberOfLabels(); if(!returnValue) { MITK_INFO(verbose) << "Total number of labels not equal."; return false; } // active layer returnValue = leftHandSide.GetActiveLayer() == rightHandSide.GetActiveLayer(); if(!returnValue) { MITK_INFO(verbose) << "Active layer not equal."; return false; } // working image data returnValue = mitk::Equal((const mitk::Image&)leftHandSide,(const mitk::Image&)rightHandSide,eps,verbose); if(!returnValue) { MITK_INFO(verbose) << "Working image data not equal."; return false; } for(unsigned int layerIndex = 0 ; layerIndex < leftHandSide.GetNumberOfLayers(); layerIndex++) { // layer image data returnValue = mitk::Equal(*leftHandSide.GetLayerImage(layerIndex),*rightHandSide.GetLayerImage(layerIndex),eps,verbose); if(!returnValue) { MITK_INFO(verbose) << "Layer image data not equal."; return false; } // layer labelset data returnValue = mitk::Equal(*leftHandSide.GetLabelSet(layerIndex),*rightHandSide.GetLabelSet(layerIndex),eps,verbose); if(!returnValue) { MITK_INFO(verbose) << "Layer labelset data not equal."; return false; } } return returnValue; } diff --git a/Modules/Multilabel/mitkLabelSetImage.h b/Modules/Multilabel/mitkLabelSetImage.h index 5d1e74c0a7..f450df4300 100644 --- a/Modules/Multilabel/mitkLabelSetImage.h +++ b/Modules/Multilabel/mitkLabelSetImage.h @@ -1,341 +1,338 @@ /*=================================================================== 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 __mitkLabelSetImage_H_ #define __mitkLabelSetImage_H_ #include "mitkImage.h" #include "MitkMultilabelExports.h" #include #include #include #include -#include namespace mitk { //##Documentation //## @brief LabelSetImage class for handling labels and layers in a segmentation session. //## //## Handles operations for adding, removing, erasing and editing labels and layers. //## @ingroup Data class MITKMULTILABEL_EXPORT LabelSetImage : public Image { public: mitkClassMacro(LabelSetImage, Image) itkNewMacro(Self) typedef mitk::Label::PixelType PixelType; typedef itk::Image< PixelType, 3 > LabelSetImageType; typedef itk::VariableLengthVector< PixelType > VariableVectorType; - typedef itk::VectorImage< PixelType, 3 > VectorImageType; - typedef itk::VectorImageToImageAdaptor< PixelType, 3 > ImageAdaptorType; /** * \brief BeforeChangeLayerEvent (e.g. used for GUI integration) * As soon as active labelset should be changed, the signal emits. * Emitted by SetActiveLayer(int layer); */ Message<> BeforeChangeLayerEvent; /** * \brief AfterchangeLayerEvent (e.g. used for GUI integration) * As soon as active labelset was changed, the signal emits. * Emitted by SetActiveLayer(int layer); */ Message<> AfterchangeLayerEvent; /** * @brief Initialize an empty mitk::LabelSetImage using the information * of an mitk::Image * @param image the image which is used for initializing the mitk::LabelSetImage */ using mitk::Image::Initialize; virtual void Initialize(const mitk::Image* image) override; /** * \brief */ void Concatenate(mitk::LabelSetImage* image); /** * \brief */ void ClearBuffer(); /** * @brief Merges the mitk::Label with a given target value with the active label * @param targetPixelValue the value of the mitk::Label that should be merged with the active one * @param layer the layer in which the merge should be performed */ void MergeLabel(PixelType targetPixelValue, unsigned int layer = 0); /** * @brief Merges a list of mitk::Labels with the mitk::Label that has a specific value * @param VectorOfLablePixelValues the list of labels that should be merge with the specified one * @param index the value of the label into which the other should be merged * @param layer the layer in which the merge should be performed */ void MergeLabels(std::vector& VectorOfLablePixelValues, PixelType index, unsigned int layer = 0); /** * \brief */ void UpdateCenterOfMass(PixelType pixelValue, unsigned int layer =0); /** * @brief Removes labels from the mitk::LabelSet of given layer. * Calls mitk::LabelSetImage::EraseLabels() which also removes the labels from within the image. * @param VectorOfLabelPixelValues a list of labels to be removed * @param layer the layer in which the labels should be removed */ void RemoveLabels(std::vector& VectorOfLabelPixelValues, unsigned int layer = 0); /** * @brief Erases the label with the given value in the given layer from the underlying image. * The label itself will not be erased from the respective mitk::LabelSet. In order to * remove the label itself use mitk::LabelSetImage::RemoveLabels() * @param pixelValue the label which will be remove from the image * @param layer the layer in which the label should be removed */ void EraseLabel(PixelType pixelValue, unsigned int layer = 0); /** * @brief Similar to mitk::LabelSetImage::EraseLabel() this funtion erase a list of labels from the image * @param VectorOfLabelPixelValues the list of labels that should be remove * @param layer the layer for which the labels should be removed */ void EraseLabels(std::vector& VectorOfLabelPixelValues, unsigned int layer = 0); /** * \brief Returns true if the value exists in one of the labelsets*/ bool ExistLabel(PixelType pixelValue) const; /** * @brief Checks if a label exists in a certain layer * @param pixelValue the label value * @param layer the layer in which should be searched for the label * @return true if the label exists otherwise false */ bool ExistLabel(PixelType pixelValue, unsigned int layer) const; /** * \brief Returns true if the labelset exists*/ bool ExistLabelSet(unsigned int layer) const; /** * @brief Returns the active label of a specific layer * @param layer the layer ID for which the active label should be returned * @return the active label of the specified layer */ mitk::Label* GetActiveLabel(unsigned int layer = 0); /** * @brief Returns the mitk::Label with the given pixelValue and for the given layer * @param pixelValue the pixel value of the label * @param layer the layer in which the labels should be located * @return the mitk::Label if available otherwise NULL */ mitk::Label* GetLabel(PixelType pixelValue, unsigned int layer = 0) const; /** * @brief Returns the currently active mitk::LabelSet * @return the mitk::LabelSet of the active layer or NULL if non is present */ mitk::LabelSet* GetActiveLabelSet(); /** * @brief Gets the mitk::LabelSet for the given layer * @param layer the layer for which the mitk::LabelSet should be retrieved * @return the respective mitk::LabelSet or NULL if non exists for the given layer */ mitk::LabelSet * GetLabelSet(unsigned int layer = 0); const mitk::LabelSet * GetLabelSet(unsigned int layer = 0) const; /** * @brief Gets the ID of the currently active layer * @return the ID of the active layer */ unsigned int GetActiveLayer() const; /** * @brief Get the number of all existing mitk::Labels for a given layer * @param layer the layer ID for which the active mitk::Labels should be retrieved * @return the number of all existing mitk::Labels for the given layer */ unsigned int GetNumberOfLabels(unsigned int layer = 0) const; /** * @brief Returns the number of all labels summed up across all layers * @return the overall number of labels across all layers */ unsigned int GetTotalNumberOfLabels() const; /** * \brief */ void SurfaceStamp(mitk::Surface* surface, bool forceOverwrite); /** * \brief */ mitk::Image::Pointer CreateLabelMask(PixelType index); /** * @brief Initialize a new mitk::LabelSetImage by an given image. * For all distinct pixel values of the parameter image new labels will * be created. If the number of distinct pixel values exceeds mitk::Label::MAX_LABEL_VALUE * a new layer will be created * @param image the image which is used for initialization */ void InitializeByLabeledImage(mitk::Image::Pointer image); /** * \brief */ void MaskStamp(mitk::Image* mask, bool forceOverwrite); /** * \brief */ void SetActiveLayer(unsigned int layer); /** * \brief */ unsigned int GetNumberOfLayers() const; - /** - * \brief */ - VectorImageType::Pointer GetVectorImage(bool forceUpdate) const; - - /** - * \brief */ - void SetVectorImage(VectorImageType::Pointer image ); - /** * @brief Adds a new layer to the LabelSetImage. The new layer will be set as the active one * @param layer a mitk::LabelSet which will be set as new layer. * @return the layer ID of the new layer */ unsigned int AddLayer(mitk::LabelSet::Pointer layer =nullptr); + /** + * \brief Add a layer based on a provided mitk::Image + * \param layerImage is added to the vector of label images + * \param lset a label set that will be added to the new layer if provided + *\return the layer ID of the new layer + */ + unsigned int AddLayer(mitk::Image::Pointer layerImage, mitk::LabelSet::Pointer lset = nullptr); + /** * @brief Removes the active layer and the respective mitk::LabelSet and image information. * The new active layer is the one below, if exists */ void RemoveLayer(); /** * \brief */ mitk::Image* GetLayerImage(unsigned int layer); const mitk::Image* GetLayerImage(unsigned int layer) const; void OnLabelSetModified(); /** * @brief Sets the label which is used as default exterior label when creating a new layer * @param label the label which will be used as new exterior label */ void SetExteriorLabel(mitk::Label * label); /** * @brief Gets the mitk::Label which is used as default exterior label * @return the exterior mitk::Label */ mitk::Label* GetExteriorLabel(); const mitk::Label* GetExteriorLabel() const; protected: mitkCloneMacro(Self) LabelSetImage(); LabelSetImage(const LabelSetImage & other); virtual ~LabelSetImage(); template < typename ImageType1, typename ImageType2 > void ChangeLayerProcessing( ImageType1* source, ImageType2* target ); template < typename ImageType > void LayerContainerToImageProcessing( ImageType* source, unsigned int layer); template < typename ImageType > void ImageToLayerContainerProcessing( ImageType* source, unsigned int layer) const; template < typename ImageType > void CalculateCenterOfMassProcessing( ImageType* input, PixelType index, unsigned int layer); template < typename ImageType > void ClearBufferProcessing( ImageType* input); template < typename ImageType > void EraseLabelProcessing( ImageType* input, PixelType index, unsigned int layer); // template < typename ImageType > // void ReorderLabelProcessing( ImageType* input, int index, int layer); template < typename ImageType > void MergeLabelProcessing( ImageType* input, PixelType pixelValue, PixelType index); template < typename ImageType > void ConcatenateProcessing( ImageType* input, mitk::LabelSetImage* other); template < typename ImageType > void MaskStampProcessing( ImageType* input, mitk::Image* mask, bool forceOverwrite); template < typename ImageType > void CreateLabelMaskProcessing( ImageType* input, mitk::Image* mask, PixelType index); template < typename ImageType1, typename ImageType2 > void InitializeByLabeledImageProcessing( ImageType1* input, ImageType2* other); std::vector< LabelSet::Pointer > m_LabelSetContainer; std::vector< Image::Pointer > m_LayerContainer; int m_ActiveLayer; mitk::Label::Pointer m_ExteriorLabel; }; /** * @brief Equal A function comparing two label set images for beeing equal in meta- and imagedata * * @ingroup MITKTestingAPI * * Following aspects are tested for equality: * - LabelSetImage members * - working image data * - layer image data * - labels in label set * * @param rightHandSide An image to be compared * @param leftHandSide An image to be compared * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return true, if all subsequent comparisons are true, false otherwise */ MITKMULTILABEL_EXPORT bool Equal( const mitk::LabelSetImage& leftHandSide, const mitk::LabelSetImage& rightHandSide, ScalarType eps, bool verbose ); } // namespace mitk #endif // __mitkLabelSetImage_H_ diff --git a/Modules/Multilabel/mitkLabelSetImageConverter.cpp b/Modules/Multilabel/mitkLabelSetImageConverter.cpp new file mode 100644 index 0000000000..c3bc05a517 --- /dev/null +++ b/Modules/Multilabel/mitkLabelSetImageConverter.cpp @@ -0,0 +1,133 @@ +/*=================================================================== + +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 "mitkLabelSetImageConverter.h" + +// mitk includes +#include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" +#include + +// itk includes +#include "itkImage.h" +#include "itkVectorImage.h" +#include +#include + +template < typename ImageType > +void VectorOfMitkImagesToMitkVectorImage(ImageType* source, mitk::Image::Pointer &output, mitk::LabelSetImage::Pointer input) +{ + typedef itk::ComposeImageFilter< ImageType > ComposeFilterType; + + unsigned int numberOfLayers = input->GetNumberOfLayers(); + + ComposeFilterType::Pointer vectorImageComposer = ComposeFilterType::New(); + + for (unsigned int layer(0); layer < numberOfLayers; layer++) + { + typename ImageType::Pointer itkCurrentLayer; + mitk::CastToItkImage(input->GetLayerImage(layer), itkCurrentLayer); + + vectorImageComposer->SetInput(layer, itkCurrentLayer); + } + + try + { + vectorImageComposer->Update(); + } + catch (const itk::ExceptionObject& e) + { + MITK_ERROR << "Caugt exception while updating compose filter: " << e.what(); + } + + output = mitk::GrabItkImageMemory(vectorImageComposer->GetOutput()); +} + +mitk::Image::Pointer mitk::LabelSetImageConverter::ConvertLabelSetImageToImage(const mitk::LabelSetImage::Pointer input) +{ + unsigned int numberOfLayers = input->GetNumberOfLayers(); + + if (numberOfLayers == 0) + { + mitkThrow() << "Tried to convert LabelSetImage without layers"; + } + + mitk::Image::Pointer output; + AccessByItk_2(input->GetLayerImage(0), VectorOfMitkImagesToMitkVectorImage, output, input); + + return output; +} + +template +void MitkImageToMitkLabelSetImage(itk::Image< TPixel, VDimensions> * source, mitk::LabelSetImage::Pointer &output) +{ + // do nothing for non-vector images +} + +template +void MitkImageToMitkLabelSetImage(itk::VectorImage< TPixel, VDimensions> * source, mitk::LabelSetImage::Pointer &output) +{ + typedef itk::VectorImage< TPixel, VDimensions > VectorImageType; + typedef itk::Image< TPixel, VDimensions > ImageType; + typedef itk::VectorIndexSelectionCastImageFilter< VectorImageType, ImageType > VectorIndexSelectorType; + + unsigned int numberOfComponents = source->GetVectorLength(); + + if (numberOfComponents < 1) + { + mitkThrow() << "At least one Component is required." + } + + typename VectorIndexSelectorType::Pointer vectorIndexSelector = typename VectorIndexSelectorType::New(); + + VectorIndexSelector->SetIndex(0); + VectorIndexSelector->SetInput(source); + + mitk::Image::Pointer tempImage; + mitk::GrabItkImageMemory(VectorIndexSelector->GetOutput(), tempImage); + + output = mitk::LabelSetImage::New(); + output->InitializeByLabeledImage(tempImage); + + for (unsigned int layer = 1; layer < numberOfComponents; ++layer) + { + typename VectorIndexSelectorType::Pointer vectorIndexSelectorLoop = typename VectorIndexSelectorType::New(); + VectorIndexSelectorLoop->SetIndex(layer); + VectorIndexSelector->SetInput(source); + + mitk::Image::Pointer loopImage; + mitk::GrabItkImageMemory(vectorIndexSelectorLoop->GetOutput(), loopImage); + + output->AddLayer(loopImage); + } + +} + +mitk::LabelSetImage::Pointer mitk::LabelSetImageConverter::ConvertImageToLabelSetImage(const mitk::Image::Pointer input) +{ + mitk::LabelSetImage::Pointer output; + + AccessByItk_1(input, MitkImageToMitkLabelSetImage, output); + + // if no vector image was detected + if ( output.IsNull() ) + { + output = mitk::LabelSetImage::New(); + output->InitializeByLabeledImage( input ); + } + + return output; +} diff --git a/Modules/Multilabel/mitkLabelSetImageConverter.h b/Modules/Multilabel/mitkLabelSetImageConverter.h new file mode 100644 index 0000000000..128d8691a9 --- /dev/null +++ b/Modules/Multilabel/mitkLabelSetImageConverter.h @@ -0,0 +1,54 @@ +/*=================================================================== + +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 __mitkLabelSetImageConverter_H_ +#define __mitkLabelSetImageConverter_H_ + +// for export +#include "MitkMultilabelExports.h" + +// mitk includes +#include "mitkImage.h" +#include "mitkLabelSetImage.h" + + +namespace mitk +{ + + /** + * \brief Converts mitkLabelSetImage into a mitk::Image containing an itk::VectorImage + * + * Convenience class to avoid the dimension templating hassle. + */ + +class MITKMULTILABEL_EXPORT LabelSetImageConverter +{ + +public: + /// \brief Converts a mitk::LabelSetImage to an a itk::VectorImage containing mitk::Image, templating is internal + static mitk::Image::Pointer ConvertLabelSetImageToImage( const mitk::LabelSetImage::Pointer input ); + + /// \brief Converst a mitk::Image to a mitk::LabelSetImage, templating and differentation between itk::Image and itk::VectorImage is internal + static mitk::LabelSetImage::Pointer ConvertImageToLabelSetImage( const mitk::Image::Pointer input ); + +protected: + +}; + +} // namespace mitk + +#endif // __mitkLabelSetImageConverter_H_