diff --git a/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.cpp b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.cpp new file mode 100644 index 0000000000..9d93762602 --- /dev/null +++ b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.cpp @@ -0,0 +1,275 @@ +/*=================================================================== + +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 "mitkContourModelSetToImageFilter.h" + +#include +#include +#include +#include +#include +#include + +// TODO Move this one to Core so that this Filter can be in the ContourModel Module! +#include +// TODO + + +mitk::ContourModelSetToImageFilter::ContourModelSetToImageFilter() + : m_MakeOutputBinary( true ), + m_TimeStep( 0 ) +{ + // Create the output. + itk::DataObject::Pointer output = this->MakeOutput(0); + Superclass::SetNumberOfRequiredInputs(1); + Superclass::SetNumberOfRequiredOutputs(1); + Superclass::SetNthOutput(0, output); +} + +mitk::ContourModelSetToImageFilter::~ContourModelSetToImageFilter() +{ +} + +void mitk::ContourModelSetToImageFilter::GenerateInputRequestedRegion() +{ + mitk::Image* output = this->GetOutput(); + if((output->IsInitialized()==false) ) + return; + + GenerateTimeInInputRegion(output, const_cast< mitk::Image * > ( this->GetImage() )); +} + +void mitk::ContourModelSetToImageFilter::GenerateOutputInformation() +{ + mitk::Image *inputImage = (mitk::Image*)this->GetImage(); + mitk::Image::Pointer output = this->GetOutput(); + + itkDebugMacro(<<"GenerateOutputInformation()"); + + if((inputImage == NULL) || + (inputImage->IsInitialized() == false) || + (inputImage->GetTimeGeometry() == NULL)) return; + + if (m_MakeOutputBinary) + { + output->Initialize(mitk::MakeScalarPixelType() , *inputImage->GetTimeGeometry(),1,1); + } + else + { + output->Initialize(inputImage->GetPixelType(), *inputImage->GetTimeGeometry()); + } + + output->SetPropertyList(inputImage->GetPropertyList()->Clone()); +} + +itk::DataObject::Pointer mitk::ContourModelSetToImageFilter::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) +{ + return OutputType::New().GetPointer(); +} + +itk::DataObject::Pointer mitk::ContourModelSetToImageFilter::MakeOutput( const DataObjectIdentifierType & name ) +{ + itkDebugMacro("MakeOutput(" << name << ")"); + if( this->IsIndexedOutputName(name) ) + { + return this->MakeOutput( this->MakeIndexFromOutputName(name) ); + } + return OutputType::New().GetPointer(); +} + +const mitk::ContourModelSet* mitk::ContourModelSetToImageFilter::GetInput(void) +{ + if (this->GetNumberOfInputs() < 1) + { + return 0; + } + + return static_cast< const mitk::ContourModelSet* > + ( this->ProcessObject::GetInput(0) ); +} + +void mitk::ContourModelSetToImageFilter::SetInput(const ContourModelSet *input) +{ + // Process object is not const-correct so the const_cast is required here + this->ProcessObject::SetNthInput(0, + const_cast< mitk::ContourModelSet* >( input ) ); +} + +void mitk::ContourModelSetToImageFilter::SetImage(const mitk::Image *refImage) +{ + this->ProcessObject::SetNthInput( 1, const_cast< mitk::Image * >( refImage ) ); +} + +const mitk::Image* mitk::ContourModelSetToImageFilter::GetImage(void) +{ + return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(1)); +} + +void mitk::ContourModelSetToImageFilter::GenerateData() +{ + mitk::ContourModelSet* contourSet = const_cast(this->GetInput()); + + // Assure that the volume data of the output is set (fill volume with zeros) + this->InitializeOutputEmpty(); + + mitk::Image::Pointer outputImage = const_cast(this->GetOutput()); + + + if(outputImage.IsNull() || outputImage->IsInitialized() == false || !outputImage->IsVolumeSet(m_TimeStep)) + { + MITK_ERROR<<"Error creating output for specified image!"; + return; + } + + if (!contourSet || contourSet->GetContourModelList()->size() == 0) + { + MITK_ERROR<<"No contours specified!"; + return; + } + + mitk::Geometry3D* outputImageGeo = outputImage->GetGeometry(m_TimeStep); + + // Create mitkVtkImageOverwrite which is needed to write the slice back into the volume + vtkSmartPointer reslice = vtkSmartPointer::New(); + + // Create ExtractSliceFilter for extracting the corresponding slices from the volume + mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice); + extractor->SetInput( outputImage ); + extractor->SetTimeStep( m_TimeStep ); + extractor->SetResliceTransformByGeometry( outputImageGeo ); + + // Fill each contour of the contourmodelset into the image + mitk::ContourModelSet::ContourModelSetIterator it = contourSet->Begin(); + mitk::ContourModelSet::ContourModelSetIterator end = contourSet->End(); + while (it != end) + { + mitk::ContourModel* contour = it->GetPointer(); + + // 1. Create slice geometry using the contour points + mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); + mitk::Point3D point3D, tempPoint; + mitk::Vector3D normal; + + mitk::Image::Pointer slice; + + int sliceIndex; + bool isFrontside = true; + bool isRotated = false; + + // Determine plane orientation + point3D = contour->GetVertexAt(0)->Coordinates; + tempPoint = contour->GetVertexAt(contour->GetNumberOfVertices()*0.5)->Coordinates; + mitk::Vector3D vec = point3D - tempPoint; + vec.Normalize(); + outputImageGeo->WorldToIndex(point3D, point3D); + + mitk::PlaneGeometry::PlaneOrientation orientation; + if (mitk::Equal(vec[0], 0)) + { + orientation = mitk::PlaneGeometry::Sagittal; + sliceIndex = point3D[0]; + } + else if (mitk::Equal(vec[1], 0)) + { + orientation = mitk::PlaneGeometry::Frontal; + sliceIndex = point3D[1]; + } + else if (mitk::Equal(vec[2], 0)) + { + orientation = mitk::PlaneGeometry::Axial; + sliceIndex = point3D[2]; + } + else + { + // TODO Maybe rotate geometry to extract slice? + MITK_ERROR<<"Cannot detect correct slice number! Only axial, sagittal and frontal oriented contours are supported!"; + return; + } + + // Initialize plane using the detected orientation + plane->InitializeStandardPlane(outputImageGeo, orientation, sliceIndex, isFrontside, isRotated); + point3D = plane->GetOrigin(); + normal = plane->GetNormal(); + normal.Normalize(); + point3D += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 + plane->SetOrigin(point3D); + + // 2. Extract slice at the given position + extractor->SetWorldGeometry( plane ); + extractor->SetVtkOutputRequest(false); + reslice->SetOverwriteMode(false); + + extractor->Modified(); + extractor->Update(); + + slice = extractor->GetOutput(); + + // 3. Fill contour into slice + mitk::ContourModel::Pointer projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contour, true, false); + mitk::ContourModelUtils::FillContourInSlice(projectedContour, slice); + + // 4. Write slice back into image volume + reslice->SetInputSlice(slice->GetVtkImageData()); + + //set overwrite mode to true to write back to the image volume + reslice->SetOverwriteMode(true); + reslice->Modified(); + + extractor->SetVtkOutputRequest(true); + extractor->Modified(); + extractor->Update(); + + mitk::ProgressBar::GetInstance()->Progress(); + ++it; + } + + outputImage->Modified(); + outputImage->GetVtkImageData()->Modified(); +} + +void mitk::ContourModelSetToImageFilter::InitializeOutputEmpty() +{ + // Initialize the output's volume with zeros + mitk::Image* output = this->GetOutput(); + unsigned int byteSize = output->GetPixelType().GetSize(); + + if(output->GetDimension() < 4) + { + for (unsigned int dim = 0; dim < output->GetDimension(); ++dim) + { + byteSize *= output->GetDimension(dim); + } + + mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(0)); + + memset( writeAccess.GetData(), 0, byteSize ); + } + else + { + //if we have a time-resolved image we need to set memory to 0 for each time step + for (unsigned int dim = 0; dim < 3; ++dim) + { + byteSize *= output->GetDimension(dim); + } + + for( unsigned int volumeNumber = 0; volumeNumber < output->GetDimension(3); volumeNumber++) + { + mitk::ImageWriteAccessor writeAccess(output, output->GetVolumeData(volumeNumber)); + + memset( writeAccess.GetData(), 0, byteSize ); + } + } +} diff --git a/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.h b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.h new file mode 100644 index 0000000000..f28e3bbdf9 --- /dev/null +++ b/Modules/Segmentation/Algorithms/mitkContourModelSetToImageFilter.h @@ -0,0 +1,98 @@ +/*=================================================================== + +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 _MITK_CONTOURMODEL_SOURCE_H +#define _MITK_CONTOURMODEL_SOURCE_H + +#include +#include + +namespace mitk +{ + +class ContourModelSet; + +/** + * @brief Fills a given mitk::ContourModelSet into a given mitk::Image + * @ingroup Process + */ +class MitkSegmentation_EXPORT ContourModelSetToImageFilter : public ImageSource +{ +public: + + mitkClassMacro( ContourModelSetToImageFilter, ImageSource ) + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + itkSetMacro(MakeOutputBinary, bool); + itkGetMacro(MakeOutputBinary, bool); + itkBooleanMacro(MakeOutputBinary); + + itkSetMacro(TimeStep, unsigned int); + + /** + * Allocates a new output object and returns it. Currently the + * index idx is not evaluated. + * @param idx the index of the output for which an object should be created + * @returns the new object + */ + virtual itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ); + + /** + * This is a default implementation to make sure we have something. + * Once all the subclasses of ProcessObject provide an appopriate + * MakeOutput(), then ProcessObject::MakeOutput() can be made pure + * virtual. + */ + virtual itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name); + + virtual void GenerateInputRequestedRegion(); + + virtual void GenerateOutputInformation(); + + virtual void GenerateData(); + + const mitk::ContourModelSet* GetInput(void); + + using itk::ProcessObject::SetInput; + virtual void SetInput(const mitk::ContourModelSet* input); + + /** + * @brief Set the image which will be used to initialize the output of this filter. + * @param refImage the image used to initialize the output image + */ + void SetImage(const mitk::Image *refImage); + + const mitk::Image *GetImage(void); + +protected: + + ContourModelSetToImageFilter(); + + virtual ~ContourModelSetToImageFilter(); + + /** + * @brief Initializes the volume of the output image with zeros + */ + void InitializeOutputEmpty(); + + bool m_MakeOutputBinary; + + unsigned int m_TimeStep; +}; + +} +#endif // #_MITK_CONTOURMODEL_SOURCE_H diff --git a/Modules/Segmentation/files.cmake b/Modules/Segmentation/files.cmake index 59d2b99d96..b29502db2a 100644 --- a/Modules/Segmentation/files.cmake +++ b/Modules/Segmentation/files.cmake @@ -1,122 +1,119 @@ set(CPP_FILES Algorithms/mitkCalculateSegmentationVolume.cpp - #Algorithms/mitkContourModelSource.cpp - #Algorithms/mitkContourModelSubDivisionFilter.cpp - #Algorithms/mitkContourModelToPointSetFilter.cpp - #Algorithms/mitkContourModelToSurfaceFilter.cpp + Algorithms/mitkContourModelSetToImageFilter.cpp Algorithms/mitkContourSetToPointSetFilter.cpp Algorithms/mitkContourUtils.cpp Algorithms/mitkCorrectorAlgorithm.cpp Algorithms/mitkDiffImageApplier.cpp Algorithms/mitkDiffSliceOperation.cpp Algorithms/mitkDiffSliceOperationApplier.cpp Algorithms/mitkImageLiveWireContourModelFilter.cpp Algorithms/mitkImageToContourFilter.cpp #Algorithms/mitkImageToContourModelFilter.cpp Algorithms/mitkImageToLiveWireContourFilter.cpp Algorithms/mitkManualSegmentationToSurfaceFilter.cpp Algorithms/mitkOtsuSegmentationFilter.cpp Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp Algorithms/mitkOverwriteSliceImageFilter.cpp Algorithms/mitkSegmentationObjectFactory.cpp Algorithms/mitkSegmentationSink.cpp Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp Algorithms/mitkShowSegmentationAsSmoothedSurface.cpp Algorithms/mitkShowSegmentationAsSurface.cpp Algorithms/mitkVtkImageOverwrite.cpp Controllers/mitkSegmentationInterpolationController.cpp Controllers/mitkToolManager.cpp Controllers/mitkSegmentationModuleActivator.cpp Controllers/mitkToolManagerProvider.cpp DataManagement/mitkContour.cpp #DataManagement/mitkContourElement.cpp #DataManagement/mitkContourModel.cpp DataManagement/mitkContourSet.cpp DataManagement/mitkExtrudedContour.cpp Interactions/mitkAdaptiveRegionGrowingTool.cpp Interactions/mitkAddContourTool.cpp Interactions/mitkAutoCropTool.cpp Interactions/mitkAutoSegmentationTool.cpp Interactions/mitkBinaryThresholdTool.cpp Interactions/mitkBinaryThresholdULTool.cpp Interactions/mitkCalculateGrayValueStatisticsTool.cpp Interactions/mitkCalculateVolumetryTool.cpp Interactions/mitkContourInteractor.cpp Interactions/mitkContourModelInteractor.cpp Interactions/mitkContourModelLiveWireInteractor.cpp Interactions/mitkContourTool.cpp Interactions/mitkCorrectorTool2D.cpp Interactions/mitkCreateSurfaceTool.cpp Interactions/mitkDrawPaintbrushTool.cpp Interactions/mitkErasePaintbrushTool.cpp Interactions/mitkEraseRegionTool.cpp Interactions/mitkExtrudedContourInteractor.cpp Interactions/mitkFastMarchingTool.cpp Interactions/mitkFastMarchingTool3D.cpp Interactions/mitkFeedbackContourTool.cpp Interactions/mitkFillRegionTool.cpp Interactions/mitkLiveWireTool2D.cpp Interactions/mitkOtsuTool3D.cpp Interactions/mitkPaintbrushTool.cpp Interactions/mitkPixelManipulationTool.cpp Interactions/mitkRegionGrow3DTool.cpp Interactions/mitkRegionGrowingTool.cpp Interactions/mitkSegmentationsProcessingTool.cpp Interactions/mitkSetRegionTool.cpp Interactions/mitkSegTool2D.cpp Interactions/mitkSubtractContourTool.cpp Interactions/mitkTool.cpp Interactions/mitkToolCommand.cpp Interactions/mitkWatershedTool.cpp Interactions/mitkPickingTool.cpp #IO/mitkContourModelIOFactory.cpp #IO/mitkContourModelReader.cpp #IO/mitkContourModelWriter.cpp #IO/mitkContourModelWriterFactory.cpp Rendering/mitkContourMapper2D.cpp #Rendering/mitkContourModelGLMapper2D.cpp #Rendering/mitkContourModelMapper2D.cpp #Rendering/mitkContourModelMapper3D.cpp Rendering/mitkContourSetMapper2D.cpp Rendering/mitkContourSetVtkMapper3D.cpp Rendering/mitkContourVtkMapper3D.cpp SegmentationUtilities/BooleanOperations/mitkBooleanOperation.cpp SegmentationUtilities/MorphologicalOperations/mitkMorphologicalOperations.cpp ) set(RESOURCE_FILES Add_48x48.png Add_Cursor_32x32.png Correction_48x48.png Correction_Cursor_32x32.png Erase_48x48.png Erase_Cursor_32x32.png FastMarching_48x48.png FastMarching_Cursor_32x32.png Fill_48x48.png Fill_Cursor_32x32.png LiveWire_48x48.png LiveWire_Cursor_32x32.png Otsu_48x48.png Paint_48x48.png Paint_Cursor_32x32.png Pick_48x48.png RegionGrowing_48x48.png RegionGrowing_Cursor_32x32.png Subtract_48x48.png Subtract_Cursor_32x32.png Threshold_48x48.png TwoThresholds_48x48.png Watershed_48x48.png Watershed_Cursor_32x32.png Wipe_48x48.png Wipe_Cursor_32x32.png Interactions/dummy.xml Interactions/LiveWireTool.xml Interactions/PressMoveRelease.xml Interactions/PressMoveReleaseAndPointSetting.xml Interactions/PressMoveReleaseWithCTRLInversion.xml Interactions/PressMoveReleaseWithCTRLInversionAllMouseMoves.xml Interactions/SegmentationToolsConfig.xml ) diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.cpp index 9992684b8e..24ec826e15 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.cpp @@ -1,277 +1,172 @@ /*=================================================================== 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 "QmitkContourModelToImageWidget.h" #include "mitkImage.h" #include "../../Common/QmitkDataSelectionWidget.h" #include #include +#include #include #include #include #include #include #include #include #include -static const char* const HelpText = "Select a binary image and a contour(set)"; +static const char* const HelpText = "Select a image and a contour(set)"; QmitkContourModelToImageWidget::QmitkContourModelToImageWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) : QmitkSegmentationUtilityWidget(timeNavigationController, parent) { m_Controls.setupUi(this); - m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::SegmentationPredicate); + m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::ImageAndSegmentationPredicate); m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::ContourModelPredicate); m_Controls.dataSelectionWidget->SetHelpText(HelpText); this->EnableButtons(false); connect (m_Controls.btnProcess, SIGNAL(pressed()), this, SLOT(OnProcessPressed())); connect(m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); if( m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() && m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() ) { this->OnSelectionChanged( 0, m_Controls.dataSelectionWidget->GetSelection(0)); } } QmitkContourModelToImageWidget::~QmitkContourModelToImageWidget() { } void QmitkContourModelToImageWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection) { QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0); mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1); if (node0.IsNull() || node1.IsNull() ) { this->EnableButtons(false); + dataSelectionWidget->SetHelpText(HelpText); } else { this->SelectionControl(index, selection); } } void QmitkContourModelToImageWidget::SelectionControl(unsigned int index, const mitk::DataNode* /*selection*/) { QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index); - //TODO check if contours are inside the image! - dataSelectionWidget->SetHelpText(""); this->EnableButtons(); } void QmitkContourModelToImageWidget::EnableButtons(bool enable) { m_Controls.btnProcess->setEnabled(enable); } void QmitkContourModelToImageWidget::OnProcessPressed() { QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; - mitk::DataNode::Pointer segmentationNode = dataSelectionWidget->GetSelection(0); + mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0); + mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1); - if (segmentationNode.IsNull()) + if(imageNode.IsNull() || contourNode.IsNull() ) { - MITK_ERROR<<"Error writing contours into binary image! No image selected!"; + MITK_ERROR << "Selection does not contain valid data"; + QMessageBox::information( this, "Contour To Image", + "Selection does not contain valid data, please select a binary image and a contour(set)", QMessageBox::Ok ); + m_Controls.btnProcess->setEnabled(false); return; } - mitk::Image::Pointer segmentationImage = static_cast(segmentationNode->GetData()); + mitk::Image::Pointer image = static_cast(imageNode->GetData()); - if (segmentationImage.IsNull()) + if (image.IsNull()) { - MITK_ERROR<<"Error writing contours into binary image! Invalid image data selected!"; + MITK_ERROR<<"Error writing contours into image! Invalid image data selected!"; return; } unsigned int timeStep = this->GetTimeNavigationController()->GetTime()->GetPos(); - m_SegmentationImage = segmentationImage; - m_SegmentationImageGeometry = segmentationImage->GetTimeGeometry()->GetGeometryForTimeStep(timeStep); - mitk::ContourModelSet::Pointer contourSet; - mitk::DataNode::Pointer contourNode = dataSelectionWidget->GetSelection(1); mitk::ContourModel::Pointer contour = dynamic_cast(contourNode->GetData()); if (contour.IsNotNull()) { contourSet = mitk::ContourModelSet::New(); contourSet->AddContourModel(contour); } else { contourSet = static_cast(contourNode->GetData()); if (contourSet.IsNull()) { MITK_ERROR<<"Error writing contours into binary image! Invalid contour data selected!"; return; } } //Disable Buttons during calculation and initialize Progressbar this->EnableButtons(false); unsigned int num_contours = contourSet->GetContourModelList()->size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(num_contours); mitk::ProgressBar::GetInstance()->Progress(); - // Do actual filling - mitk::ContourModel::Pointer projectedContour; - mitk::ContourModelSet::ContourModelSetIterator it = contourSet->Begin(); - mitk::ContourModelSet::ContourModelSetIterator end = contourSet->End(); - while (it != end) - { - mitk::ContourModel* contour = it->GetPointer(); - - //Check Controls - - // 1. Get corresponding image slice - mitk::Image::Pointer slice = this->GetSliceForContour(contour, timeStep); - - // 2. Fill contour into slice - projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contour, true, false); - mitk::ContourModelUtils::FillContourInSlice(projectedContour, slice); -// mitk::DataNode::Pointer filled = mitk::DataNode::New(); -// filled->SetName("FILLED"); -// filled->SetData(slice); -// dataSelectionWidget->GetDataStorage()->Add(filled); - - // 3. Write slice back into image volume - if (slice.IsNotNull()) - { - this->WriteBackSlice(slice, timeStep); - } - else - { - MITK_ERROR<<"Contour to image failed!"; - } - mitk::ProgressBar::GetInstance()->Progress(); - ++it; - } - - if(segmentationNode.IsNull() || contourNode.IsNull() ) + // Use mitk::ContourModelSetToImageFilter to fill the ContourModelSet into the image + mitk::ContourModelSetToImageFilter::Pointer contourFiller = mitk::ContourModelSetToImageFilter::New(); + contourFiller->SetTimeStep(timeStep); + contourFiller->SetImage(image); + contourFiller->SetInput(contourSet); + contourFiller->MakeOutputBinaryOn(); + contourFiller->Update(); + + // Add result to data storage + mitk::Image::Pointer result = contourFiller->GetOutput(); + if (result.IsNull()) { - MITK_ERROR << "Selection does not contain valid data"; - QMessageBox::information( this, "Contour To Image", - "Selection does not contain valid data, please select a binary image and a contour(set)", QMessageBox::Ok ); - m_Controls.btnProcess->setEnabled(false); + MITK_ERROR<<"Could not write the selected contours into the image!"; return; } - this->EnableButtons(); -} - -mitk::Image::Pointer QmitkContourModelToImageWidget::GetSliceForContour(mitk::ContourModel::Pointer contour, unsigned int timestep) -{ - mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); - mitk::Point3D point3D, tempPoint; - mitk::Vector3D normal; - - mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(); - mitk::Image::Pointer slice; - - int sliceIndex; - bool isFrontside = true; - bool isRotated = false; - - point3D = contour->GetVertexAt(0)->Coordinates; - tempPoint = contour->GetVertexAt(contour->GetNumberOfVertices()*0.5)->Coordinates; - mitk::Vector3D vec = point3D - tempPoint; - vec.Normalize(); -// MITK_INFO<GetIndexToWorldTransform()->GetMatrix(); - m_SegmentationImageGeometry->WorldToIndex(point3D, point3D); - mitk::PlaneGeometry::PlaneOrientation orientation; - if (mitk::Equal(vec[0], 0)) - { - orientation = mitk::PlaneGeometry::Sagittal; - sliceIndex = point3D[0]; - } - else if (mitk::Equal(vec[1], 0)) - { - orientation = mitk::PlaneGeometry::Frontal; - sliceIndex = point3D[1]; - } - else if (mitk::Equal(vec[2], 0)) - { - orientation = mitk::PlaneGeometry::Axial; - sliceIndex = point3D[2]; - } - else - { - // Maybe rotate geometry to extract slice? - MITK_ERROR<<"Cannot detect correct slice number! Only axial, sagittal and frontal oriented contours are supported!"; - return 0; - } - plane->InitializeStandardPlane(m_SegmentationImageGeometry, orientation, sliceIndex, isFrontside, isRotated); - point3D = plane->GetOrigin(); - normal = plane->GetNormal(); - normal.Normalize(); - point3D += normal * 0.5;//pixelspacing is 1, so half the spacing is 0.5 - plane->SetOrigin(point3D); + result->DisconnectPipeline(); + mitk::DataNode::Pointer filled = mitk::DataNode::New(); + std::stringstream stream; + stream << imageNode->GetName(); + stream << "_"; + stream << contourNode->GetName(); + filled->SetName(stream.str()); + filled->SetData(result); + dataSelectionWidget->GetDataStorage()->Add(filled, imageNode); - m_CurrentPlane = plane; - - // 2. fill into it - extractor->SetInput( m_SegmentationImage ); -// extractor->SetTimeStep( timeStep ); - extractor->SetWorldGeometry( plane ); - extractor->SetVtkOutputRequest(false); - extractor->SetResliceTransformByGeometry( m_SegmentationImageGeometry ); - - extractor->Modified(); - extractor->Update(); - - slice = extractor->GetOutput(); - return slice; -} - -void QmitkContourModelToImageWidget::WriteBackSlice(mitk::Image::Pointer slice, unsigned int timestep) -{ - //Make sure that for reslicing and overwriting the same alogrithm is used. We can specify the mode of the vtk reslicer - vtkSmartPointer reslice = vtkSmartPointer::New(); - - //Set the slice as 'input' - reslice->SetInputSlice(slice->GetVtkImageData()); - - //set overwrite mode to true to write back to the image volume - reslice->SetOverwriteMode(true); - reslice->Modified(); - - mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice); - extractor->SetInput( m_SegmentationImage ); - extractor->SetTimeStep( timestep ); - extractor->SetWorldGeometry( m_CurrentPlane ); - extractor->SetVtkOutputRequest(true); - extractor->SetResliceTransformByGeometry( m_SegmentationImage->GetGeometry( timestep ) ); - - extractor->Modified(); - extractor->Update(); + this->EnableButtons(); - m_SegmentationImage->Modified(); - m_SegmentationImage->GetVtkImageData()->Modified(); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.h index 76afb38f08..52750f08f6 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.h @@ -1,92 +1,76 @@ /*=================================================================== 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 QmitkContourModelToImageWidget_h #define QmitkContourModelToImageWidget_h #include "../QmitkSegmentationUtilityWidget.h" #include namespace mitk { class Image; class ContourModelSet; class ContourModel; class Geometry3D; class PlaneGeometry; } /*! \brief QmitkContourModelToImageWidget Tool masks an image with a binary image or a surface. The Method requires an image and a binary image mask or a surface. The input image and the binary image mask must be of the same size. Masking with a surface creates first a binary image of the surface and then use this for the masking of the input image. */ class QmitkContourModelToImageWidget : public QmitkSegmentationUtilityWidget { Q_OBJECT public: /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */ explicit QmitkContourModelToImageWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = NULL); /** @brief Defaul destructor. */ ~QmitkContourModelToImageWidget(); private slots: /** @brief This slot is called if the selection in the workbench is changed. */ void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); -// /** @brief This slot is called if user activates the radio button for masking an image with a binary image mask. */ -// void OnContourModelToImageToggled(bool); - -// /** @brief This slot is called if user activates the radio button for masking an image with a surface. */ -// void OnSurfaceMaskingToggled(bool); - /** @brief This slot is called if user activates the button to mask an image. */ void OnProcessPressed(); private: /** @brief Check if selections is valid. */ void SelectionControl( unsigned int index, const mitk::DataNode* selection); /** @brief Enable buttons if data selction is valid. */ void EnableButtons(bool enable = true); - /** @brief Extracts the slice which correspond to the position of the contour*/ - itk::SmartPointer GetSliceForContour(itk::SmartPointer contour, unsigned int timestep); - - /** @brief Extracts the slice which correspond to the position of the contour*/ - void WriteBackSlice (itk::SmartPointer slice, unsigned int timestep); - /** @brief Fills a mitk::ContourModel into a given segmentation image */ itk::SmartPointer ContourModelToImage(itk::SmartPointer segmenationImage, itk::SmartPointer contour ); /** @brief Fills a whole ContourModelSet into a given segmentation image */ itk::SmartPointer ContourModelSetToImage( itk::SmartPointer segmenationImage, itk::SmartPointer contourSet ); Ui::QmitkContourModelToImageWidgetControls m_Controls; - - itk::SmartPointer m_SegmentationImage; - mitk::Geometry3D::Pointer m_SegmentationImageGeometry; - itk::SmartPointer m_CurrentPlane; }; #endif