diff --git a/Applications/Tutorial/Step6RegionGrowing1.cpp b/Applications/Tutorial/Step6RegionGrowing1.cpp index 74e950085c..04104e5ac6 100644 --- a/Applications/Tutorial/Step6RegionGrowing1.cpp +++ b/Applications/Tutorial/Step6RegionGrowing1.cpp @@ -1,31 +1,33 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "Step6RegionGrowing.txx" +#include + #define InstantiateAccessFunction_RegionGrowing(pixelType, dim) \ template void RegionGrowing(itk::Image*, Step6*); /// Instantiate the access function for 2D and all datatypes. /// Instantiation for 3D is done in Step6RegionGrowing2. /// Some compilers have memory problems without the explicit /// instantiation, some even need the separation in 2D/3D. InstantiateAccessFunctionForFixedDimension(RegionGrowing, 2) /** \example Step6RegionGrowing1.cpp */ diff --git a/Applications/Tutorial/Step6RegionGrowing2.cpp b/Applications/Tutorial/Step6RegionGrowing2.cpp index 1ebb509b9f..5a2333b575 100644 --- a/Applications/Tutorial/Step6RegionGrowing2.cpp +++ b/Applications/Tutorial/Step6RegionGrowing2.cpp @@ -1,31 +1,33 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "Step6RegionGrowing.txx" +#include + #define InstantiateAccessFunction_RegionGrowing(pixelType, dim) \ template void RegionGrowing(itk::Image*, Step6*); /// Instantiate the access function for 3D and all datatypes. /// Instantiation for 2D is done in Step6RegionGrowing1. /// Some compilers have memory problems without the explicit /// instantiation, some even need the separation in 2D/3D. InstantiateAccessFunctionForFixedDimension(RegionGrowing, 3) /** \example Step6RegionGrowing2.cpp */ diff --git a/Applications/Tutorial/mitkWithITKAndVTK.cpp b/Applications/Tutorial/mitkWithITKAndVTK.cpp index a60ecefcd2..90767280d6 100644 --- a/Applications/Tutorial/mitkWithITKAndVTK.cpp +++ b/Applications/Tutorial/mitkWithITKAndVTK.cpp @@ -1,66 +1,67 @@ #include #include #include #include #include +#include #include #include #include /// /// Small application for demonstrating the interaction between MITK, /// ITK and VTK (not necessarily useful). /// int main( int /*argc*/, char ** argv ) { // MITK: Read a .pic.gz file, e.g. Core/Code/Testing/Data/Pic3D.pic.gz from // disk mitk::PicFileReader::Pointer reader = mitk::PicFileReader::New(); const char * filename = argv[1]; try { reader->SetFileName(filename); reader->Update(); } catch(...) { fprintf( stderr, "Could not open file %s \n\n", filename ); return EXIT_FAILURE; } mitk::Image::Pointer mitkImage = reader->GetOutput(); // ITK: Image smoothing // Create ITK image, cast from MITK image typedef itk::Image< short , 3 > ImageType; ImageType::Pointer itkImage = ImageType::New(); mitk::CastToItkImage( mitkImage, itkImage ); typedef itk::DiscreteGaussianImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkImage ); filter->SetVariance( 2 ); filter->SetMaximumKernelWidth( 5 ); filter->Update(); // run filter // reimport filtered image data mitk::CastToMitkImage( filter->GetOutput(), mitkImage ); // VTK: Show result in renderwindow vtkImageViewer *viewer=vtkImageViewer::New(); vtkRenderWindowInteractor* renderWindowInteractor =vtkRenderWindowInteractor ::New(); viewer->SetupInteractor(renderWindowInteractor); viewer->SetInput(mitkImage->GetVtkImageData()); viewer->Render(); viewer->SetColorWindow(255); viewer->SetColorLevel(128); renderWindowInteractor->Start(); renderWindowInteractor->Delete(); viewer->Delete(); return EXIT_SUCCESS; } diff --git a/Modules/DeformableRegistration/mitkBSplineRegistration.cpp b/Modules/DeformableRegistration/mitkBSplineRegistration.cpp index 5b3761e1cd..7fef213719 100644 --- a/Modules/DeformableRegistration/mitkBSplineRegistration.cpp +++ b/Modules/DeformableRegistration/mitkBSplineRegistration.cpp @@ -1,369 +1,371 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-05 19:02:32 +0200 (Tue, 05 May 2009) $ Version: $Revision: 17105 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ +#include + #include "itkImageFileWriter.h" #include "itkWarpImageFilter.h" #include "itkImageRegionIterator.h" #include "mitkBSplineRegistration.h" #include "itkBSplineDeformableTransform.h" //#include "itkLBFGSOptimizer.h" #include "itkMeanSquaresImageToImageMetric.h" #include "itkMattesMutualInformationImageToImageMetric.h" #include "itkResampleImageFilter.h" #include "itkImageRegistrationMethod.h" #include "itkBSplineDeformableTransformInitializer.h" #include "mitkOptimizerFactory.h" #include "mitkMetricFactory.h" #include #include namespace mitk { BSplineRegistration::BSplineRegistration(): m_Iterations(50), m_ResultName("deformedImage.mhd"), m_SaveResult(true), m_SaveDeformationField(false), m_UpdateInputImage(false), m_MatchHistograms(true), m_Metric(0) { m_Observer = mitk::RigidRegistrationObserver::New(); } BSplineRegistration::~BSplineRegistration() { } void BSplineRegistration::SetNumberOfIterations(int iterations) { m_Iterations = iterations; } void BSplineRegistration::SetSaveResult(bool saveResult) { m_SaveResult = saveResult; } void BSplineRegistration::SetResultFileName(const char* resultName) { m_ResultName = resultName; } template < typename TPixel, unsigned int VImageDimension > void BSplineRegistration::GenerateData2( itk::Image* itkImage1) { std::cout << "start bspline registration" << std::endl; // Typedefs typedef typename itk::Image< TPixel, VImageDimension > InternalImageType; typedef typename itk::Vector< float, VImageDimension > VectorPixelType; typedef typename itk::Image< VectorPixelType, VImageDimension > DeformationFieldType; typedef itk::BSplineDeformableTransform< double, VImageDimension, 3 > TransformType; typedef typename TransformType::ParametersType ParametersType; //typedef itk::LBFGSOptimizer OptimizerType; typedef itk::SingleValuedNonLinearOptimizer OptimizerType; //typedef itk::SingleValuedCostFunction MetricType; typedef itk::MattesMutualInformationImageToImageMetric< InternalImageType, InternalImageType > MetricType; typedef itk::MeanSquaresImageToImageMetric< InternalImageType, InternalImageType > MetricTypeMS; typedef itk::LinearInterpolateImageFunction< InternalImageType, double > InterpolatorType; typedef itk::ImageRegistrationMethod< InternalImageType, InternalImageType > RegistrationType; typedef typename itk::WarpImageFilter< InternalImageType, InternalImageType, DeformationFieldType > WarperType; typedef typename TransformType::SpacingType SpacingType; typedef typename TransformType::OriginType OriginType; typedef itk::ResampleImageFilter< InternalImageType, InternalImageType > ResampleFilterType; typedef itk::Image< TPixel, VImageDimension > OutputImageType; // Sample new image with the same image type as the fixed image typedef itk::CastImageFilter< InternalImageType, InternalImageType > CastFilterType; typedef itk::Vector< float, VImageDimension > VectorType; typedef itk::Image< VectorType, VImageDimension > DeformationFieldType; typedef itk::BSplineDeformableTransformInitializer < TransformType, InternalImageType > InitializerType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); typename RegistrationType::Pointer registration = RegistrationType::New(); typename InitializerType::Pointer initializer = InitializerType::New(); typename TransformType::Pointer transform = TransformType::New(); if(m_Metric==0 || m_Metric==1) { typename MetricType::Pointer metric = MetricType::New(); metric->SetNumberOfHistogramBins( 32); metric->SetNumberOfSpatialSamples(90000); registration->SetMetric( metric ); } else{ typename MetricTypeMS::Pointer metric = MetricTypeMS::New(); registration->SetMetric( metric ); } typename OptimizerFactory::Pointer optFac = OptimizerFactory::New(); optFac->SetOptimizerParameters(m_OptimizerParameters); optFac->SetNumberOfTransformParameters(transform->GetNumberOfParameters()); OptimizerType::Pointer optimizer = optFac->GetOptimizer(); optimizer->AddObserver(itk::AnyEvent(), m_Observer); //typedef mitk::MetricFactory MetricFactoryType; //typename MetricFactoryType::Pointer metricFac = MetricFactoryType::New(); //metricFac->SetMetricParameters(m_MetricParameters); ////MetricType::Pointer metric = metricFac->GetMetric(); typename InternalImageType::Pointer fixedImage = InternalImageType::New(); mitk::CastToItkImage(m_ReferenceImage, fixedImage); typename InternalImageType::Pointer movingImage = itkImage1; typename InternalImageType::RegionType fixedRegion = fixedImage->GetBufferedRegion(); typename InternalImageType::RegionType movingRegion = movingImage->GetBufferedRegion(); if(m_MatchHistograms) { typedef itk::RescaleIntensityImageFilter FilterType; typedef itk::HistogramMatchingImageFilter HEFilterType; typename FilterType::Pointer inputRescaleFilter = FilterType::New(); typename FilterType::Pointer referenceRescaleFilter = FilterType::New(); referenceRescaleFilter->SetInput(fixedImage); inputRescaleFilter->SetInput(movingImage); TPixel desiredMinimum = 0; TPixel desiredMaximum = 255; referenceRescaleFilter->SetOutputMinimum( desiredMinimum ); referenceRescaleFilter->SetOutputMaximum( desiredMaximum ); referenceRescaleFilter->UpdateLargestPossibleRegion(); inputRescaleFilter->SetOutputMinimum( desiredMinimum ); inputRescaleFilter->SetOutputMaximum( desiredMaximum ); inputRescaleFilter->UpdateLargestPossibleRegion(); // Histogram match the images typename HEFilterType::Pointer intensityEqualizeFilter = HEFilterType::New(); intensityEqualizeFilter->SetReferenceImage( inputRescaleFilter->GetOutput() ); intensityEqualizeFilter->SetInput( referenceRescaleFilter->GetOutput() ); intensityEqualizeFilter->SetNumberOfHistogramLevels( 64 ); intensityEqualizeFilter->SetNumberOfMatchPoints( 12 ); intensityEqualizeFilter->ThresholdAtMeanIntensityOn(); intensityEqualizeFilter->Update(); //fixedImage = referenceRescaleFilter->GetOutput(); //movingImage = IntensityEqualizeFilter->GetOutput(); fixedImage = intensityEqualizeFilter->GetOutput(); movingImage = inputRescaleFilter->GetOutput(); } // registration->SetOptimizer( optimizer ); registration->SetInterpolator( interpolator ); registration->SetFixedImage( fixedImage ); registration->SetMovingImage( movingImage ); registration->SetFixedImageRegion(fixedRegion ); initializer->SetTransform(transform); initializer->SetImage(fixedImage); initializer->SetNumberOfGridNodesInsideTheImage( m_NumberOfGridPoints ); initializer->InitializeTransform(); registration->SetTransform( transform ); const unsigned int numberOfParameters = transform->GetNumberOfParameters(); typename itk::BSplineDeformableTransform< double, VImageDimension, 3 >::ParametersType parameters; parameters.set_size(numberOfParameters); parameters.Fill( 0.0 ); transform->SetParameters( parameters ); // We now pass the parameters of the current transform as the initial // parameters to be used when the registration process starts. registration->SetInitialTransformParameters( transform->GetParameters() ); std::cout << "Intial Parameters = " << std::endl; std::cout << transform->GetParameters() << std::endl; std::cout << std::endl << "Starting Registration" << std::endl; try { double tstart(clock()); registration->StartRegistration(); double time = clock() - tstart; time = time / CLOCKS_PER_SEC; MITK_INFO << "Registration time: " << time; } catch( itk::ExceptionObject & err ) { std::cerr << "ExceptionObject caught !" << std::endl; std::cerr << err << std::endl; } typename OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters(); std::cout << "Last Transform Parameters" << std::endl; std::cout << finalParameters << std::endl; transform->SetParameters( finalParameters ); /* ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetTransform( transform ); resampler->SetInput( movingImage ); resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() ); resampler->SetOutputOrigin( fixedImage->GetOrigin() ); resampler->SetOutputSpacing( fixedImage->GetSpacing() ); resampler->SetOutputDirection( fixedImage->GetDirection() ); resampler->SetDefaultPixelValue( 100 ); resampler->SetInterpolator( interpolator); resampler->Update();*/ // Generate deformation field typename DeformationFieldType::Pointer field = DeformationFieldType::New(); field->SetRegions( movingRegion ); field->SetOrigin( movingImage->GetOrigin() ); field->SetSpacing( movingImage->GetSpacing() ); field->SetDirection( movingImage->GetDirection() ); field->Allocate(); typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator; FieldIterator fi( field, movingRegion ); fi.GoToBegin(); typename TransformType::InputPointType fixedPoint; typename TransformType::OutputPointType movingPoint; typename DeformationFieldType::IndexType index; VectorType displacement; while( ! fi.IsAtEnd() ) { index = fi.GetIndex(); field->TransformIndexToPhysicalPoint( index, fixedPoint ); movingPoint = transform->TransformPoint( fixedPoint ); displacement = movingPoint - fixedPoint; fi.Set( displacement ); ++fi; } // Use the deformation field to warp the moving image typename WarperType::Pointer warper = WarperType::New(); warper->SetInput( movingImage ); warper->SetInterpolator( interpolator ); warper->SetOutputSpacing( movingImage->GetSpacing() ); warper->SetOutputOrigin( movingImage->GetOrigin() ); warper->SetOutputDirection( movingImage->GetDirection() ); warper->SetDeformationField( field ); warper->Update(); typename InternalImageType::Pointer result = warper->GetOutput(); if(m_UpdateInputImage) { Image::Pointer outputImage = this->GetOutput(); mitk::CastToMitkImage( result, outputImage ); } // Save the deformationfield resulting from the registration if(m_SaveDeformationField) { typedef itk::ImageFileWriter< DeformationFieldType > FieldWriterType; typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New(); fieldWriter->SetInput( field ); fieldWriter->SetFileName( m_DeformationFileName ); try { fieldWriter->Update(); } catch( itk::ExceptionObject & excp ) { std::cerr << "Exception thrown " << std::endl; std::cerr << excp << std::endl; //return EXIT_FAILURE; } } } } // end namespace diff --git a/Modules/DeformableRegistration/mitkDemonsRegistration.cpp b/Modules/DeformableRegistration/mitkDemonsRegistration.cpp index fbee3cbcea..0ac8e1312f 100644 --- a/Modules/DeformableRegistration/mitkDemonsRegistration.cpp +++ b/Modules/DeformableRegistration/mitkDemonsRegistration.cpp @@ -1,265 +1,267 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ +#include + #include "itkImageFileWriter.h" #include "itkWarpImageFilter.h" #include "itkImageRegionIterator.h" #include "mitkDemonsRegistration.h" namespace mitk { DemonsRegistration::DemonsRegistration(): m_Iterations(50), m_StandardDeviation(1.0), m_FieldName("newField.mhd"), m_ResultName("deformedImage.mhd"), m_SaveField(true), m_SaveResult(true), m_DeformationField(NULL) { } DemonsRegistration::~DemonsRegistration() { } void DemonsRegistration::SetNumberOfIterations(int iterations) { m_Iterations = iterations; } void DemonsRegistration::SetStandardDeviation(float deviation) { m_StandardDeviation = deviation; } void DemonsRegistration::SetSaveDeformationField(bool saveField) { m_SaveField = saveField; } void DemonsRegistration::SetDeformationFieldFileName(const char* fieldName) { m_FieldName = fieldName; } void DemonsRegistration::SetSaveResult(bool saveResult) { m_SaveResult = saveResult; } void DemonsRegistration::SetResultFileName(const char* resultName) { m_ResultName = resultName; } itk::Image,3>::Pointer DemonsRegistration::GetDeformationField() { return m_DeformationField; } template < typename TPixel, unsigned int VImageDimension > void DemonsRegistration::GenerateData2( itk::Image* itkImage1) { typedef typename itk::Image< TPixel, VImageDimension > FixedImageType; typedef typename itk::Image< TPixel, VImageDimension > MovingImageType; typedef float InternalPixelType; typedef typename itk::Image< InternalPixelType, VImageDimension > InternalImageType; typedef typename itk::CastImageFilter< FixedImageType, InternalImageType > FixedImageCasterType; typedef typename itk::CastImageFilter< MovingImageType, InternalImageType > MovingImageCasterType; typedef typename itk::Image< InternalPixelType, VImageDimension > InternalImageType; typedef typename itk::Vector< float, VImageDimension > VectorPixelType; typedef typename itk::Image< VectorPixelType, VImageDimension > DeformationFieldType; typedef typename itk::DemonsRegistrationFilter< InternalImageType, InternalImageType, DeformationFieldType> RegistrationFilterType; typedef typename itk::WarpImageFilter< MovingImageType, MovingImageType, DeformationFieldType > WarperType; typedef typename itk::LinearInterpolateImageFunction< MovingImageType, double > InterpolatorType; typedef TPixel OutputPixelType; typedef typename itk::Image< OutputPixelType, VImageDimension > OutputImageType; typedef typename itk::CastImageFilter< MovingImageType, OutputImageType > CastFilterType; typedef typename itk::ImageFileWriter< OutputImageType > WriterType; typedef typename itk::ImageFileWriter< DeformationFieldType > FieldWriterType; typename FixedImageType::Pointer fixedImage = FixedImageType::New(); mitk::CastToItkImage(m_ReferenceImage, fixedImage); typename MovingImageType::Pointer movingImage = itkImage1; if (fixedImage.IsNotNull() && movingImage.IsNotNull()) { typename RegistrationFilterType::Pointer filter = RegistrationFilterType::New(); this->AddStepsToDo(4); typename itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &DemonsRegistration::SetProgress); filter->AddObserver( itk::IterationEvent(), command ); typename FixedImageCasterType::Pointer fixedImageCaster = FixedImageCasterType::New(); fixedImageCaster->SetInput(fixedImage); filter->SetFixedImage( fixedImageCaster->GetOutput() ); typename MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New(); movingImageCaster->SetInput(movingImage); filter->SetMovingImage(movingImageCaster->GetOutput()); filter->SetNumberOfIterations( m_Iterations ); filter->SetStandardDeviations( m_StandardDeviation ); filter->Update(); typename WarperType::Pointer warper = WarperType::New(); typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); warper->SetInput( movingImage ); warper->SetInterpolator( interpolator ); warper->SetOutputSpacing( fixedImage->GetSpacing() ); warper->SetOutputOrigin( fixedImage->GetOrigin() ); warper->SetOutputDirection( fixedImage->GetDirection()); warper->SetDeformationField( filter->GetOutput() ); warper->Update(); Image::Pointer outputImage = this->GetOutput(); mitk::CastToMitkImage( warper->GetOutput(), outputImage ); typename WriterType::Pointer writer = WriterType::New(); typename CastFilterType::Pointer caster = CastFilterType::New(); writer->SetFileName( m_ResultName ); caster->SetInput( warper->GetOutput() ); writer->SetInput( caster->GetOutput() ); if(m_SaveResult) { writer->Update(); } if (VImageDimension == 2) { typedef DeformationFieldType VectorImage2DType; typedef typename DeformationFieldType::PixelType Vector2DType; typename VectorImage2DType::ConstPointer vectorImage2D = filter->GetOutput(); typename VectorImage2DType::RegionType region2D = vectorImage2D->GetBufferedRegion(); typename VectorImage2DType::IndexType index2D = region2D.GetIndex(); typename VectorImage2DType::SizeType size2D = region2D.GetSize(); typedef typename itk::Vector< float, 3 > Vector3DType; typedef typename itk::Image< Vector3DType, 3 > VectorImage3DType; typedef typename itk::ImageFileWriter< VectorImage3DType > WriterType; typename WriterType::Pointer writer3D = WriterType::New(); typename VectorImage3DType::Pointer vectorImage3D = VectorImage3DType::New(); typename VectorImage3DType::RegionType region3D; typename VectorImage3DType::IndexType index3D; typename VectorImage3DType::SizeType size3D; index3D[0] = index2D[0]; index3D[1] = index2D[1]; index3D[2] = 0; size3D[0] = size2D[0]; size3D[1] = size2D[1]; size3D[2] = 1; region3D.SetSize( size3D ); region3D.SetIndex( index3D ); typename VectorImage2DType::SpacingType spacing2D = vectorImage2D->GetSpacing(); typename VectorImage3DType::SpacingType spacing3D; spacing3D[0] = spacing2D[0]; spacing3D[1] = spacing2D[1]; spacing3D[2] = 1.0; vectorImage3D->SetSpacing( spacing3D ); vectorImage3D->SetRegions( region3D ); vectorImage3D->Allocate(); typedef typename itk::ImageRegionConstIterator< VectorImage2DType > Iterator2DType; typedef typename itk::ImageRegionIterator< VectorImage3DType > Iterator3DType; Iterator2DType it2( vectorImage2D, region2D ); Iterator3DType it3( vectorImage3D, region3D ); it2.GoToBegin(); it3.GoToBegin(); Vector2DType vector2D; Vector3DType vector3D; vector3D[2] = 0; // set Z component to zero. while( !it2.IsAtEnd() ) { vector2D = it2.Get(); vector3D[0] = vector2D[0]; vector3D[1] = vector2D[1]; it3.Set( vector3D ); ++it2; ++it3; } writer3D->SetInput( vectorImage3D ); m_DeformationField = vectorImage3D; writer3D->SetFileName( m_FieldName ); try { if(m_SaveField) { writer3D->Update(); } } catch( itk::ExceptionObject & excp ) { MITK_ERROR << excp << std::endl; } } else { typename FieldWriterType::Pointer fieldwriter = FieldWriterType::New(); fieldwriter->SetFileName(m_FieldName); fieldwriter->SetInput( filter->GetOutput() ); m_DeformationField = (itk::Image,3> *)(filter->GetOutput()); if(m_SaveField) { fieldwriter->Update(); } } this->SetRemainingProgress(4); } } } // end namespace diff --git a/Modules/DeformableRegistration/mitkHistogramMatching.cpp b/Modules/DeformableRegistration/mitkHistogramMatching.cpp index 81f976981c..81ab99d1b0 100644 --- a/Modules/DeformableRegistration/mitkHistogramMatching.cpp +++ b/Modules/DeformableRegistration/mitkHistogramMatching.cpp @@ -1,84 +1,86 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkHistogramMatching.h" +#include + namespace mitk { HistogramMatching::HistogramMatching() { m_ThresholdAtMeanIntensity = true; m_NumberOfHistogramLevels = 1024; m_NumberOfMatchPoints = 7; } HistogramMatching::~HistogramMatching() { } void HistogramMatching::SetNumberOfHistogramLevels(int histogrammLevels) { m_NumberOfHistogramLevels = histogrammLevels; } void HistogramMatching::SetNumberOfMatchPoints(int matchPoints) { m_NumberOfMatchPoints = matchPoints; } void HistogramMatching::SetThresholdAtMeanIntensity(bool on) { m_ThresholdAtMeanIntensity = on; } template < typename TPixel, unsigned int VImageDimension > void HistogramMatching::GenerateData2( itk::Image* itkImage1) { typedef typename itk::Image< TPixel, VImageDimension > FixedImageType; typedef typename itk::Image< TPixel, VImageDimension > MovingImageType; typedef float InternalPixelType; typedef typename itk::Image< InternalPixelType, VImageDimension > InternalImageType; typedef typename itk::CastImageFilter< FixedImageType, InternalImageType > FixedImageCasterType; typedef typename itk::CastImageFilter< MovingImageType, InternalImageType > MovingImageCasterType; typedef typename itk::HistogramMatchingImageFilter< InternalImageType, InternalImageType > MatchingFilterType; typename FixedImageType::Pointer fixedImage = FixedImageType::New(); mitk::CastToItkImage(m_ReferenceImage, fixedImage); typename MovingImageType::Pointer movingImage = itkImage1; if (fixedImage.IsNotNull() && movingImage.IsNotNull()) { typename FixedImageCasterType::Pointer fixedImageCaster = FixedImageCasterType::New(); fixedImageCaster->SetInput(fixedImage); typename MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New(); movingImageCaster->SetInput(movingImage); typename MatchingFilterType::Pointer matcher = MatchingFilterType::New(); matcher->SetInput( movingImageCaster->GetOutput() ); matcher->SetReferenceImage( fixedImageCaster->GetOutput() ); matcher->SetNumberOfHistogramLevels( m_NumberOfHistogramLevels ); matcher->SetNumberOfMatchPoints( m_NumberOfMatchPoints ); matcher->SetThresholdAtMeanIntensity(m_ThresholdAtMeanIntensity); matcher->Update(); Image::Pointer outputImage = this->GetOutput(); mitk::CastToMitkImage( matcher->GetOutput(), outputImage ); } } } // end namespace diff --git a/Modules/DeformableRegistration/mitkSymmetricForcesDemonsRegistration.cpp b/Modules/DeformableRegistration/mitkSymmetricForcesDemonsRegistration.cpp index 017134af20..e1a4f01523 100644 --- a/Modules/DeformableRegistration/mitkSymmetricForcesDemonsRegistration.cpp +++ b/Modules/DeformableRegistration/mitkSymmetricForcesDemonsRegistration.cpp @@ -1,265 +1,267 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ +#include + #include "itkImageFileWriter.h" #include "itkWarpImageFilter.h" #include "itkInverseDeformationFieldImageFilter.h" #include "mitkSymmetricForcesDemonsRegistration.h" namespace mitk { SymmetricForcesDemonsRegistration::SymmetricForcesDemonsRegistration(): m_Iterations(50), m_StandardDeviation(1.0), m_FieldName("newField.mhd"), m_ResultName("deformedImage.mhd"), m_SaveField(true), m_SaveResult(true), m_DeformationField(NULL) { } SymmetricForcesDemonsRegistration::~SymmetricForcesDemonsRegistration() { } void SymmetricForcesDemonsRegistration::SetNumberOfIterations(int iterations) { m_Iterations = iterations; } void SymmetricForcesDemonsRegistration::SetStandardDeviation(float deviation) { m_StandardDeviation = deviation; } void SymmetricForcesDemonsRegistration::SetSaveDeformationField(bool saveField) { m_SaveField = saveField; } void SymmetricForcesDemonsRegistration::SetDeformationFieldFileName(const char* fieldName) { m_FieldName = fieldName; } void SymmetricForcesDemonsRegistration::SetSaveResult(bool saveResult) { m_SaveResult = saveResult; } void SymmetricForcesDemonsRegistration::SetResultFileName(const char* resultName) { m_ResultName = resultName; } itk::Image,3>::Pointer SymmetricForcesDemonsRegistration::GetDeformationField() { return m_DeformationField; } template < typename TPixel, unsigned int VImageDimension > void SymmetricForcesDemonsRegistration::GenerateData2( itk::Image* itkImage1) { typedef typename itk::Image< TPixel, VImageDimension > FixedImageType; typedef typename itk::Image< TPixel, VImageDimension > MovingImageType; typedef float InternalPixelType; typedef typename itk::Image< InternalPixelType, VImageDimension > InternalImageType; typedef typename itk::CastImageFilter< FixedImageType, InternalImageType > FixedImageCasterType; typedef typename itk::CastImageFilter< MovingImageType, InternalImageType > MovingImageCasterType; typedef typename itk::Vector< float, VImageDimension > VectorPixelType; typedef typename itk::Image< VectorPixelType, VImageDimension > DeformationFieldType; typedef typename itk::SymmetricForcesDemonsRegistrationFilter< InternalImageType, InternalImageType, DeformationFieldType> RegistrationFilterType; typedef typename itk::WarpImageFilter< MovingImageType, MovingImageType, DeformationFieldType > WarperType; typedef typename itk::LinearInterpolateImageFunction< MovingImageType, double > InterpolatorType; typedef TPixel OutputPixelType; typedef typename itk::Image< OutputPixelType, VImageDimension > OutputImageType; typedef typename itk::CastImageFilter< MovingImageType, OutputImageType > CastFilterType; typedef typename itk::ImageFileWriter< OutputImageType > WriterType; typedef typename itk::ImageFileWriter< DeformationFieldType > FieldWriterType; typedef typename itk::InverseDeformationFieldImageFilter InverseFilterType; typename FixedImageType::Pointer fixedImage = FixedImageType::New(); mitk::CastToItkImage(m_ReferenceImage, fixedImage); typename MovingImageType::Pointer movingImage = itkImage1; if (fixedImage.IsNotNull() && movingImage.IsNotNull()) { typename RegistrationFilterType::Pointer filter = RegistrationFilterType::New(); this->AddStepsToDo(4); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &SymmetricForcesDemonsRegistration::SetProgress); filter->AddObserver( itk::IterationEvent(), command ); typename FixedImageCasterType::Pointer fixedImageCaster = FixedImageCasterType::New(); fixedImageCaster->SetInput(fixedImage); filter->SetFixedImage( fixedImageCaster->GetOutput() ); typename MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New(); movingImageCaster->SetInput(movingImage); filter->SetMovingImage(movingImageCaster->GetOutput()); filter->SetNumberOfIterations( m_Iterations ); filter->SetStandardDeviations( m_StandardDeviation ); filter->Update(); typename WarperType::Pointer warper = WarperType::New(); typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); warper->SetInput( movingImage ); warper->SetInterpolator( interpolator ); warper->SetOutputSpacing( fixedImage->GetSpacing() ); warper->SetOutputOrigin( fixedImage->GetOrigin() ); warper->SetDeformationField( filter->GetOutput() ); warper->Update(); typename WriterType::Pointer writer = WriterType::New(); typename CastFilterType::Pointer caster = CastFilterType::New(); writer->SetFileName( m_ResultName ); caster->SetInput( warper->GetOutput() ); writer->SetInput( caster->GetOutput() ); if(m_SaveResult) { writer->Update(); } Image::Pointer outputImage = this->GetOutput(); mitk::CastToMitkImage( warper->GetOutput(), outputImage ); if (VImageDimension == 2) { typedef DeformationFieldType VectorImage2DType; typedef typename DeformationFieldType::PixelType Vector2DType; typename VectorImage2DType::ConstPointer vectorImage2D = filter->GetOutput(); typename VectorImage2DType::RegionType region2D = vectorImage2D->GetBufferedRegion(); typename VectorImage2DType::IndexType index2D = region2D.GetIndex(); typename VectorImage2DType::SizeType size2D = region2D.GetSize(); typedef typename itk::Vector< float, 3 > Vector3DType; typedef typename itk::Image< Vector3DType, 3 > VectorImage3DType; typedef typename itk::ImageFileWriter< VectorImage3DType > WriterType; WriterType::Pointer writer3D = WriterType::New(); VectorImage3DType::Pointer vectorImage3D = VectorImage3DType::New(); VectorImage3DType::RegionType region3D; VectorImage3DType::IndexType index3D; VectorImage3DType::SizeType size3D; index3D[0] = index2D[0]; index3D[1] = index2D[1]; index3D[2] = 0; size3D[0] = size2D[0]; size3D[1] = size2D[1]; size3D[2] = 1; region3D.SetSize( size3D ); region3D.SetIndex( index3D ); typename VectorImage2DType::SpacingType spacing2D = vectorImage2D->GetSpacing(); VectorImage3DType::SpacingType spacing3D; spacing3D[0] = spacing2D[0]; spacing3D[1] = spacing2D[1]; spacing3D[2] = 1.0; vectorImage3D->SetSpacing( spacing3D ); vectorImage3D->SetRegions( region3D ); vectorImage3D->Allocate(); typedef typename itk::ImageRegionConstIterator< VectorImage2DType > Iterator2DType; typedef typename itk::ImageRegionIterator< VectorImage3DType > Iterator3DType; Iterator2DType it2( vectorImage2D, region2D ); Iterator3DType it3( vectorImage3D, region3D ); it2.GoToBegin(); it3.GoToBegin(); Vector2DType vector2D; Vector3DType vector3D; vector3D[2] = 0; // set Z component to zero. while( !it2.IsAtEnd() ) { vector2D = it2.Get(); vector3D[0] = vector2D[0]; vector3D[1] = vector2D[1]; it3.Set( vector3D ); ++it2; ++it3; } writer3D->SetInput( vectorImage3D ); m_DeformationField = vectorImage3D; writer3D->SetFileName( m_FieldName ); try { if(m_SaveField) { writer3D->Update(); } } catch( itk::ExceptionObject & excp ) { MITK_ERROR << excp << std::endl; } } else { typename FieldWriterType::Pointer fieldwriter = FieldWriterType::New(); fieldwriter->SetFileName( m_FieldName ); fieldwriter->SetInput( filter->GetOutput() ); //m_DeformationField = filter->GetOutput(); m_DeformationField = (itk::Image,3> *)(filter->GetOutput()); //see BUG #3732 if(m_SaveField) { fieldwriter->Update(); } } this->SetRemainingProgress(4); } } } // end namespace diff --git a/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp b/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp index 60d96532e3..ae034449f0 100644 --- a/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp +++ b/Modules/DiffusionImaging/IODataStructures/TensorImages/mitkNrrdTensorImageWriter.cpp @@ -1,106 +1,107 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2008-12-10 18:05:13 +0100 (Mi, 10 Dez 2008) $ Version: $Revision: 15922 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkNrrdTensorImageWriter.h" #include "itkMetaDataDictionary.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" #include "itkImageFileWriter.h" +#include "itkDiffusionTensor3D.h" #include "mitkImageCast.h" mitk::NrrdTensorImageWriter::NrrdTensorImageWriter() : m_FileName(""), m_FilePrefix(""), m_FilePattern(""), m_Success(false) { this->SetNumberOfRequiredInputs( 1 ); } mitk::NrrdTensorImageWriter::~NrrdTensorImageWriter() {} void mitk::NrrdTensorImageWriter::GenerateData() { m_Success = false; InputType* input = this->GetInput(); if (input == NULL) { itkWarningMacro(<<"Sorry, input to NrrdTensorImageWriter is NULL!"); return; } if ( m_FileName == "" ) { itkWarningMacro( << "Sorry, filename has not been set!" ); return ; } itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); typedef itk::Image,3> ImageType; typedef itk::ImageFileWriter WriterType; WriterType::Pointer nrrdWriter = WriterType::New(); ImageType::Pointer outimage = ImageType::New(); CastToItkImage(input, outimage); nrrdWriter->SetInput( outimage ); nrrdWriter->SetImageIO(io); nrrdWriter->SetFileName(m_FileName); nrrdWriter->UseCompressionOn(); try { nrrdWriter->Update(); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; } m_Success = true; } void mitk::NrrdTensorImageWriter::SetInput( InputType* diffVolumes ) { this->ProcessObject::SetNthInput( 0, diffVolumes ); } mitk::TensorImage* mitk::NrrdTensorImageWriter::GetInput() { if ( this->GetNumberOfInputs() < 1 ) { return NULL; } else { return dynamic_cast ( this->ProcessObject::GetInput( 0 ) ); } } std::vector mitk::NrrdTensorImageWriter::GetPossibleFileExtensions() { std::vector possibleFileExtensions; possibleFileExtensions.push_back(".dti"); possibleFileExtensions.push_back(".hdti"); return possibleFileExtensions; } diff --git a/Modules/ImageExtraction/Testing/mitkCompareImageSliceTestHelper.h b/Modules/ImageExtraction/Testing/mitkCompareImageSliceTestHelper.h index 4762e50a45..718300586d 100644 --- a/Modules/ImageExtraction/Testing/mitkCompareImageSliceTestHelper.h +++ b/Modules/ImageExtraction/Testing/mitkCompareImageSliceTestHelper.h @@ -1,161 +1,163 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef mitkCompareImageSliceTestHelperhincluded #define mitkCompareImageSliceTestHelperhincluded #include "mitkImageCast.h" +#include #include #include // copied from mitk/Core/Algorithms/mitkOverwriteSliceImageFilter.cpp // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h #define myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \ if ( typeId == typeid(pixeltype) ) \ { \ typedef itk::Image ImageType; \ typedef mitk::ImageToItk ImageToItkType; \ itk::SmartPointer imagetoitk = ImageToItkType::New(); \ imagetoitk->SetInput(mitkImage); \ imagetoitk->Update(); \ itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \ } #define myMITKOverwriteSliceImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \ { \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \ } class CompareImageSliceTestHelper { private: /* variables to be used by CompareSlice only */ static unsigned int m_Dimension0; static unsigned int m_Dimension1; static unsigned int m_SliceDimension; static unsigned int m_SliceIndex; static bool m_ComparisonResult; static mitk::Image* m_SliceImage; public: template static void ItkImageCompare( itk::Image* inputImage, itk::Image* outputImage ) { m_ComparisonResult = false; typedef itk::Image SliceImageType; typedef itk::Image VolumeImageType; typedef itk::ImageSliceConstIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< SliceImageType > InputSliceIteratorType; typename VolumeImageType::RegionType sliceInVolumeRegion; sliceInVolumeRegion = outputImage->GetLargestPossibleRegion(); sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion ); outputIterator.SetFirstDirection(m_Dimension0); outputIterator.SetSecondDirection(m_Dimension1); InputSliceIteratorType inputIterator( inputImage, inputImage->GetLargestPossibleRegion() ); // iterate over output slice (and over input slice simultaneously) outputIterator.GoToBegin(); inputIterator.GoToBegin(); while ( !outputIterator.IsAtEnd() ) { while ( !outputIterator.IsAtEndOfSlice() ) { while ( !outputIterator.IsAtEndOfLine() ) { m_ComparisonResult = outputIterator.Get() == (TPixel2) inputIterator.Get(); if (!m_ComparisonResult) return; // return on first mismatch ++outputIterator; ++inputIterator; } outputIterator.NextLine(); } outputIterator.NextSlice(); } } template static void ItkImageSwitch( itk::Image* itkImage ) { const std::type_info& typeId=*(m_SliceImage->GetPixelType().GetTypeId()); - myMITKOverwriteSliceImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageCompare, 2, itkImage ); + AccessFixedDimensionByItk_n( m_SliceImage, ItkImageCompare, 2, itkImage ) + //myMITKOverwriteSliceImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageCompare, 2, itkImage ); } static bool CompareSlice( mitk::Image* image, unsigned int sliceDimension, unsigned int sliceIndex, mitk::Image* slice ) { if ( !image || ! slice ) return false; switch (sliceDimension) { default: case 2: m_Dimension0 = 0; m_Dimension1 = 1; break; case 1: m_Dimension0 = 0; m_Dimension1 = 2; break; case 0: m_Dimension0 = 1; m_Dimension1 = 2; break; } if ( slice->GetDimension() != 2 || image->GetDimension() != 3 || slice->GetDimension(0) != image->GetDimension(m_Dimension0) || slice->GetDimension(1) != image->GetDimension(m_Dimension1) ) { std::cerr << "Slice and image dimensions differ. Sorry, cannot work like this." << std::endl; return false; } // this will do a long long if/else to find out both pixel typesA m_SliceImage = slice; m_SliceIndex = sliceIndex; m_SliceDimension = sliceDimension; m_ComparisonResult = false; AccessFixedDimensionByItk( image, ItkImageSwitch, 3 ); return m_ComparisonResult; } }; // end class #endif diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp index bc71cc4e55..fa65f08e95 100644 --- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp +++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilterNew.cpp @@ -1,294 +1,296 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-12-02 14:54:03 +0100 (Do, 2 Dec 2010) $ Version: $Revision: 21147 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkExtractDirectedPlaneImageFilterNew.h" #include "mitkImageCast.h" #include "mitkImageTimeSelector.h" #include "itkImageRegionIterator.h" +#include + mitk::ExtractDirectedPlaneImageFilterNew::ExtractDirectedPlaneImageFilterNew() :m_CurrentWorldGeometry2D(NULL) { } mitk::ExtractDirectedPlaneImageFilterNew::~ExtractDirectedPlaneImageFilterNew() { } void mitk::ExtractDirectedPlaneImageFilterNew::GenerateData(){ mitk::Image::ConstPointer inputImage = ImageToImageFilter::GetInput(0); if ( !inputImage ) { MITK_ERROR << "mitk::ExtractDirectedPlaneImageFilterNew: No input available. Please set the input!" << std::endl; itkExceptionMacro("mitk::ExtractDirectedPlaneImageFilterNew: No input available. Please set the input!"); return; } m_ImageGeometry = inputImage->GetGeometry(); //If no timestep is set, the lowest given will be selected const mitk::TimeSlicedGeometry* inputTimeGeometry = this->GetInput()->GetTimeSlicedGeometry(); if ( !m_ActualInputTimestep ) { ScalarType time = m_CurrentWorldGeometry2D->GetTimeBounds()[0]; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) { m_ActualInputTimestep = inputTimeGeometry->MSToTimeStep( time ); } } if ( inputImage->GetDimension() > 4 || inputImage->GetDimension() < 2) { MITK_ERROR << "mitk::ExtractDirectedPlaneImageFilterNew:GenerateData works only with 3D and 3D+t images, sorry." << std::endl; itkExceptionMacro("mitk::ExtractDirectedPlaneImageFilterNew works only with 3D and 3D+t images, sorry."); return; } else if ( inputImage->GetDimension() == 4 ) { mitk::ImageTimeSelector::Pointer timeselector = mitk::ImageTimeSelector::New(); timeselector->SetInput( inputImage ); timeselector->SetTimeNr( m_ActualInputTimestep ); timeselector->UpdateLargestPossibleRegion(); inputImage = timeselector->GetOutput(); } else if ( inputImage->GetDimension() == 2) { mitk::Image::Pointer resultImage = ImageToImageFilter::GetOutput(); resultImage = const_cast( inputImage.GetPointer() ); ImageToImageFilter::SetNthOutput( 0, resultImage); return; } if ( !m_CurrentWorldGeometry2D ) { MITK_ERROR<< "mitk::ExtractDirectedPlaneImageFilterNew::GenerateData has no CurrentWorldGeometry2D set" << std::endl; return; } AccessFixedDimensionByItk( inputImage, ItkSliceExtraction, 3 ); }//Generate Data void mitk::ExtractDirectedPlaneImageFilterNew::GenerateOutputInformation () { Superclass::GenerateOutputInformation(); } /* * The desired slice is extracted by filling the image`s corresponding pixel values in an empty 2 dimensional itk::Image * Therefor the itk image`s extent in pixel (in each direction) is doubled and its spacing (also in each direction) is divided by two * (similar to the shannon theorem). */ template void mitk::ExtractDirectedPlaneImageFilterNew::ItkSliceExtraction (itk::Image* inputImage) { typedef itk::Image InputImageType; typedef itk::Image SliceImageType; typedef itk::ImageRegionConstIterator< SliceImageType > SliceIterator; //Creating an itk::Image that represents the sampled slice typename SliceImageType::Pointer resultSlice = SliceImageType::New(); typename SliceImageType::IndexType start; start[0] = 0; start[1] = 0; Point3D origin = m_CurrentWorldGeometry2D->GetOrigin(); Vector3D right = m_CurrentWorldGeometry2D->GetAxisVector(0); Vector3D bottom = m_CurrentWorldGeometry2D->GetAxisVector(1); //Calculation the sample-spacing, i.e the half of the smallest spacing existing in the original image Vector3D newPixelSpacing = m_ImageGeometry->GetSpacing(); float minSpacing = newPixelSpacing[0]; for (unsigned int i = 1; i < newPixelSpacing.Size(); i++) { if (newPixelSpacing[i] < minSpacing ) { minSpacing = newPixelSpacing[i]; } } newPixelSpacing[0] = 0.5*minSpacing; newPixelSpacing[1] = 0.5*minSpacing; newPixelSpacing[2] = 0.5*minSpacing; float pixelSpacing[2]; pixelSpacing[0] = newPixelSpacing[0]; pixelSpacing[1] = newPixelSpacing[1]; //Calculating the size of the sampled slice typename SliceImageType::SizeType size; Vector2D extentInMM; extentInMM[0] = m_CurrentWorldGeometry2D->GetExtentInMM(0); extentInMM[1] = m_CurrentWorldGeometry2D->GetExtentInMM(1); //The maximum extent is the lenght of the diagonal of the considered plane double maxExtent = sqrt(extentInMM[0]*extentInMM[0]+extentInMM[1]*extentInMM[1]); unsigned int xTranlation = (maxExtent-extentInMM[0]); unsigned int yTranlation = (maxExtent-extentInMM[1]); size[0] = (maxExtent+xTranlation)/newPixelSpacing[0]; size[1] = (maxExtent+yTranlation)/newPixelSpacing[1]; //Creating an ImageRegion Object typename SliceImageType::RegionType region; region.SetSize( size ); region.SetIndex( start ); //Defining the image`s extent and origin by passing the region to it and allocating memory for it resultSlice->SetRegions( region ); resultSlice->SetSpacing( pixelSpacing ); resultSlice->Allocate(); /* * Here we create an new geometry so that the transformations are calculated correctly (our resulting slice has a different bounding box and spacing) * The original current worldgeometry must be cloned because we have to keep the directions of the axis vector which represents the rotation */ right.Normalize(); bottom.Normalize(); //Here we translate the origin to adapt the new geometry to the previous calculated extent origin[0] -= xTranlation*right[0]+yTranlation*bottom[0]; origin[1] -= xTranlation*right[1]+yTranlation*bottom[1]; origin[2] -= xTranlation*right[2]+yTranlation*bottom[2]; //Putting it together for the new geometry mitk::Geometry3D::Pointer newSliceGeometryTest = dynamic_cast(m_CurrentWorldGeometry2D->Clone().GetPointer()); newSliceGeometryTest->ChangeImageGeometryConsideringOriginOffset(true); //Workaround because of BUG (#6505) newSliceGeometryTest->GetIndexToWorldTransform()->SetMatrix(m_CurrentWorldGeometry2D->GetIndexToWorldTransform()->GetMatrix()); //Workaround end newSliceGeometryTest->SetOrigin(origin); ScalarType bounds[6]={0, size[0], 0, size[1], 0, 1}; newSliceGeometryTest->SetBounds(bounds); newSliceGeometryTest->SetSpacing(newPixelSpacing); newSliceGeometryTest->Modified(); //Workaround because of BUG (#6505) itk::MatrixOffsetTransformBase::MatrixType tempTransform = newSliceGeometryTest->GetIndexToWorldTransform()->GetMatrix(); //Workaround end /* * Now we iterate over the recently created slice. * For each slice - pixel we check whether there is an according * pixel in the input - image which can be set in the slice. * In this way a slice is sampled out of the input - image regrading to the given PlaneGeometry */ Point3D currentSliceIndexPointIn2D; Point3D currentImageWorldPointIn3D; typename InputImageType::IndexType inputIndex; SliceIterator sliceIterator ( resultSlice, resultSlice->GetLargestPossibleRegion() ); sliceIterator.GoToBegin(); while ( !sliceIterator.IsAtEnd() ) { /* * Here we add 0.5 to to assure that the indices are correctly transformed. * (Because of the 0.5er Bug) */ currentSliceIndexPointIn2D[0] = sliceIterator.GetIndex()[0]+0.5; currentSliceIndexPointIn2D[1] = sliceIterator.GetIndex()[1]+0.5; currentSliceIndexPointIn2D[2] = 0; newSliceGeometryTest->IndexToWorld( currentSliceIndexPointIn2D, currentImageWorldPointIn3D ); m_ImageGeometry->WorldToIndex( currentImageWorldPointIn3D, inputIndex); if ( m_ImageGeometry->IsIndexInside( inputIndex )) { resultSlice->SetPixel( sliceIterator.GetIndex(), inputImage->GetPixel(inputIndex) ); } else { resultSlice->SetPixel( sliceIterator.GetIndex(), 0); } ++sliceIterator; } Image::Pointer resultImage = ImageToImageFilter::GetOutput(); GrabItkImageMemory(resultSlice, resultImage, NULL, false); resultImage->SetClonedGeometry(newSliceGeometryTest); //Workaround because of BUG (#6505) resultImage->GetGeometry()->GetIndexToWorldTransform()->SetMatrix(tempTransform); //Workaround end } ///**TEST** May ba a little bit more efficient but doesn`t already work/ //right.Normalize(); //bottom.Normalize(); //Point3D currentImagePointIn3D = origin /*+ bottom*newPixelSpacing*/; //unsigned int columns ( 0 ); /**ENDE**/ /****TEST***/ //SliceImageType::IndexType index = sliceIterator.GetIndex(); //if ( columns == (extentInPixel[0]) ) //{ //If we are at the end of a row, then we have to go to the beginning of the next row //currentImagePointIn3D = origin; //currentImagePointIn3D += newPixelSpacing[1]*bottom*index[1]; //columns = 0; //m_ImageGeometry->WorldToIndex(currentImagePointIn3D, inputIndex); //} //else //{ //// //if ( columns != 0 ) //{ //currentImagePointIn3D += newPixelSpacing[0]*right; //} //m_ImageGeometry->WorldToIndex(currentImagePointIn3D, inputIndex); //} //if ( m_ImageGeometry->IsIndexInside( inputIndex )) //{ //resultSlice->SetPixel( sliceIterator.GetIndex(), inputImage->GetPixel(inputIndex) ); //} //else if (currentImagePointIn3D == origin) //{ //Point3D temp; //temp[0] = bottom[0]*newPixelSpacing[0]*0.5; //temp[1] = bottom[1]*newPixelSpacing[1]*0.5; //temp[2] = bottom[2]*newPixelSpacing[2]*0.5; //origin[0] += temp[0]; //origin[1] += temp[1]; //origin[2] += temp[2]; //currentImagePointIn3D = origin; //m_ImageGeometry->WorldToIndex(currentImagePointIn3D, inputIndex); //if ( m_ImageGeometry->IsIndexInside( inputIndex )) //{ //resultSlice->SetPixel( sliceIterator.GetIndex(), inputImage->GetPixel(inputIndex) ); //} //} /****TEST ENDE****/ diff --git a/Modules/ImageExtraction/mitkExtractImageFilter.cpp b/Modules/ImageExtraction/mitkExtractImageFilter.cpp index 0957ed70fd..94047a738e 100644 --- a/Modules/ImageExtraction/mitkExtractImageFilter.cpp +++ b/Modules/ImageExtraction/mitkExtractImageFilter.cpp @@ -1,252 +1,254 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkExtractImageFilter.h" #include "mitkImageCast.h" #include "mitkPlaneGeometry.h" #include "mitkITKImageImport.h" #include "mitkImageTimeSelector.h" +#include + #include mitk::ExtractImageFilter::ExtractImageFilter() :m_SliceIndex(0), m_SliceDimension(0), m_TimeStep(0) { } mitk::ExtractImageFilter::~ExtractImageFilter() { } void mitk::ExtractImageFilter::GenerateData() { Image::ConstPointer input = ImageToImageFilter::GetInput(0); if ( (input->GetDimension() > 4) || (input->GetDimension() < 2) ) { MITK_ERROR << "mitk::ExtractImageFilter:GenerateData works only with 3D and 3D+t images, sorry." << std::endl; itkExceptionMacro("mitk::ExtractImageFilter works only with 3D and 3D+t images, sorry."); return; } else if (input->GetDimension() == 4) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( input ); timeSelector->SetTimeNr( m_TimeStep ); timeSelector->UpdateLargestPossibleRegion(); input = timeSelector->GetOutput(); } else if (input->GetDimension() == 2) { Image::Pointer resultImage = ImageToImageFilter::GetOutput(); resultImage = const_cast(input.GetPointer()); ImageToImageFilter::SetNthOutput( 0, resultImage ); return; } if ( m_SliceDimension >= input->GetDimension() ) { MITK_ERROR << "mitk::ExtractImageFilter:GenerateData m_SliceDimension == " << m_SliceDimension << " makes no sense with an " << input->GetDimension() << "D image." << std::endl; itkExceptionMacro("This is not a sensible value for m_SliceDimension."); return; } AccessFixedDimensionByItk( input, ItkImageProcessing, 3 ); // set a nice geometry for display and point transformations Geometry3D* inputImageGeometry = ImageToImageFilter::GetInput(0)->GetGeometry(); if (!inputImageGeometry) { MITK_ERROR << "In ExtractImageFilter::ItkImageProcessing: Input image has no geometry!" << std::endl; return; } PlaneGeometry::PlaneOrientation orientation = PlaneGeometry::Transversal; switch ( m_SliceDimension ) { default: case 2: orientation = PlaneGeometry::Transversal; break; case 1: orientation = PlaneGeometry::Frontal; break; case 0: orientation = PlaneGeometry::Sagittal; break; } PlaneGeometry::Pointer planeGeometry = PlaneGeometry::New(); planeGeometry->InitializeStandardPlane( inputImageGeometry, orientation, (ScalarType)m_SliceIndex, true, false ); Image::Pointer resultImage = ImageToImageFilter::GetOutput(); planeGeometry->ChangeImageGeometryConsideringOriginOffset(true); resultImage->SetGeometry( planeGeometry ); } template void mitk::ExtractImageFilter::ItkImageProcessing( itk::Image* itkImage ) { // use the itk::ExtractImageFilter to get a 2D image typedef itk::Image< TPixel, VImageDimension > ImageType3D; typedef itk::Image< TPixel, VImageDimension-1 > ImageType2D; typename ImageType3D::RegionType inSliceRegion = itkImage->GetLargestPossibleRegion(); inSliceRegion.SetSize( m_SliceDimension, 0 ); typedef itk::ExtractImageFilter ExtractImageFilterType; typename ExtractImageFilterType::Pointer sliceExtractor = ExtractImageFilterType::New(); sliceExtractor->SetInput( itkImage ); inSliceRegion.SetIndex( m_SliceDimension, m_SliceIndex ); sliceExtractor->SetExtractionRegion( inSliceRegion ); // calculate the output sliceExtractor->UpdateLargestPossibleRegion(); typename ImageType2D::Pointer slice = sliceExtractor->GetOutput(); // possible bug in itk::ExtractImageFilter: or in CastToItkImage ? // direction maxtrix is wrong/broken/not working with mitk::Image::InitializeByItkImage // solution here: we overwrite it with an unity matrix // correct image direction only if ITK version < 3.10 #if (ITK_VERSION_MAJOR == 3 && ITK_VERSION_MINOR < 10) || ITK_VERSION_MAJOR < 3 typename ImageType2D::DirectionType imageDirection; imageDirection.SetIdentity(); slice->SetDirection(imageDirection); #endif // re-import to MITK Image::Pointer resultImage = ImageToImageFilter::GetOutput(); GrabItkImageMemory(slice, resultImage, NULL, false); } /* * What is the input requested region that is required to produce the output * requested region? By default, the largest possible region is always * required but this is overridden in many subclasses. For instance, for an * image processing filter where an output pixel is a simple function of an * input pixel, the input requested region will be set to the output * requested region. For an image processing filter where an output pixel is * a function of the pixels in a neighborhood of an input pixel, then the * input requested region will need to be larger than the output requested * region (to avoid introducing artificial boundary conditions). This * function should never request an input region that is outside the the * input largest possible region (i.e. implementations of this method should * crop the input requested region at the boundaries of the input largest * possible region). */ void mitk::ExtractImageFilter::GenerateInputRequestedRegion() { Superclass::GenerateInputRequestedRegion(); ImageToImageFilter::InputImagePointer input = const_cast< ImageToImageFilter::InputImageType* > ( this->GetInput() ); Image::Pointer output = this->GetOutput(); if (input->GetDimension() == 2) { input->SetRequestedRegionToLargestPossibleRegion(); return; } Image::RegionType requestedRegion; requestedRegion = output->GetRequestedRegion(); requestedRegion.SetIndex(0, 0); requestedRegion.SetIndex(1, 0); requestedRegion.SetIndex(2, 0); requestedRegion.SetSize(0, input->GetDimension(0)); requestedRegion.SetSize(1, input->GetDimension(1)); requestedRegion.SetSize(2, input->GetDimension(2)); requestedRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // only one slice needed requestedRegion.SetSize( m_SliceDimension, 1 ); input->SetRequestedRegion( &requestedRegion ); } /* * Generate the information decribing the output data. The default * implementation of this method will copy information from the input to the * output. A filter may override this method if its output will have different * information than its input. For instance, a filter that shrinks an image will * need to provide an implementation for this method that changes the spacing of * the pixels. Such filters should call their superclass' implementation of this * method prior to changing the information values they need (i.e. * GenerateOutputInformation() should call * Superclass::GenerateOutputInformation() prior to changing the information. */ void mitk::ExtractImageFilter::GenerateOutputInformation() { Image::Pointer output = this->GetOutput(); Image::ConstPointer input = this->GetInput(); if (input.IsNull()) return; if ( m_SliceDimension >= input->GetDimension() && input->GetDimension() != 2 ) { MITK_ERROR << "mitk::ExtractImageFilter:GenerateOutputInformation m_SliceDimension == " << m_SliceDimension << " makes no sense with an " << input->GetDimension() << "D image." << std::endl; itkExceptionMacro("This is not a sensible value for m_SliceDimension."); return; } unsigned int sliceDimension( m_SliceDimension ); if ( input->GetDimension() == 2) { sliceDimension = 2; } unsigned int tmpDimensions[2]; switch ( sliceDimension ) { default: case 2: // orientation = PlaneGeometry::Transversal; tmpDimensions[0] = input->GetDimension(0); tmpDimensions[1] = input->GetDimension(1); break; case 1: // orientation = PlaneGeometry::Frontal; tmpDimensions[0] = input->GetDimension(0); tmpDimensions[1] = input->GetDimension(2); break; case 0: // orientation = PlaneGeometry::Sagittal; tmpDimensions[0] = input->GetDimension(1); tmpDimensions[1] = input->GetDimension(2); break; } output->Initialize(input->GetPixelType(), 2, tmpDimensions, 1 /*input->GetNumberOfChannels()*/); // initialize the spacing of the output /* Vector3D spacing = input->GetSlicedGeometry()->GetSpacing(); if(input->GetDimension()>=2) spacing[2]=spacing[1]; else spacing[2] = 1.0; output->GetSlicedGeometry()->SetSpacing(spacing); */ output->SetPropertyList(input->GetPropertyList()->Clone()); } diff --git a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp index 9a33945c9c..3ad2d250fa 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp +++ b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp @@ -1,1028 +1,1029 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-12 19:56:03 +0200 (Di, 12 Mai 2009) $ Version: $Revision: 17179 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkImageStatisticsCalculator.h" #include "mitkImageAccessByItk.h" +#include "mitkImageCast.h" #include "mitkExtractImageFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if ( ( VTK_MAJOR_VERSION <= 5 ) && ( VTK_MINOR_VERSION<=8) ) #include "mitkvtkLassoStencilSource.h" #else #include "vtkLassoStencilSource.h" #endif #include #include namespace mitk { ImageStatisticsCalculator::ImageStatisticsCalculator() : m_MaskingMode( MASKING_MODE_NONE ), m_MaskingModeChanged( false ), m_DoIgnorePixelValue(false), m_IgnorePixelValue(0.0), m_IgnorePixelValueChanged(false) { m_EmptyHistogram = HistogramType::New(); HistogramType::SizeType histogramSize; histogramSize.Fill( 256 ); m_EmptyHistogram->Initialize( histogramSize ); m_EmptyStatistics.Reset(); } ImageStatisticsCalculator::~ImageStatisticsCalculator() { } void ImageStatisticsCalculator::SetImage( const mitk::Image *image ) { if ( m_Image != image ) { m_Image = image; this->Modified(); unsigned int numberOfTimeSteps = image->GetTimeSteps(); // Initialize vectors to time-size of this image m_ImageHistogramVector.resize( numberOfTimeSteps ); m_MaskedImageHistogramVector.resize( numberOfTimeSteps ); m_PlanarFigureHistogramVector.resize( numberOfTimeSteps ); m_ImageStatisticsVector.resize( numberOfTimeSteps ); m_MaskedImageStatisticsVector.resize( numberOfTimeSteps ); m_PlanarFigureStatisticsVector.resize( numberOfTimeSteps ); m_ImageStatisticsTimeStampVector.resize( numberOfTimeSteps ); m_MaskedImageStatisticsTimeStampVector.resize( numberOfTimeSteps ); m_PlanarFigureStatisticsTimeStampVector.resize( numberOfTimeSteps ); m_ImageStatisticsCalculationTriggerVector.resize( numberOfTimeSteps ); m_MaskedImageStatisticsCalculationTriggerVector.resize( numberOfTimeSteps ); m_PlanarFigureStatisticsCalculationTriggerVector.resize( numberOfTimeSteps ); for ( unsigned int t = 0; t < image->GetTimeSteps(); ++t ) { m_ImageStatisticsTimeStampVector[t].Modified(); m_ImageStatisticsCalculationTriggerVector[t] = true; } } } void ImageStatisticsCalculator::SetImageMask( const mitk::Image *imageMask ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_Image->GetTimeSteps() != imageMask->GetTimeSteps() ) { itkExceptionMacro( << "Image and image mask need to have equal number of time steps!" ); } if ( m_ImageMask != imageMask ) { m_ImageMask = imageMask; this->Modified(); for ( unsigned int t = 0; t < m_Image->GetTimeSteps(); ++t ) { m_MaskedImageStatisticsTimeStampVector[t].Modified(); m_MaskedImageStatisticsCalculationTriggerVector[t] = true; } } } void ImageStatisticsCalculator::SetPlanarFigure( const mitk::PlanarFigure *planarFigure ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_PlanarFigure != planarFigure ) { m_PlanarFigure = planarFigure; this->Modified(); for ( unsigned int t = 0; t < m_Image->GetTimeSteps(); ++t ) { m_PlanarFigureStatisticsTimeStampVector[t].Modified(); m_PlanarFigureStatisticsCalculationTriggerVector[t] = true; } } } void ImageStatisticsCalculator::SetMaskingMode( unsigned int mode ) { if ( m_MaskingMode != mode ) { m_MaskingMode = mode; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetMaskingModeToNone() { if ( m_MaskingMode != MASKING_MODE_NONE ) { m_MaskingMode = MASKING_MODE_NONE; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetMaskingModeToImage() { if ( m_MaskingMode != MASKING_MODE_IMAGE ) { m_MaskingMode = MASKING_MODE_IMAGE; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetMaskingModeToPlanarFigure() { if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE ) { m_MaskingMode = MASKING_MODE_PLANARFIGURE; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetIgnorePixelValue(double value) { if ( m_IgnorePixelValue != value ) { m_IgnorePixelValue = value; if(m_DoIgnorePixelValue) { m_IgnorePixelValueChanged = true; } this->Modified(); } } double ImageStatisticsCalculator::GetIgnorePixelValue() { return m_IgnorePixelValue; } void ImageStatisticsCalculator::SetDoIgnorePixelValue(bool value) { if ( m_DoIgnorePixelValue != value ) { m_DoIgnorePixelValue = value; m_IgnorePixelValueChanged = true; this->Modified(); } } bool ImageStatisticsCalculator::GetDoIgnorePixelValue() { return m_DoIgnorePixelValue; } bool ImageStatisticsCalculator::ComputeStatistics( unsigned int timeStep ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image not set!" ); } if ( m_Image->GetReferenceCount() == 1 ) { // Image no longer valid; we are the only ones to still hold a reference on it return false; } if ( timeStep >= m_Image->GetTimeSteps() ) { throw std::runtime_error( "Error: invalid time step!" ); } // If a mask was set but we are the only ones to still hold a reference on // it, delete it. if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) ) { m_ImageMask = NULL; } // Check if statistics is already up-to-date unsigned long imageMTime = m_ImageStatisticsTimeStampVector[timeStep].GetMTime(); unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStampVector[timeStep].GetMTime(); unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStampVector[timeStep].GetMTime(); bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerVector[timeStep]; bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerVector[timeStep]; bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerVector[timeStep]; if ( !m_IgnorePixelValueChanged && ((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_IMAGE) || (maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) ) { // Statistics is up to date! if ( m_MaskingModeChanged ) { m_MaskingModeChanged = false; return true; } else { return false; } } // Reset state changed flag m_MaskingModeChanged = false; m_IgnorePixelValueChanged = false; // Depending on masking mode, extract and/or generate the required image // and mask data from the user input this->ExtractImageAndMask( timeStep ); Statistics *statistics; HistogramType::ConstPointer *histogram; switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: { if(!m_DoIgnorePixelValue) { statistics = &m_ImageStatisticsVector[timeStep]; histogram = &m_ImageHistogramVector[timeStep]; m_ImageStatisticsTimeStampVector[timeStep].Modified(); m_ImageStatisticsCalculationTriggerVector[timeStep] = false; } else { statistics = &m_MaskedImageStatisticsVector[timeStep]; histogram = &m_MaskedImageHistogramVector[timeStep]; m_MaskedImageStatisticsTimeStampVector[timeStep].Modified(); m_MaskedImageStatisticsCalculationTriggerVector[timeStep] = false; } break; } case MASKING_MODE_IMAGE: statistics = &m_MaskedImageStatisticsVector[timeStep]; histogram = &m_MaskedImageHistogramVector[timeStep]; m_MaskedImageStatisticsTimeStampVector[timeStep].Modified(); m_MaskedImageStatisticsCalculationTriggerVector[timeStep] = false; break; case MASKING_MODE_PLANARFIGURE: statistics = &m_PlanarFigureStatisticsVector[timeStep]; histogram = &m_PlanarFigureHistogramVector[timeStep]; m_PlanarFigureStatisticsTimeStampVector[timeStep].Modified(); m_PlanarFigureStatisticsCalculationTriggerVector[timeStep] = false; break; } // Calculate statistics and histogram(s) if ( m_InternalImage->GetDimension() == 3 ) { if ( m_MaskingMode == MASKING_MODE_NONE && !m_DoIgnorePixelValue ) { AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 3, *statistics, histogram ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 3, m_InternalImageMask3D.GetPointer(), *statistics, histogram ); } } else if ( m_InternalImage->GetDimension() == 2 ) { if ( m_MaskingMode == MASKING_MODE_NONE && !m_DoIgnorePixelValue ) { AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 2, *statistics, histogram ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 2, m_InternalImageMask2D.GetPointer(), *statistics, histogram ); } } else { MITK_ERROR << "ImageStatistics: Image dimension not supported!"; } // Release unused image smart pointers to free memory m_InternalImage = mitk::Image::ConstPointer(); m_InternalImageMask3D = MaskImage3DType::Pointer(); m_InternalImageMask2D = MaskImage2DType::Pointer(); return true; } const ImageStatisticsCalculator::HistogramType * ImageStatisticsCalculator::GetHistogram( unsigned int timeStep ) const { if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) ) { return NULL; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: { if(m_DoIgnorePixelValue) return m_MaskedImageHistogramVector[timeStep]; return m_ImageHistogramVector[timeStep]; } case MASKING_MODE_IMAGE: return m_MaskedImageHistogramVector[timeStep]; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureHistogramVector[timeStep]; } } const ImageStatisticsCalculator::Statistics & ImageStatisticsCalculator::GetStatistics( unsigned int timeStep ) const { if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) ) { return m_EmptyStatistics; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: { if(m_DoIgnorePixelValue) return m_MaskedImageStatisticsVector[timeStep]; return m_ImageStatisticsVector[timeStep]; } case MASKING_MODE_IMAGE: return m_MaskedImageStatisticsVector[timeStep]; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureStatisticsVector[timeStep]; } } void ImageStatisticsCalculator::ExtractImageAndMask( unsigned int timeStep ) { if ( m_Image.IsNull() ) { throw std::runtime_error( "Error: image empty!" ); } if ( timeStep >= m_Image->GetTimeSteps() ) { throw std::runtime_error( "Error: invalid time step!" ); } ImageTimeSelector::Pointer imageTimeSelector = ImageTimeSelector::New(); imageTimeSelector->SetInput( m_Image ); imageTimeSelector->SetTimeNr( timeStep ); imageTimeSelector->UpdateLargestPossibleRegion(); mitk::Image *timeSliceImage = imageTimeSelector->GetOutput(); switch ( m_MaskingMode ) { case MASKING_MODE_NONE: { m_InternalImage = timeSliceImage; m_InternalImageMask2D = NULL; m_InternalImageMask3D = NULL; if(m_DoIgnorePixelValue) { CastToItkImage( timeSliceImage, m_InternalImageMask3D ); m_InternalImageMask3D->FillBuffer(1); } break; } case MASKING_MODE_IMAGE: { if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) ) { if ( timeStep < m_ImageMask->GetTimeSteps() ) { ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New(); maskedImageTimeSelector->SetInput( m_ImageMask ); maskedImageTimeSelector->SetTimeNr( timeStep ); maskedImageTimeSelector->UpdateLargestPossibleRegion(); mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput(); m_InternalImage = timeSliceImage; CastToItkImage( timeSliceMaskedImage, m_InternalImageMask3D ); } else { throw std::runtime_error( "Error: image mask has not enough time steps!" ); } } else { throw std::runtime_error( "Error: image mask empty!" ); } break; } case MASKING_MODE_PLANARFIGURE: { m_InternalImageMask2D = NULL; if ( m_PlanarFigure.IsNull() ) { throw std::runtime_error( "Error: planar figure empty!" ); } if ( !m_PlanarFigure->IsClosed() ) { throw std::runtime_error( "Masking not possible for non-closed figures" ); } const Geometry3D *imageGeometry = timeSliceImage->GetGeometry(); if ( imageGeometry == NULL ) { throw std::runtime_error( "Image geometry invalid!" ); } const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); if ( planarFigureGeometry2D == NULL ) { throw std::runtime_error( "Planar-Figure not yet initialized!" ); } const PlaneGeometry *planarFigureGeometry = dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D ); if ( planarFigureGeometry == NULL ) { throw std::runtime_error( "Non-planar planar figures not supported!" ); } // Find principal direction of PlanarFigure in input image unsigned int axis; if ( !this->GetPrincipalAxis( imageGeometry, planarFigureGeometry->GetNormal(), axis ) ) { throw std::runtime_error( "Non-aligned planar figures not supported!" ); } // Find slice number corresponding to PlanarFigure in input image MaskImage3DType::IndexType index; imageGeometry->WorldToIndex( planarFigureGeometry->GetOrigin(), index ); unsigned int slice = index[axis]; // Extract slice with given position and direction from image ExtractImageFilter::Pointer imageExtractor = ExtractImageFilter::New(); imageExtractor->SetInput( timeSliceImage ); imageExtractor->SetSliceDimension( axis ); imageExtractor->SetSliceIndex( slice ); imageExtractor->Update(); m_InternalImage = imageExtractor->GetOutput(); // Compute mask from PlanarFigure AccessFixedDimensionByItk_1( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 2, axis ); } } if(m_DoIgnorePixelValue) { if ( m_InternalImage->GetDimension() == 3 ) { AccessFixedDimensionByItk_1( m_InternalImage, InternalMaskIgnoredPixels, 3, m_InternalImageMask3D.GetPointer() ); } else if ( m_InternalImage->GetDimension() == 2 ) { AccessFixedDimensionByItk_1( m_InternalImage, InternalMaskIgnoredPixels, 2, m_InternalImageMask2D.GetPointer() ); } } } bool ImageStatisticsCalculator::GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector, unsigned int &axis ) { vector.Normalize(); for ( unsigned int i = 0; i < 3; ++i ) { Vector3D axisVector = geometry->GetAxisVector( i ); axisVector.Normalize(); if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps ) { axis = i; return true; } } return false; } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked( const itk::Image< TPixel, VImageDimension > *image, Statistics &statistics, typename HistogramType::ConstPointer *histogram ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned short, VImageDimension > MaskImageType; typedef typename ImageType::IndexType IndexType; typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType > HistogramGeneratorType; // Progress listening... typedef itk::SimpleMemberCommand< ImageStatisticsCalculator > ITKCommandType; ITKCommandType::Pointer progressListener; progressListener = ITKCommandType::New(); progressListener->SetCallbackFunction( this, &ImageStatisticsCalculator::UnmaskedStatisticsProgressUpdate ); // Issue 100 artificial progress events since ScalarIMageToHistogramGenerator // does not (yet?) support progress reporting this->InvokeEvent( itk::StartEvent() ); for ( unsigned int i = 0; i < 100; ++i ) { this->UnmaskedStatisticsProgressUpdate(); } // Calculate histogram typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New(); histogramGenerator->SetInput( image ); histogramGenerator->SetMarginalScale( 100 ); // Defines y-margin width of histogram histogramGenerator->SetNumberOfBins( 768 ); // CT range [-1024, +2048] --> bin size 4 values histogramGenerator->SetHistogramMin( -1024.0 ); histogramGenerator->SetHistogramMax( 2048.0 ); histogramGenerator->Compute(); *histogram = histogramGenerator->GetOutput(); // Calculate statistics (separate filter) typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType; typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New(); statisticsFilter->SetInput( image ); unsigned long observerTag = statisticsFilter->AddObserver( itk::ProgressEvent(), progressListener ); statisticsFilter->Update(); statisticsFilter->RemoveObserver( observerTag ); this->InvokeEvent( itk::EndEvent() ); statistics.N = image->GetBufferedRegion().GetNumberOfPixels(); statistics.Min = statisticsFilter->GetMinimum(); statistics.Max = statisticsFilter->GetMaximum(); statistics.Mean = statisticsFilter->GetMean(); statistics.Median = 0.0; statistics.Sigma = statisticsFilter->GetSigma(); statistics.RMS = sqrt( statistics.Mean * statistics.Mean + statistics.Sigma * statistics.Sigma ); } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalMaskIgnoredPixels( const itk::Image< TPixel, VImageDimension > *image, itk::Image< unsigned short, VImageDimension > *maskImage ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned short, VImageDimension > MaskImageType; itk::ImageRegionIterator itmask(maskImage, maskImage->GetLargestPossibleRegion()); itk::ImageRegionConstIterator itimage(image, image->GetLargestPossibleRegion()); itmask = itmask.Begin(); itimage = itimage.Begin(); while( !itmask.IsAtEnd() ) { if(m_IgnorePixelValue == itimage.Get()) { itmask.Set(0); } ++itmask; ++itimage; } } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalCalculateStatisticsMasked( const itk::Image< TPixel, VImageDimension > *image, itk::Image< unsigned short, VImageDimension > *maskImage, Statistics &statistics, typename HistogramType::ConstPointer *histogram ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned short, VImageDimension > MaskImageType; typedef typename ImageType::IndexType IndexType; typedef typename ImageType::PointType PointType; typedef typename ImageType::SpacingType SpacingType; typedef itk::LabelStatisticsImageFilter< ImageType, MaskImageType > LabelStatisticsFilterType; typedef itk::ChangeInformationImageFilter< MaskImageType > ChangeInformationFilterType; typedef itk::ExtractImageFilter< ImageType, ImageType > ExtractImageFilterType; // Make sure that mask is set if ( maskImage == NULL ) { itkExceptionMacro( << "Mask image needs to be set!" ); } // Make sure that spacing of mask and image are the same SpacingType imageSpacing = image->GetSpacing(); SpacingType maskSpacing = maskImage->GetSpacing(); PointType zeroPoint; zeroPoint.Fill( 0.0 ); if ( (zeroPoint + imageSpacing).SquaredEuclideanDistanceTo( (zeroPoint + maskSpacing) ) > mitk::eps ) { itkExceptionMacro( << "Mask needs to have same spacing as image! (Image spacing: " << imageSpacing << "; Mask spacing: " << maskSpacing << ")" ); } // Make sure that the voxels of mask and image are correctly "aligned", i.e., voxel boundaries are the same in both images PointType imageOrigin = image->GetOrigin(); PointType maskOrigin = maskImage->GetOrigin(); long offset[ImageType::ImageDimension]; for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i ) { double indexCoordDistance = (maskOrigin[i] - imageOrigin[i]) / imageSpacing[i]; double misalignment = indexCoordDistance - floor( indexCoordDistance + 0.5 ); if ( fabs( misalignment ) > imageSpacing[i] / 20.0 ) { itkExceptionMacro( << "Pixels/voxels of mask and image are not sufficiently aligned! (Misalignment: " << misalignment << ")" ); } offset[i] = (int) indexCoordDistance + image->GetBufferedRegion().GetIndex()[i]; } // Adapt the origin and region (index/size) of the mask so that the origin of both are the same typename ChangeInformationFilterType::Pointer adaptMaskFilter; adaptMaskFilter = ChangeInformationFilterType::New(); adaptMaskFilter->ChangeOriginOn(); adaptMaskFilter->ChangeRegionOn(); adaptMaskFilter->SetInput( maskImage ); adaptMaskFilter->SetOutputOrigin( image->GetOrigin() ); adaptMaskFilter->SetOutputOffset( offset ); adaptMaskFilter->Update(); typename MaskImageType::Pointer adaptedMaskImage = adaptMaskFilter->GetOutput(); // Make sure that mask region is contained within image region if ( !image->GetLargestPossibleRegion().IsInside( adaptedMaskImage->GetLargestPossibleRegion() ) ) { itkExceptionMacro( << "Mask region needs to be inside of image region! (Image region: " << image->GetLargestPossibleRegion() << "; Mask region: " << adaptedMaskImage->GetLargestPossibleRegion() << ")" ); } // If mask region is smaller than image region, extract the sub-sampled region from the original image typename ImageType::SizeType imageSize = image->GetBufferedRegion().GetSize(); typename ImageType::SizeType maskSize = maskImage->GetBufferedRegion().GetSize(); bool maskSmallerImage = false; for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i ) { if ( maskSize[i] < imageSize[i] ) { maskSmallerImage = true; } } typename ImageType::ConstPointer adaptedImage; if ( maskSmallerImage ) { typename ExtractImageFilterType::Pointer extractImageFilter = ExtractImageFilterType::New(); extractImageFilter->SetInput( image ); extractImageFilter->SetExtractionRegion( adaptedMaskImage->GetBufferedRegion() ); extractImageFilter->Update(); adaptedImage = extractImageFilter->GetOutput(); } else { adaptedImage = image; } // Initialize Filter typename LabelStatisticsFilterType::Pointer labelStatisticsFilter; labelStatisticsFilter = LabelStatisticsFilterType::New(); labelStatisticsFilter->SetInput( adaptedImage ); labelStatisticsFilter->SetLabelInput( adaptedMaskImage ); labelStatisticsFilter->UseHistogramsOn(); labelStatisticsFilter->SetHistogramParameters( 384, -1024.0, 2048.0); // Add progress listening typedef itk::SimpleMemberCommand< ImageStatisticsCalculator > ITKCommandType; ITKCommandType::Pointer progressListener; progressListener = ITKCommandType::New(); progressListener->SetCallbackFunction( this, &ImageStatisticsCalculator::MaskedStatisticsProgressUpdate ); unsigned long observerTag = labelStatisticsFilter->AddObserver( itk::ProgressEvent(), progressListener ); // Execute filter this->InvokeEvent( itk::StartEvent() ); // Make sure that only the mask region is considered (otherwise, if the mask region is smaller // than the image region, the Update() would result in an exception). labelStatisticsFilter->GetOutput()->SetRequestedRegion( adaptedMaskImage->GetLargestPossibleRegion() ); // Execute the filter labelStatisticsFilter->Update(); this->InvokeEvent( itk::EndEvent() ); labelStatisticsFilter->RemoveObserver( observerTag ); // Find label of mask (other than 0) bool maskNonEmpty = false; unsigned int i; for ( i = 1; i < 4096; ++i ) { if ( labelStatisticsFilter->HasLabel( i ) ) { maskNonEmpty = true; break; } } if ( maskNonEmpty ) { *histogram = labelStatisticsFilter->GetHistogram( i ); statistics.N = labelStatisticsFilter->GetCount( i ); statistics.Min = labelStatisticsFilter->GetMinimum( i ); statistics.Max = labelStatisticsFilter->GetMaximum( i ); statistics.Mean = labelStatisticsFilter->GetMean( i ); statistics.Median = labelStatisticsFilter->GetMedian( i ); statistics.Sigma = labelStatisticsFilter->GetSigma( i ); statistics.RMS = sqrt( statistics.Mean * statistics.Mean + statistics.Sigma * statistics.Sigma ); } else { *histogram = m_EmptyHistogram; statistics.Reset(); } } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalCalculateMaskFromPlanarFigure( const itk::Image< TPixel, VImageDimension > *image, unsigned int axis ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, MaskImage2DType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". typename CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput( image ); castFilter->Update(); castFilter->GetOutput()->FillBuffer( 1 ); // all PolylinePoints of the PlanarFigure are stored in a vtkPoints object. // These points are used by the vtkLassoStencilSource to create // a vtkImageStencil. const mitk::Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const mitk::Geometry3D *imageGeometry3D = m_Image->GetGeometry( 0 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } // store the polyline contour as vtkPoints object bool outOfBounds = false; vtkSmartPointer points = vtkPoints::New(); typename PlanarFigure::PolyLineType::const_iterator it; const Vector3D& imageSpacing3D = imageGeometry3D->GetSpacing(); for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected // image planarFigureGeometry2D->Map( it->Point, point3D ); // Polygons (partially) outside of the image bounds can not be processed // further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { outOfBounds = true; } imageGeometry3D->WorldToIndex( point3D, point3D ); points->InsertNextPoint( point3D[i0], point3D[i1], 0 ); } if ( outOfBounds ) { throw std::runtime_error( "Figure at least partially outside of image bounds!" ); } // create a vtkLassoStencilSource and set the points of the Polygon vtkSmartPointer lassoStencil = vtkLassoStencilSource::New(); lassoStencil->SetShapeToPolygon(); lassoStencil->SetPoints( points ); // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< MaskImage2DType > ImageImportType; typedef itk::VTKImageExport< MaskImage2DType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( castFilter->GetOutput() ); vtkSmartPointer vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); // Apply the generated image stencil to the input image vtkSmartPointer imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() ); imageStencilFilter->SetStencil( lassoStencil->GetOutput() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkSmartPointer vtkExporter = vtkImageExport::New(); vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // Store mask m_InternalImageMask2D = itkImporter->GetOutput(); // Clean up VTK objects vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? } void ImageStatisticsCalculator::UnmaskedStatisticsProgressUpdate() { // Need to throw away every second progress event to reach a final count of // 100 since two consecutive filters are used in this case static int updateCounter = 0; if ( updateCounter++ % 2 == 0 ) { this->InvokeEvent( itk::ProgressEvent() ); } } void ImageStatisticsCalculator::MaskedStatisticsProgressUpdate() { this->InvokeEvent( itk::ProgressEvent() ); } } diff --git a/Modules/MitkExt/Algorithms/mitkBoundingObjectToSegmentationFilter.cpp b/Modules/MitkExt/Algorithms/mitkBoundingObjectToSegmentationFilter.cpp index 3c7b5dbe90..55411b9788 100644 --- a/Modules/MitkExt/Algorithms/mitkBoundingObjectToSegmentationFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkBoundingObjectToSegmentationFilter.cpp @@ -1,120 +1,122 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 27918 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkBoundingObjectToSegmentationFilter.h" #include "mitkImageCast.h" +#include + mitk::BoundingObjectToSegmentationFilter::BoundingObjectToSegmentationFilter() { this->SetNumberOfRequiredInputs(1); } mitk::BoundingObjectToSegmentationFilter::~BoundingObjectToSegmentationFilter() { } void mitk::BoundingObjectToSegmentationFilter::SetBoundingObject(mitk::BoundingObject::Pointer boundingObject) { mitk::BoundingObjectGroup* testgroup = dynamic_cast (boundingObject.GetPointer()); if (testgroup) m_boundingObjectGroup = testgroup; else { m_boundingObjectGroup = mitk::BoundingObjectGroup::New(); m_boundingObjectGroup->AddBoundingObject(boundingObject); } } void mitk::BoundingObjectToSegmentationFilter::GenerateData() { typedef itk::Image itkImageType; mitk::Image::Pointer outputImage = this->GetOutput(); mitk::Image::ConstPointer inputImage = this->GetInput(); outputImage->Initialize(inputImage); itkImageType::Pointer itkImage; CastToItkImage(outputImage, itkImage); itkImage->FillBuffer(0); for (unsigned int i=0; iGetCount(); i++) { //create region for boundingobject mitk::BoundingObject::Pointer boundingObject = m_boundingObjectGroup->GetBoundingObjects().at(i); mitk::Geometry3D::Pointer boGeometry = boundingObject->GetGeometry(); mitk::Geometry3D::Pointer inputImageGeometry = inputImage->GetSlicedGeometry(); mitk::BoundingBox::Pointer boToIm = boGeometry->CalculateBoundingBoxRelativeToTransform(inputImageGeometry->GetIndexToWorldTransform()); mitk::BoundingBox::ConstPointer imgBB = inputImageGeometry->GetBoundingBox(); mitk::BoundingBox::PointType minImg = imgBB->GetMinimum(); mitk::BoundingBox::PointType maxImg = imgBB->GetMaximum(); itkImageType::IndexType boIndex; itkImageType::SizeType boSize; mitk::BoundingBox::PointType min = boToIm->GetMinimum(); mitk::BoundingBox::PointType max = boToIm->GetMaximum(); //check if boundingbox is inside imageregion for (int i =0; i<3; i++) { if (min [i] < minImg[i]) min[i] = minImg[i]; if (max [i] < minImg[i]) max[i] = minImg[i]; if (max[i] > maxImg[i]) max[i] = maxImg[i]; if (min [i] > maxImg[i]) min[i] = maxImg[i]-1; } // add 0.5 (boGeometry is no image geometry) boIndex[0] = (mitk::SlicedData::IndexType::IndexValueType)(min[0] + 0.5); boIndex[1] = (mitk::SlicedData::IndexType::IndexValueType)(min[1] + 0.5); boIndex[2] = (mitk::SlicedData::IndexType::IndexValueType)(min[2] + 0.5); // add 1 because we need 0.5 for each index boSize[0] = (mitk::SlicedData::IndexType::IndexValueType) (max[0]-min[0]); boSize[1] = (mitk::SlicedData::IndexType::IndexValueType) (max[1]-min[1]); boSize[2] = (mitk::SlicedData::IndexType::IndexValueType) (max[2]-min[2]); itkImageType::RegionType region(boIndex, boSize); //create region iterator itk::ImageRegionIteratorWithIndex itBoundingObject = itk::ImageRegionIteratorWithIndex(itkImage, region ); itBoundingObject.GoToBegin(); while(!itBoundingObject.IsAtEnd()) { itkImageType::IndexType index = itBoundingObject.GetIndex(); mitk::Point3D p; p[0] = index[0]; p[1] = index[1]; p[2] = index[2]; inputImageGeometry->IndexToWorld(p,p); if (boundingObject->IsInside(p) && boundingObject->GetPositive()) itBoundingObject.Set(1); else if (boundingObject->IsInside(p) && !boundingObject->GetPositive()) itBoundingObject.Set(0); ++itBoundingObject; } } CastToMitkImage(itkImage, outputImage); -} \ No newline at end of file +} diff --git a/Modules/MitkExt/Algorithms/mitkCalculateSegmentationVolume.cpp b/Modules/MitkExt/Algorithms/mitkCalculateSegmentationVolume.cpp index a339453733..3301d2b6eb 100644 --- a/Modules/MitkExt/Algorithms/mitkCalculateSegmentationVolume.cpp +++ b/Modules/MitkExt/Algorithms/mitkCalculateSegmentationVolume.cpp @@ -1,123 +1,125 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ +#include + #include "mitkCalculateSegmentationVolume.h" #include "itkImageRegionConstIteratorWithIndex.h" #include namespace mitk { CalculateSegmentationVolume::CalculateSegmentationVolume() { } CalculateSegmentationVolume::~CalculateSegmentationVolume() { } template < typename TPixel, unsigned int VImageDimension > void CalculateSegmentationVolume::ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, TPixel* itkNotUsed(dummy) ) { itk::ImageRegionConstIteratorWithIndex > iterBinaryImage( itkImage, itkImage->GetLargestPossibleRegion() ); typename itk::ImageRegionConstIteratorWithIndex >::IndexType currentIndex; typename itk::ImageRegionConstIteratorWithIndex >::IndexType minIndex; for (unsigned int i = 0; i < VImageDimension; ++i) minIndex[i] = std::numeric_limits::max(); typename itk::ImageRegionConstIteratorWithIndex >::IndexType maxIndex; for (unsigned int i = 0; i < VImageDimension; ++i) maxIndex[i] = std::numeric_limits::min(); m_CenterOfMass.Fill(0.0); m_Volume = 0; while (!iterBinaryImage.IsAtEnd()) { if ( iterBinaryImage.Get() > static_cast(0.0) ) { // update center of mass currentIndex = iterBinaryImage.GetIndex(); itk::Vector currentPoint; for (unsigned int i = 0; i < VImageDimension; ++i) currentPoint[i] = currentIndex[i]; m_CenterOfMass = (m_CenterOfMass * ( static_cast(m_Volume) / static_cast(m_Volume+1) ) ) // e.g. 3 points: old center * 2/3 + currentPoint * 1/3; + currentPoint / static_cast(m_Volume+1); // update number of voxels ++m_Volume; // update bounding box for (unsigned int i = 0; i < VImageDimension; ++i) { if (currentIndex[i] < minIndex[i]) minIndex[i] = currentIndex[i]; if (currentIndex[i] > maxIndex[i]) maxIndex[i] = currentIndex[i]; } } ++iterBinaryImage; } m_MinIndexOfBoundingBox[2] = 0.0; m_MaxIndexOfBoundingBox[2] = 0.0; for (unsigned int i = 0; i < VImageDimension; ++i) { m_MinIndexOfBoundingBox[i] = minIndex[i]; m_MaxIndexOfBoundingBox[i] = maxIndex[i]; } } bool CalculateSegmentationVolume::ReadyToRun() { Image::Pointer image; GetPointerParameter("Input", image); return image.IsNotNull() && GetGroupNode(); } bool CalculateSegmentationVolume::ThreadedUpdateFunction() { // get image Image::Pointer image; GetPointerParameter("Input", image); AccessFixedDimensionByItk( image.GetPointer(), ItkImageProcessing, 3 ); // some magic to call the correctly templated function (we only do 3D images here!) // consider single voxel volume Vector3D spacing = image->GetSlicedGeometry()->GetSpacing(); // spacing in mm float volumeML = (ScalarType) m_Volume * spacing[0] * spacing[1] * spacing[2] / 1000.0; // convert to ml DataNode* groupNode = GetGroupNode(); if (groupNode) { groupNode->SetProperty( "volume", FloatProperty::New(volumeML) ); groupNode->SetProperty( "centerOfMass", Vector3DProperty::New(m_CenterOfMass) ); groupNode->SetProperty( "boundingBoxMinimum", Vector3DProperty::New(m_MinIndexOfBoundingBox) ); groupNode->SetProperty( "boundingBoxMaximum", Vector3DProperty::New(m_MaxIndexOfBoundingBox) ); groupNode->SetProperty( "showVolume", BoolProperty::New(true) ); } return true; } } // namespace diff --git a/Modules/MitkExt/Algorithms/mitkContourUtils.cpp b/Modules/MitkExt/Algorithms/mitkContourUtils.cpp index a43b834d3c..483eba1f23 100644 --- a/Modules/MitkExt/Algorithms/mitkContourUtils.cpp +++ b/Modules/MitkExt/Algorithms/mitkContourUtils.cpp @@ -1,169 +1,171 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkContourUtils.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" +#include "mitkInstantiateAccessFunctions.h" #include "ipSegmentation.h" #define InstantiateAccessFunction_ItkCopyFilledContourToSlice(pixelType, dim) \ template void mitk::ContourUtils::ItkCopyFilledContourToSlice(itk::Image*, const mitk::Image*, int); // explicitly instantiate the 2D version of this method InstantiateAccessFunctionForFixedDimension(ItkCopyFilledContourToSlice, 2); mitk::ContourUtils::ContourUtils() { } mitk::ContourUtils::~ContourUtils() { } mitk::Contour::Pointer mitk::ContourUtils::ProjectContourTo2DSlice(Image* slice, Contour* contourIn3D, bool itkNotUsed( correctionForIpSegmentation ), bool constrainToInside) { if ( !slice || !contourIn3D ) return NULL; Contour::Pointer projectedContour = Contour::New(); const Contour::PathType::VertexListType* pointsIn3D = contourIn3D->GetContourPath()->GetVertexList(); const Geometry3D* sliceGeometry = slice->GetGeometry(); for ( Contour::PathType::VertexListType::const_iterator iter = pointsIn3D->begin(); iter != pointsIn3D->end(); ++iter ) { Contour::PathType::VertexType currentPointIn3DITK = *iter; Point3D currentPointIn3D; for (int i = 0; i < 3; ++i) currentPointIn3D[i] = currentPointIn3DITK[i]; Point3D projectedPointIn2D; projectedPointIn2D.Fill(0.0); sliceGeometry->WorldToIndex( currentPointIn3D, projectedPointIn2D ); // MITK_INFO << "world point " << currentPointIn3D << " in index is " << projectedPointIn2D; if ( !sliceGeometry->IsIndexInside( projectedPointIn2D ) && constrainToInside ) { MITK_INFO << "**" << currentPointIn3D << " is " << projectedPointIn2D << " --> correct it (TODO)" << std::endl; } projectedContour->AddVertex( projectedPointIn2D ); } return projectedContour; } mitk::Contour::Pointer mitk::ContourUtils::BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, Contour* contourIn2D, bool itkNotUsed( correctionForIpSegmentation ) ) { if ( !sliceGeometry || !contourIn2D ) return NULL; Contour::Pointer worldContour = Contour::New(); const Contour::PathType::VertexListType* pointsIn2D = contourIn2D->GetContourPath()->GetVertexList(); for ( Contour::PathType::VertexListType::const_iterator iter = pointsIn2D->begin(); iter != pointsIn2D->end(); ++iter ) { Contour::PathType::VertexType currentPointIn3DITK = *iter; Point3D currentPointIn2D; for (int i = 0; i < 3; ++i) currentPointIn2D[i] = currentPointIn3DITK[i]; Point3D worldPointIn3D; worldPointIn3D.Fill(0.0); sliceGeometry->IndexToWorld( currentPointIn2D, worldPointIn3D ); //MITK_INFO << "index " << currentPointIn2D << " world " << worldPointIn3D << std::endl; worldContour->AddVertex( worldPointIn3D ); } return worldContour; } void mitk::ContourUtils::FillContourInSlice( Contour* projectedContour, Image* sliceImage, int paintingPixelValue ) { // 1. Use ipSegmentation to draw a filled(!) contour into a new 8 bit 2D image, which will later be copied back to the slice. // We don't work on the "real" working data, because ipSegmentation would restrict us to 8 bit images // convert the projected contour into a ipSegmentation format mitkIpInt4_t* picContour = new mitkIpInt4_t[2 * projectedContour->GetNumberOfPoints()]; const Contour::PathType::VertexListType* pointsIn2D = projectedContour->GetContourPath()->GetVertexList(); unsigned int index(0); for ( Contour::PathType::VertexListType::const_iterator iter = pointsIn2D->begin(); iter != pointsIn2D->end(); ++iter, ++index ) { picContour[ 2 * index + 0 ] = static_cast( (*iter)[0] + 1.0 ); // +0.5 wahrscheinlich richtiger picContour[ 2 * index + 1 ] = static_cast( (*iter)[1] + 1.0 ); //MITK_INFO << "mitk 2d [" << (*iter)[0] << ", " << (*iter)[1] << "] pic [" << picContour[ 2*index+0] << ", " << picContour[ 2*index+1] << "]"; } assert( sliceImage->GetSliceData() ); mitkIpPicDescriptor* originalPicSlice = sliceImage->GetSliceData()->GetPicDescriptor(); mitkIpPicDescriptor* picSlice = ipMITKSegmentationNew( originalPicSlice ); ipMITKSegmentationClear( picSlice ); assert( originalPicSlice && picSlice ); // here comes the actual contour filling algorithm (from ipSegmentation/Graphics Gems) ipMITKSegmentationCombineRegion ( picSlice, picContour, projectedContour->GetNumberOfPoints(), NULL, IPSEGMENTATION_OR, 1); // set to 1 delete[] picContour; // 2. Copy the filled contour to the working data slice // copy all pixels that are non-zero to the original image (not caring for the actual type of the working image). perhaps make the replace value a parameter ( -> general painting tool ). // make the pic slice an mitk/itk image (as little ipPic code as possible), call a templated method with accessbyitk, iterate over the original and the modified slice Image::Pointer ipsegmentationModifiedSlice = Image::New(); ipsegmentationModifiedSlice->Initialize( picSlice ); ipsegmentationModifiedSlice->SetPicSlice( picSlice ); AccessFixedDimensionByItk_2( sliceImage, ItkCopyFilledContourToSlice, 2, ipsegmentationModifiedSlice, paintingPixelValue ); ipsegmentationModifiedSlice = NULL; // free MITK header information ipMITKSegmentationFree( picSlice ); // free actual memory } template void mitk::ContourUtils::ItkCopyFilledContourToSlice( itk::Image* originalSlice, const Image* filledContourSlice, int overwritevalue ) { typedef itk::Image SliceType; typename SliceType::Pointer filledContourSliceITK; CastToItkImage( filledContourSlice, filledContourSliceITK ); // now the original slice and the ipSegmentation-painted slice are in the same format, and we can just copy all pixels that are non-zero typedef itk::ImageRegionIterator< SliceType > OutputIteratorType; typedef itk::ImageRegionConstIterator< SliceType > InputIteratorType; InputIteratorType inputIterator( filledContourSliceITK, filledContourSliceITK->GetLargestPossibleRegion() ); OutputIteratorType outputIterator( originalSlice, originalSlice->GetLargestPossibleRegion() ); outputIterator.GoToBegin(); inputIterator.GoToBegin(); while ( !outputIterator.IsAtEnd() ) { if ( inputIterator.Get() != 0 ) { outputIterator.Set( overwritevalue ); } ++outputIterator; ++inputIterator; } } diff --git a/Modules/MitkExt/Algorithms/mitkCorrectorAlgorithm.cpp b/Modules/MitkExt/Algorithms/mitkCorrectorAlgorithm.cpp index 4561a458f8..afbf24fce1 100644 --- a/Modules/MitkExt/Algorithms/mitkCorrectorAlgorithm.cpp +++ b/Modules/MitkExt/Algorithms/mitkCorrectorAlgorithm.cpp @@ -1,507 +1,509 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkCorrectorAlgorithm.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" +#include "mitkImageDataItem.h" #include "mitkContourUtils.h" mitk::CorrectorAlgorithm::CorrectorAlgorithm() :ImageToImageFilter() { } mitk::CorrectorAlgorithm::~CorrectorAlgorithm() { } void mitk::CorrectorAlgorithm::GenerateData() { Image::Pointer inputImage = const_cast(ImageToImageFilter::GetInput(0)); if (inputImage.IsNull() || inputImage->GetDimension() != 2) { itkExceptionMacro("CorrectorAlgorithm needs a 2D image as input."); } if (m_Contour.IsNull()) { itkExceptionMacro("CorrectorAlgorithm needs a Contour object as input."); } // copy the input (since m_WorkingImage will be changed later) m_WorkingImage = Image::New(); m_WorkingImage->Initialize( inputImage ); m_WorkingImage->SetVolume( inputImage.GetPointer()->GetData() ); if (inputImage->GetTimeSlicedGeometry() ) { AffineGeometryFrame3D::Pointer originalGeometryAGF = inputImage->GetTimeSlicedGeometry()->Clone(); TimeSlicedGeometry::Pointer originalGeometry = dynamic_cast( originalGeometryAGF.GetPointer() ); m_WorkingImage->SetGeometry( originalGeometry ); } else { itkExceptionMacro("Original image does not have a 'Time sliced geometry'! Cannot copy."); } // Convert to ipMITKSegmentationTYPE (because TobiasHeimannCorrectionAlgorithm relys on that data type) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage( m_WorkingImage, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); // possible bug in CastToItkImage ? // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479: // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed // solution here: we overwrite it with an unity matrix itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeImage->SetDirection(imageDirection); Image::Pointer temporarySlice = this->GetOutput(); // temporarySlice = ImportItkImage( correctPixelTypeImage ); CastToMitkImage( correctPixelTypeImage, temporarySlice ); TobiasHeimannCorrectionAlgorithm( temporarySlice->GetSliceData()->GetPicDescriptor() ); // temporarySlice is our return value (user can get it by calling GetOutput() ) CalculateDifferenceImage( temporarySlice, inputImage ); if ( m_DifferenceImage.IsNotNull() && inputImage->GetTimeSlicedGeometry() ) { AffineGeometryFrame3D::Pointer originalGeometryAGF = inputImage->GetTimeSlicedGeometry()->Clone(); TimeSlicedGeometry::Pointer originalGeometry = dynamic_cast( originalGeometryAGF.GetPointer() ); m_DifferenceImage->SetGeometry( originalGeometry ); } else { itkExceptionMacro("Original image does not have a 'Time sliced geometry'! Cannot copy."); } } void mitk::CorrectorAlgorithm::TobiasHeimannCorrectionAlgorithm(mitkIpPicDescriptor* pic) { /*! Some documentation (not by the original author) TobiasHeimannCorrectionAlgorithm will be called, when the user has finished drawing a freehand line. There should be different results, depending on the line's properties: 1. Without any prior segmentation, the start point and the end point of the drawn line will be connected to a contour and the area enclosed by the contour will be marked as segmentation. 2. When the whole line is inside a segmentation, start and end point will be connected to a contour and the area of this contour will be subtracted from the segmentation. 3. When the line starts inside a segmentation and ends outside with only a single transition from segmentation to no-segmentation, nothing will happen. 4. When there are multiple transitions between inside-segmentation and outside-segmentation, the line will be divided in so called segments. Each segment is either fully inside or fully outside a segmentation. When it is inside a segmentation, its enclosed area will be subtracted from the segmentation. When the segment is outside a segmentation, its enclosed area it will be added to the segmentation. The algorithm is described in full length in Tobias Heimann's diploma thesis (MBI Technical Report 145, p. 37 - 40). */ int oaSize = 1000000; // if we need a fixed number, then let it be big int* _ofsArray = new int[ oaSize ]; for (int i=0; i segData; segData.reserve( 16 ); Contour* contour3D = const_cast(m_Contour.GetPointer()); ContourUtils::Pointer contourUtils = ContourUtils::New(); Contour::Pointer projectedContour = contourUtils->ProjectContourTo2DSlice( m_WorkingImage, contour3D, true, false ); if (projectedContour.IsNull()) { delete[] _ofsArray; return; } if (projectedContour->GetNumberOfPoints() < 2) { delete[] _ofsArray; return; } // convert the projected contour into a ipSegmentation format mitkIpInt4_t* _points = new mitkIpInt4_t[2 * projectedContour->GetNumberOfPoints()]; const Contour::PathType::VertexListType* pointsIn2D = projectedContour->GetContourPath()->GetVertexList(); unsigned int index(0); for ( Contour::PathType::VertexListType::const_iterator iter = pointsIn2D->begin(); iter != pointsIn2D->end(); ++iter, ++index ) { _points[ 2 * index + 0 ] = static_cast( (*iter)[0] + 0.5 ); _points[ 2 * index + 1 ] = static_cast( (*iter)[1] + 0.5 ); } // store ofsets of the drawn line in array int _ofsNum = 0; unsigned int num = projectedContour->GetNumberOfPoints(); int lastOfs = -1; for (unsigned int i=0; i=pic->n[0]) x = pic->n[0]-0.5; if (y<0) y=0.5; else if (y>=pic->n[1]) y = pic->n[1]-0.5; // ok, now store safe ofs int ofs = (int)(x) + pic->n[0]*((int)(y)); x += dx; y += dy; if (ofs != lastOfs) { _ofsArray[_ofsNum++] = ofs; lastOfs = ofs; } } } if (_ofsNum == 0) { // contour was completely outside the binary image delete[] _ofsArray; delete[] _points; return; } ipMITKSegmentationTYPE* picdata = static_cast(pic->data); // divide line in logical segments: int numSegments = 0; ipMITKSegmentationTYPE state = *(picdata + _ofsArray[0]); int ofsP = 1; int modifyStart, modifyEnd; // start of first and end of last segment bool nextSegment; segData.clear(); do { nextSegment = false; while (ofsP<_ofsNum && *(picdata + _ofsArray[ofsP])==state) ofsP++; if (ofsP<_ofsNum) { int lineStart = ofsP-1; if (numSegments==0) modifyStart = ofsP; state = *(picdata + _ofsArray[ofsP]); while (ofsP<_ofsNum && *(picdata + _ofsArray[ofsP])==state) ofsP++; if (ofsP<_ofsNum) { int lineEnd = ofsP; modifyEnd = lineEnd; nextSegment = true; // now we've got a valid segment from lineStart to lineEnd TSegData thisSegData; thisSegData.lineStart = lineStart; thisSegData.lineEnd = lineEnd; thisSegData.modified = modifySegment( lineStart, lineEnd, state, pic, _ofsArray ); segData.push_back( thisSegData ); numSegments++; } } } while (nextSegment); for (int segNr=0; segNr < numSegments; segNr++) { // draw line if modified: if ( segData[segNr].modified ) { for (int i=segData[segNr].lineStart+1; in[0]*pic->n[1]; for (oneContourOffset = 0; oneContourOffset < imageSize; oneContourOffset++) if ( ((ipMITKSegmentationTYPE*) pic->data)[oneContourOffset]> 0) break; float* contourPoints = ipMITKSegmentationGetContour8N( pic, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc if (contourPoints) { // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < numberOfContourPoints; ++index) { newPoint[0] = contourPoints[ 2 * index + 0 ]; newPoint[1] = contourPoints[ 2 * index + 1]; newPoint[2] = 0; contourInImageIndexCoordinates->AddVertex( newPoint ); } free(contourPoints); ContourUtils::Pointer contourUtils = ContourUtils::New(); contourUtils->FillContourInSlice( contourInImageIndexCoordinates, m_WorkingImage ); } delete[] _ofsArray; delete[] _points; } bool mitk::CorrectorAlgorithm::modifySegment( int lineStart, int lineEnd, ipMITKSegmentationTYPE state, mitkIpPicDescriptor *pic, int* _ofsArray ) { // offsets for pixels right, top, left, bottom int nbDelta4[4]; nbDelta4[0]=1; nbDelta4[1]=pic->n[0]; nbDelta4[1]*=-1; // necessary because of unsigned declaration of pic->n nbDelta4[2]=-1; nbDelta4[3]=pic->n[0]; // offsets for pixels right, top-right, top, top-left left, bottom-left, bottom, bottom-right int nbDelta8[8]; nbDelta8[0] = 1; nbDelta8[1] = nbDelta4[1]+1; nbDelta8[2] = nbDelta4[1]; nbDelta8[3] = nbDelta4[1]-1; nbDelta8[4] = -1; nbDelta8[5] = nbDelta4[3]-1; nbDelta8[6] = nbDelta4[3]; nbDelta8[7] = nbDelta4[3]+1; ipMITKSegmentationTYPE* picdata = static_cast(pic->data); ipMITKSegmentationTYPE saveStart = *(picdata + _ofsArray[lineStart]); ipMITKSegmentationTYPE saveEnd = *(picdata + _ofsArray[lineEnd]); ipMITKSegmentationTYPE newState = ((!state)&1) + 2; // probably equal to: ipMITKSegmentationTYPE newState = 3 - state; // make two copies of pic: mitkIpPicDescriptor *seg1 = mitkIpPicClone( pic ); mitkIpPicDescriptor *seg2 = mitkIpPicClone( pic ); int i; // mark line in original for (i=lineStart; i<=lineEnd; i++) { *(picdata + _ofsArray[i]) = 3; } // mark the first side in copy 1: bool firstPix = true; bool modified; int line = pic->n[0]; // #pixels in line int maxOfs = (int)(line * pic->n[1]); // #pixels in slice for (i=lineStart+1; i= maxOfs // below last line ) continue; ipMITKSegmentationTYPE nbVal = *(picdata + nbOfs); ipMITKSegmentationTYPE destVal = *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs); if (nbVal!=3 && destVal!=newState) { // get only neigbhours that are not part of the line itself if (firstPix) { *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs) = newState; // this one is used to mark the side! firstPix = false; modified = true; } else { int tnb = 0; while ( tnb < 4 && ((nbOfs + nbDelta4[tnb]) >= 0) && ((nbOfs + nbDelta4[tnb]) < maxOfs) && *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs + nbDelta4[tnb]) != newState ) tnb++; if (tnb < 4 && ((nbOfs + nbDelta4[tnb]) >= 0) && ((nbOfs + nbDelta4[tnb]) < maxOfs) ) { *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs) = newState; // we've got a buddy close modified = true; } } } } } while (modified); } // mark the other side in copy 2: for (i=lineStart+1; i= maxOfs // below last line ) continue; ipMITKSegmentationTYPE lineVal = *(picdata + nbOfs); ipMITKSegmentationTYPE side1Val = *(((ipMITKSegmentationTYPE*)seg1->data) + nbOfs); if (lineVal != 3 && side1Val != newState) { *(((ipMITKSegmentationTYPE*)seg2->data) + nbOfs) = newState; } } } // take care of line ends for multiple segments: *(((ipMITKSegmentationTYPE*)seg1->data) + _ofsArray[lineStart]) = newState; *(((ipMITKSegmentationTYPE*)seg1->data) + _ofsArray[lineEnd]) = newState; *(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[lineStart]) = newState; *(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[lineEnd]) = newState; // replace regions: newState = (!state)&1; int sizeRegion1 = 0, sizeRegion2 = 0; for (i=lineStart+1; idata) + _ofsArray[i]) != newState) { sizeRegion1 += ipMITKSegmentationReplaceRegion4N( seg1, _ofsArray[i], newState ); } if (*(((ipMITKSegmentationTYPE*)seg2->data) + _ofsArray[i]) != newState) { sizeRegion2 += ipMITKSegmentationReplaceRegion4N( seg2, _ofsArray[i], newState ); } } // combine image: //printf( "Size Region1 = %8i Size Region2 = %8i\n", sizeRegion1, sizeRegion2 ); int sizeDif; ipMITKSegmentationTYPE *current, *segSrc; if (sizeRegion1 < sizeRegion2) { segSrc = (ipMITKSegmentationTYPE*)seg1->data; sizeDif = sizeRegion2 - sizeRegion1; } else { segSrc = (ipMITKSegmentationTYPE*)seg2->data; sizeDif = sizeRegion1 - sizeRegion2; } modified = false; if (sizeDif > 2*(lineEnd-lineStart)) { // decision is safe enough: ipMITKSegmentationTYPE *end = picdata + (pic->n[0]*pic->n[1]); for (current = picdata; current we calculate a diff image using ITK, switching for the correct type of originalImage */ m_DifferenceImage = NULL; Image::Pointer tmpPtr = originalImage; AccessFixedDimensionByItk_1( tmpPtr, ItkCalculateDifferenceImage, 2, modifiedImage ); } template void mitk::CorrectorAlgorithm::ItkCalculateDifferenceImage( itk::Image* originalImage, Image* modifiedMITKImage ) { typedef itk::Image ModifiedImageType; typedef itk::Image DiffImageType; typedef itk::ImageRegionConstIterator< itk::Image > OriginalSliceIteratorType; typedef itk::ImageRegionConstIterator< ModifiedImageType > ModifiedSliceIteratorType; typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType; typename ModifiedImageType::Pointer modifiedImage; CastToItkImage( modifiedMITKImage, modifiedImage ); // create new image as a copy of the input // this new image is the output of this filter class typename DiffImageType::Pointer diffImage; m_DifferenceImage = Image::New(); PixelType pixelType( typeid(short signed int) ); m_DifferenceImage->Initialize( pixelType, 2, modifiedMITKImage->GetDimensions() ); CastToItkImage( m_DifferenceImage, diffImage ); // iterators over both input images (original and modified) and the output image (diff) ModifiedSliceIteratorType modifiedIterator( modifiedImage, diffImage->GetLargestPossibleRegion() ); OriginalSliceIteratorType originalIterator( originalImage, diffImage->GetLargestPossibleRegion() ); DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); modifiedIterator.GoToBegin(); originalIterator.GoToBegin(); diffIterator.GoToBegin(); while ( !diffIterator.IsAtEnd() ) { short signed int difference = static_cast( static_cast(modifiedIterator.Get()) - static_cast(originalIterator.Get())); // not good for bigger values ?! diffIterator.Set( difference ); ++modifiedIterator; ++originalIterator; ++diffIterator; } } diff --git a/Modules/MitkExt/Algorithms/mitkDiffImageApplier.cpp b/Modules/MitkExt/Algorithms/mitkDiffImageApplier.cpp index 97336e3356..3a62b82191 100644 --- a/Modules/MitkExt/Algorithms/mitkDiffImageApplier.cpp +++ b/Modules/MitkExt/Algorithms/mitkDiffImageApplier.cpp @@ -1,328 +1,329 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkDiffImageApplier.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkApplyDiffImageOperation.h" #include "mitkRenderingManager.h" #include "mitkSegmentationInterpolationController.h" #include "mitkImageTimeSelector.h" #include #include mitk::DiffImageApplier::DiffImageApplier() { } mitk::DiffImageApplier::~DiffImageApplier() { } void mitk::DiffImageApplier::ExecuteOperation( Operation* operation ) { ApplyDiffImageOperation* imageOperation = dynamic_cast( operation ); if ( imageOperation // we actually have the kind of operation that we can handle && imageOperation->IsImageStillValid() ) // AND the image is not yet deleted { m_Image = imageOperation->GetImage(); Image::Pointer image3D = m_Image; // will be changed later in case of 3D+t m_SliceDifferenceImage = imageOperation->GetDiffImage(); m_TimeStep = imageOperation->GetTimeStep(); m_Factor = imageOperation->GetFactor(); if ( m_SliceDifferenceImage->GetDimension() == 2 ) { m_SliceIndex = imageOperation->GetSliceIndex(); m_SliceDimension = imageOperation->GetSliceDimension(); switch (m_SliceDimension) { default: case 2: m_Dimension0 = 0; m_Dimension1 = 1; break; case 1: m_Dimension0 = 0; m_Dimension1 = 2; break; case 0: m_Dimension0 = 1; m_Dimension1 = 2; break; } if ( m_SliceDifferenceImage->GetDimension() != 2 || (m_Image->GetDimension() < 3 || m_Image->GetDimension() > 4) || m_SliceDifferenceImage->GetDimension(0) != m_Image->GetDimension(m_Dimension0) || m_SliceDifferenceImage->GetDimension(1) != m_Image->GetDimension(m_Dimension1) || m_SliceIndex >= m_Image->GetDimension(m_SliceDimension) ) { itkExceptionMacro("Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this."); return; } if ( m_Image->GetDimension() == 4 ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( m_Image ); timeSelector->SetTimeNr( m_TimeStep ); timeSelector->UpdateLargestPossibleRegion(); image3D = timeSelector->GetOutput(); } // this will do a long long if/else to find out both pixel types AccessFixedDimensionByItk( image3D, ItkImageSwitch2DDiff, 3 ); if ( m_Factor == 1 || m_Factor == -1 ) { if ( m_Factor == -1 ) { // multiply diff pixels by factor and then send this diff slice AccessFixedDimensionByItk( m_SliceDifferenceImage, ItkInvertPixelValues, 2 ); } // just send the diff to SegmentationInterpolationController SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage( m_Image ); if (interpolator) { interpolator->BlockModified(true); interpolator->SetChangedSlice( m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep ); } m_Image->Modified(); if (interpolator) { interpolator->BlockModified(false); } if ( m_Factor == -1 ) // return to normal values { AccessFixedDimensionByItk( m_SliceDifferenceImage, ItkInvertPixelValues, 2 ); } } else // no trivial case, too lazy to do something else { m_Image->Modified(); // check if interpolation is called. prefer to send diff directly } RenderingManager::GetInstance()->RequestUpdateAll(); } else if ( m_SliceDifferenceImage->GetDimension() == 3 ) { // ... if ( m_SliceDifferenceImage->GetDimension(0) != m_Image->GetDimension(0) || m_SliceDifferenceImage->GetDimension(1) != m_Image->GetDimension(1) || m_SliceDifferenceImage->GetDimension(2) != m_Image->GetDimension(2) || m_TimeStep >= m_Image->GetDimension(3) ) { itkExceptionMacro("Diff image size differs from original image size. Sorry, cannot work like this."); return; } if ( m_Image->GetDimension() == 4 ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( m_Image ); timeSelector->SetTimeNr( m_TimeStep ); timeSelector->UpdateLargestPossibleRegion(); image3D = timeSelector->GetOutput(); } // this will do a long long if/else to find out both pixel types AccessFixedDimensionByItk( image3D, ItkImageSwitch3DDiff, 3 ); if ( m_Factor == 1 || m_Factor == -1 ) { if ( m_Factor == -1 ) { // multiply diff pixels by factor and then send this diff slice AccessFixedDimensionByItk( m_SliceDifferenceImage, ItkInvertPixelValues, 3 ); } // just send the diff to SegmentationInterpolationController SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage( m_Image ); if (interpolator) { interpolator->BlockModified(true); interpolator->SetChangedVolume( m_SliceDifferenceImage, m_TimeStep ); } m_Image->Modified(); if (interpolator) { interpolator->BlockModified(false); } if ( m_Factor == -1 ) // return to normal values { AccessFixedDimensionByItk( m_SliceDifferenceImage, ItkInvertPixelValues, 3 ); } } else // no trivial case, too lazy to do something else { m_Image->Modified(); // check if interpolation is called. prefer to send diff directly } RenderingManager::GetInstance()->RequestUpdateAll(); } else { itkExceptionMacro("Diff image must be 2D or 3D. Sorry, cannot work like this."); return; } } m_Image = NULL; m_SliceDifferenceImage = NULL; } mitk::DiffImageApplier* mitk::DiffImageApplier::GetInstanceForUndo() { static DiffImageApplier::Pointer s_Instance = DiffImageApplier::New(); return s_Instance; } // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h #define myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \ if ( typeId == typeid(pixeltype) ) \ { \ typedef itk::Image ImageType; \ typedef mitk::ImageToItk ImageToItkType; \ itk::SmartPointer imagetoitk = ImageToItkType::New(); \ imagetoitk->SetInput(mitkImage); \ imagetoitk->Update(); \ itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \ } #define myMITKDiffImageApplierFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \ { \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \ myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \ } template void mitk::DiffImageApplier::ItkImageSwitch2DDiff( itk::Image* itkImage ) { const std::type_info& typeId=*(m_SliceDifferenceImage->GetPixelType().GetTypeId()); myMITKDiffImageApplierFilterAccessAllTypesByItk( m_SliceDifferenceImage, ItkImageProcessing2DDiff, 2, itkImage ); } template void mitk::DiffImageApplier::ItkImageSwitch3DDiff( itk::Image* itkImage ) { const std::type_info& typeId=*(m_SliceDifferenceImage->GetPixelType().GetTypeId()); myMITKDiffImageApplierFilterAccessAllTypesByItk( m_SliceDifferenceImage, ItkImageProcessing3DDiff, 3, itkImage ); } template void mitk::DiffImageApplier::ItkImageProcessing2DDiff( itk::Image* diffImage, itk::Image* outputImage ) { typedef itk::Image DiffImageType; typedef itk::Image VolumeImageType; typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< DiffImageType > DiffSliceIteratorType; typename VolumeImageType::RegionType sliceInVolumeRegion; sliceInVolumeRegion = outputImage->GetLargestPossibleRegion(); sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion ); outputIterator.SetFirstDirection(m_Dimension0); outputIterator.SetSecondDirection(m_Dimension1); DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); // iterate over output slice (and over input slice simultaneously) outputIterator.GoToBegin(); diffIterator.GoToBegin(); while ( !outputIterator.IsAtEnd() ) { while ( !outputIterator.IsAtEndOfSlice() ) { while ( !outputIterator.IsAtEndOfLine() ) { TPixel2 newValue = outputIterator.Get() + (TPixel2) ((double)diffIterator.Get() * m_Factor); outputIterator.Set( newValue ); ++outputIterator; ++diffIterator; } outputIterator.NextLine(); } outputIterator.NextSlice(); } } template void mitk::DiffImageApplier::ItkImageProcessing3DDiff( itk::Image* diffImage, itk::Image* outputImage ) { typedef itk::Image DiffImageType; typedef itk::Image VolumeImageType; typedef itk::ImageRegionIterator< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< DiffImageType > DiffSliceIteratorType; OutputSliceIteratorType outputIterator( outputImage, outputImage->GetLargestPossibleRegion() ); DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); // iterate over output slice (and over input slice simultaneously) outputIterator.GoToBegin(); diffIterator.GoToBegin(); while ( !outputIterator.IsAtEnd() ) { TPixel2 newValue = outputIterator.Get() + (TPixel2) ((double)diffIterator.Get() * m_Factor); outputIterator.Set( newValue ); ++outputIterator; ++diffIterator; } } template void mitk::DiffImageApplier::ItkInvertPixelValues( itk::Image* itkImage ) { typedef itk::ImageRegionIterator< itk::Image > IteratorType; IteratorType iter( itkImage, itkImage->GetLargestPossibleRegion() ); iter.GoToBegin(); while ( !iter.IsAtEnd() ) { iter.Set( -( iter.Get() ) ); ++iter; } } diff --git a/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp b/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp index 8361c05216..d7d47e5bf0 100644 --- a/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp @@ -1,391 +1,392 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include #include #include #include #include #include #include #if (VTK_MAJOR_VERSION < 5) #include #endif #include #include #include +#include #include #include mitk::LabeledImageToSurfaceFilter::LabeledImageToSurfaceFilter() : m_GaussianStandardDeviation(1.5), m_GenerateAllLabels(true), m_Label(1), m_BackgroundLabel(0) { } mitk::LabeledImageToSurfaceFilter::~LabeledImageToSurfaceFilter() { } void mitk::LabeledImageToSurfaceFilter::GenerateOutputInformation() { Superclass::GenerateOutputInformation(); // // check which labels are available in the image // m_AvailableLabels = this->GetAvailableLabels(); m_IdxToLabels.clear(); // // if we don't want to generate surfaces for all labels // we have to remove all labels except m_Label and m_BackgroundLabel // from the list of available labels // if ( ! m_GenerateAllLabels ) { LabelMapType tmp; LabelMapType::iterator it; it = m_AvailableLabels.find( m_Label ); if ( it != m_AvailableLabels.end() ) tmp[m_Label] = it->second; else tmp[m_Label] = 0; it = m_AvailableLabels.find( m_BackgroundLabel ); if ( it != m_AvailableLabels.end() ) tmp[m_BackgroundLabel] = it->second; else tmp[m_BackgroundLabel] = 0; m_AvailableLabels = tmp; } // // check for the number of labels: if the whole image is filled, no // background is available and thus the numberOfOutpus is equal to the // number of available labels in the image (which is a special case). // If we have background voxels, the number of outputs is one less than // then number of available labels. // unsigned int numberOfOutputs = 0; if ( m_AvailableLabels.find( m_BackgroundLabel ) == m_AvailableLabels.end() ) numberOfOutputs = m_AvailableLabels.size(); else numberOfOutputs = m_AvailableLabels.size() - 1; if ( numberOfOutputs == 0 ) { itkWarningMacro("Number of outputs == 0"); } // // determine the number of time steps of the input image // mitk::Image* image = ( mitk::Image* )GetInput(); unsigned int numberOfTimeSteps = image->GetTimeSlicedGeometry()->GetTimeSteps(); // // set the number of outputs to the number of labels used. // initialize the output surfaces accordingly (incl. time steps) // this->SetNumberOfOutputs( numberOfOutputs ); this->SetNumberOfRequiredOutputs( numberOfOutputs ); for ( unsigned int i = 0 ; i < numberOfOutputs; ++i ) { if ( ! this->GetOutput( i ) ) { mitk::Surface::Pointer output = static_cast( this->MakeOutput(0).GetPointer() ); assert ( output.IsNotNull() ); output->Expand( numberOfTimeSteps ); this->SetNthOutput( i, output.GetPointer() ); } } } void mitk::LabeledImageToSurfaceFilter::GenerateData() { mitk::Image* image = ( mitk::Image* )GetInput(); if ( image == NULL ) { itkWarningMacro("Image is NULL"); return; } mitk::Image::RegionType outputRegion = image->GetRequestedRegion(); m_IdxToLabels.clear(); if ( this->GetNumberOfOutputs() == 0 ) return; // // traverse the known labels and create surfaces for them. // unsigned int currentOutputIndex = 0; for ( LabelMapType::iterator it = m_AvailableLabels.begin() ; it != m_AvailableLabels.end() ; ++it ) { if ( it->first == m_BackgroundLabel ) continue; if ( ( it->second == 0 ) && m_GenerateAllLabels ) continue; assert ( currentOutputIndex < this->GetNumberOfOutputs() ); mitk::Surface::Pointer surface = this->GetOutput( currentOutputIndex ); assert( surface.IsNotNull() ); int tstart=outputRegion.GetIndex(3); int tmax=tstart+outputRegion.GetSize(3); //GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloet int t; for( t=tstart; t < tmax; ++t) { vtkImageData *vtkimagedata = image->GetVtkImageData( t ); CreateSurface( t,vtkimagedata,surface.GetPointer(), it->first ); } m_IdxToLabels[ currentOutputIndex ] = it->first; currentOutputIndex++; } } void mitk::LabeledImageToSurfaceFilter::CreateSurface( int time, vtkImageData *vtkimage, mitk::Surface * surface, mitk::LabeledImageToSurfaceFilter::LabelType label ) { vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New(); indexCoordinatesImageFilter->SetInput(vtkimage); indexCoordinatesImageFilter->SetOutputOrigin(0.0,0.0,0.0); vtkImageThreshold* threshold = vtkImageThreshold::New(); threshold->SetInput( indexCoordinatesImageFilter->GetOutput() ); //indexCoordinatesImageFilter->Delete(); threshold->SetInValue( 100 ); threshold->SetOutValue( 0 ); threshold->ThresholdBetween( label, label ); threshold->SetOutputScalarTypeToUnsignedChar(); threshold->ReleaseDataFlagOn(); vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New(); gaussian->SetInput( threshold->GetOutput() ); //threshold->Delete(); gaussian->SetDimensionality( 3 ); gaussian->SetRadiusFactor( 0.49 ); gaussian->SetStandardDeviation( GetGaussianStandardDeviation() ); gaussian->ReleaseDataFlagOn(); gaussian->UpdateInformation(); gaussian->Update(); //MarchingCube -->create Surface vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New(); skinExtractor->ReleaseDataFlagOn(); skinExtractor->SetInput(gaussian->GetOutput());//RC++ indexCoordinatesImageFilter->Delete(); skinExtractor->SetValue(0, 50); vtkPolyData *polydata; polydata = skinExtractor->GetOutput(); polydata->Register(NULL);//RC++ skinExtractor->Delete(); if (m_Smooth) { vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New(); //read poly1 (poly1 can be the original polygon, or the decimated polygon) smoother->SetInput(polydata);//RC++ smoother->SetNumberOfIterations( m_SmoothIteration ); smoother->SetRelaxationFactor( m_SmoothRelaxation ); smoother->SetFeatureAngle( 60 ); smoother->FeatureEdgeSmoothingOff(); smoother->BoundarySmoothingOff(); smoother->SetConvergence( 0 ); polydata->Delete();//RC-- polydata = smoother->GetOutput(); polydata->Register(NULL);//RC++ smoother->Delete(); } // //#if (VTK_MAJOR_VERSION >= 5) // if (m_Decimate == Decimate ) // { // MITK_ERROR << "vtkDecimate not available for VTK 5.0 and above."; // MITK_ERROR << " Using vtkDecimatePro instead." << std::endl; // m_Decimate = DecimatePro; // } //#endif //decimate = to reduce number of polygons if(m_Decimate==DecimatePro) { vtkDecimatePro *decimate = vtkDecimatePro::New(); decimate->SplittingOff(); decimate->SetErrorIsAbsolute(5); decimate->SetFeatureAngle(30); decimate->PreserveTopologyOn(); decimate->BoundaryVertexDeletionOff(); decimate->SetDegree(10); //std-value is 25! decimate->SetInput(polydata);//RC++ decimate->SetTargetReduction(m_TargetReduction); decimate->SetMaximumError(0.002); polydata->Delete();//RC-- polydata = decimate->GetOutput(); polydata->Register(NULL);//RC++ decimate->Delete(); } #if (VTK_MAJOR_VERSION < 5) else if (m_Decimate==Decimate) { vtkDecimate *decimate = vtkDecimate::New(); decimate->SetInput( polydata ); decimate->PreserveTopologyOn(); decimate->BoundaryVertexDeletionOff(); decimate->SetTargetReduction( m_TargetReduction ); polydata->Delete();//RC-- polydata = decimate->GetOutput(); polydata->Register(NULL);//RC++ decimate->Delete(); } #endif polydata->Update(); polydata->SetSource(NULL); if(polydata->GetNumberOfPoints() > 0) { mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing(); vtkPoints * points = polydata->GetPoints(); vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New(); GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix); double (*matrix)[4] = vtkmatrix->Element; unsigned int i,j; for(i=0;i<3;++i) for(j=0;j<3;++j) matrix[i][j]/=spacing[j]; unsigned int n = points->GetNumberOfPoints(); vtkFloatingPointType point[3]; for (i = 0; i < n; i++) { points->GetPoint(i, point); mitkVtkLinearTransformPoint(matrix,point,point); points->SetPoint(i, point); } vtkmatrix->Delete(); } surface->SetVtkPolyData(polydata, time); polydata->UnRegister(NULL); gaussian->Delete(); threshold->Delete(); } template < typename TPixel, unsigned int VImageDimension > void GetAvailableLabelsInternal( itk::Image* image, mitk::LabeledImageToSurfaceFilter::LabelMapType& availableLabels ) { typedef itk::Image ImageType; typedef itk::ImageRegionIterator< ImageType > ImageRegionIteratorType; availableLabels.clear(); ImageRegionIteratorType it( image, image->GetLargestPossibleRegion() ); it.GoToBegin(); mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt; while( ! it.IsAtEnd() ) { labelIt = availableLabels.find( ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ); if ( labelIt == availableLabels.end() ) { availableLabels[ ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ] = 1; } else { labelIt->second += 1; } ++it; } } #define InstantiateAccessFunction_GetAvailableLabelsInternal(pixelType, dim) \ template void GetAvailableLabelsInternal(itk::Image*, mitk::LabeledImageToSurfaceFilter::LabelMapType&); InstantiateAccessFunctionForFixedDimension(GetAvailableLabelsInternal, 3); mitk::LabeledImageToSurfaceFilter::LabelMapType mitk::LabeledImageToSurfaceFilter::GetAvailableLabels() { mitk::Image::Pointer image = ( mitk::Image* )GetInput(); LabelMapType availableLabels; AccessFixedDimensionByItk_1( image, GetAvailableLabelsInternal, 3, availableLabels ); return availableLabels; } void mitk::LabeledImageToSurfaceFilter::CreateSurface(int, vtkImageData*, mitk::Surface*, const ScalarType) { itkWarningMacro( "This function should never be called!" ); assert(false); } mitk::LabeledImageToSurfaceFilter::LabelType mitk::LabeledImageToSurfaceFilter::GetLabelForNthOutput( const unsigned int& idx ) { IdxToLabelMapType::iterator it = m_IdxToLabels.find( idx ); if ( it != m_IdxToLabels.end() ) { return it->second; } else { itkWarningMacro( "Unknown index encountered: " << idx << ". There are " << this->GetNumberOfOutputs() << " outputs available." ); return itk::NumericTraits::max(); } } mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForNthOutput( const unsigned int& i ) { return GetVolumeForLabel( GetLabelForNthOutput( i ) ); } mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForLabel( const mitk::LabeledImageToSurfaceFilter::LabelType& label ) { // get the image spacing mitk::Image* image = ( mitk::Image* )GetInput(); const float* spacing = image->GetSlicedGeometry()->GetFloatSpacing(); // get the number of voxels encountered for the given label, // calculate the volume and return it. LabelMapType::iterator it = m_AvailableLabels.find( label ); if ( it != m_AvailableLabels.end() ) { return static_cast(it->second) * ( spacing[0] * spacing[1] * spacing[2] / 1000.0f ); } else { itkWarningMacro( "Unknown label encountered: " << label ); return 0.0; } } diff --git a/Modules/MitkExt/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp b/Modules/MitkExt/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp index a04d8e822b..37b9c6bca3 100644 --- a/Modules/MitkExt/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp @@ -1,490 +1,491 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2010-01-14 14:20:26 +0100 (Do, 14 Jan 2010) $ Version: $Revision: 21047 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkOverwriteDirectedPlaneImageFilter.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkSegmentationInterpolationController.h" #include "mitkApplyDiffImageOperation.h" #include "mitkOperationEvent.h" #include "mitkInteractionConst.h" #include "mitkUndoController.h" #include "mitkDiffImageApplier.h" #include "mitkImageTimeSelector.h" #include #include mitk::OverwriteDirectedPlaneImageFilter::OverwriteDirectedPlaneImageFilter() :m_PlaneGeometry(0), m_ImageGeometry3D(0), m_TimeStep(0), m_Dimension0(0), m_Dimension1(1), m_CreateUndoInformation(false) { } mitk::OverwriteDirectedPlaneImageFilter::~OverwriteDirectedPlaneImageFilter() { } void mitk::OverwriteDirectedPlaneImageFilter::GenerateData() { // // this is the place to implement the major part of undo functionality (bug #491) // here we have to create undo/do operations // // WHO is the operation actor? This object may not be destroyed ever (design of undo stack)! // -> some singleton method of this filter? // // neccessary additional objects: // - something that executes the operations // - the operation class (must hold a binary diff or something) // - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations from the undo stack) // //Image::ConstPointer input = ImageToImageFilter::GetInput(0); Image::ConstPointer input3D = ImageToImageFilter::GetInput(0); //Image::ConstPointer slice = m_SliceImage; if ( input3D.IsNull() || m_SliceImage.IsNull() ) return; if ( input3D->GetDimension() == 4 ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( input3D ); timeSelector->SetTimeNr( m_TimeStep ); timeSelector->UpdateLargestPossibleRegion(); input3D = timeSelector->GetOutput(); } m_ImageGeometry3D = input3D->GetGeometry(); /* if ( m_SliceDifferenceImage.IsNull() || m_SliceDifferenceImage->GetDimension(0) != m_SliceImage->GetDimension(0) || m_SliceDifferenceImage->GetDimension(1) != m_SliceImage->GetDimension(1) ) { m_SliceDifferenceImage = mitk::Image::New(); mitk::PixelType pixelType( typeid(short signed int) ); m_SliceDifferenceImage->Initialize( pixelType, 2, m_SliceImage->GetDimensions() ); } */ //MITK_INFO << "Overwriting slice " << m_SliceIndex << " in dimension " << m_SliceDimension << " at time step " << m_TimeStep << std::endl; // this will do a long long if/else to find out both pixel types /*AccessFixedDimensionByItk( input3D, ItkImageSwitch, 3 );*/ AccessFixedDimensionByItk( input3D, ItkSliceOverwriting, 3 ); //SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage( input3D ); //if (interpolator) //{ // interpolator->BlockModified(true); // //interpolator->SetChangedSlice( m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep ); //} /* if ( m_CreateUndoInformation ) { // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image ApplyDiffImageOperation* doOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); ApplyDiffImageOperation* undoOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); undoOp->SetFactor( -1.0 ); OperationEvent* undoStackItem = new OperationEvent( DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, this->EventDescription(m_SliceDimension, m_SliceIndex, m_TimeStep) ); UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); } */ // this image is modified (good to know for the renderer) input3D->Modified(); /*if (interpolator) { interpolator->BlockModified(false); }*/ } template void mitk::OverwriteDirectedPlaneImageFilter::ItkSliceOverwriting( itk::Image* input3D ) { typedef itk::Image SliceImageType; typedef itk::Image VolumeImageType; typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< SliceImageType > SliceIteratorType; typename SliceImageType::Pointer sliceImage = SliceImageType::New(); CastToItkImage(m_SliceImage,sliceImage); SliceIteratorType sliceIterator( sliceImage, sliceImage->GetLargestPossibleRegion() ); sliceIterator.GoToBegin(); Point3D currentPointIn2D; Point3D worldPointIn3D; //Here we just iterate over the slice which must be written into the 3D volumen and set the corresponding pixel in our 3D volume while ( !sliceIterator.IsAtEnd() ) { currentPointIn2D[0] = sliceIterator.GetIndex()[0]+0.5; currentPointIn2D[1] = sliceIterator.GetIndex()[1]+0.5; currentPointIn2D[2] = 0; m_PlaneGeometry->IndexToWorld( currentPointIn2D, worldPointIn3D ); typename itk::Image::IndexType outputIndex; m_ImageGeometry3D->WorldToIndex( worldPointIn3D, outputIndex ); // Only access ITK image if it's inside if ( m_ImageGeometry3D->IsIndexInside( outputIndex ) ) { input3D->SetPixel( outputIndex, (TPixel)sliceIterator.Get() ); } ++sliceIterator; } } /****TEST***/ //Maybe a bit more efficient but doesn`t already work. See also ExtractCirectedPlaneImageFilter //typename itk::Image::IndexType outputIndex; //if ( columns == extent[0] ) //{ ////If we are at the end of a row, then we have to go to the beginning of the next row //currentImagePointIn3D = origin; //currentImagePointIn3D += spacing[1]*bottom*currentPointIn2D[1]; //columns = 0; //m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); //} //else //{ //if ( columns != 0 ) //{ //currentImagePointIn3D += spacing[0]*right; //} //m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); //} //if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) //{ //outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); //} //else if (currentImagePointIn3D == origin) //{ //Point3D temp; //temp[0] = bottom[0]*spacing[0]*0.5; //temp[1] = bottom[1]*spacing[1]*0.5; //temp[2] = bottom[2]*spacing[2]*0.5; //origin[0] += temp[0]; //origin[1] += temp[1]; //origin[2] += temp[2]; //currentImagePointIn3D = origin; //m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); //if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) //{ //outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); //} //} //columns++; /****TEST ENDE****/ //* // // Offset the world coordinate by one pixel to compensate for // // index/world origin differences. // Point3D offsetIndex; // offsetIndex.Fill( 1 ); // Point3D offsetWorld; // offsetWorld.Fill( 0 ); // m_PlaneGeometry->IndexToWorld( offsetIndex, offsetWorld ); // // remove origin shift // const Point3D origin = m_PlaneGeometry->GetOrigin(); // offsetWorld[0] -= origin[0]; // offsetWorld[1] -= origin[1]; // offsetWorld[2] -= origin[2]; // // offset world coordinate // worldPointIn3D[ 0 ] += offsetWorld[0]; // worldPointIn3D[ 1 ] += offsetWorld[1]; // worldPointIn3D[ 2 ] += offsetWorld[2]; //*/ // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h /*#define myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \ // if ( typeId == typeid(pixeltype) ) \ //{ \ // typedef itk::Image ImageType; \ // typedef mitk::ImageToItk ImageToItkType; \ // itk::SmartPointer imagetoitk = ImageToItkType::New(); \ // imagetoitk->SetInput(mitkImage); \ // imagetoitk->Update(); \ // itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \ //} // //#define myMITKOverwriteDirectedPlaneImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \ //{ \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \ //}*/ // // //template //void mitk::OverwriteDirectedPlaneImageFilter::ItkImageSwitch( itk::Image* itkImage ) //{ // const std::type_info& typeId=*(m_SliceImage->GetPixelType().GetTypeId()); // // myMITKOverwriteDirectedPlaneImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageProcessing, 2, itkImage ); //} //template //void mitk::OverwriteDirectedPlaneImageFilter::ItkImageProcessing( itk::Image* inputImage, itk::Image* outputImage ) //{ // typedef itk::Image SliceImageType; // typedef itk::Image DiffImageType; // typedef itk::Image VolumeImageType; // // typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; // typedef itk::ImageRegionConstIterator< SliceImageType > InputSliceIteratorType; // //typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType; // // InputSliceIteratorType inputIterator( inputImage, inputImage->GetLargestPossibleRegion() ); // // //typename DiffImageType::Pointer diffImage; // //CastToItkImage( m_SliceDifferenceImage, diffImage ); // //DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); // // inputIterator.GoToBegin(); // //diffIterator.GoToBegin(); // // //TEST // Point3D origin = m_PlaneGeometry->GetOrigin(); // Vector3D right = m_PlaneGeometry->GetAxisVector(0); // Vector3D bottom = m_PlaneGeometry->GetAxisVector(1); // right.Normalize(); // bottom.Normalize(); // // Vector2D spacing = inputImage->GetSpacing(); // // Vector2D extentInMM; // extentInMM[0] = m_PlaneGeometry->GetExtentInMM(0); // extentInMM[1] = m_PlaneGeometry->GetExtentInMM(1); // // Vector2D extent; // extent[0] = m_PlaneGeometry->GetExtent(0); // extent[1] = m_PlaneGeometry->GetExtent(1); // //TEST ENDE // // Point3D currentPointIn2D, worldPointIn3D; // TPixel2 outputPixel = 0; // // int debugCounter( 0 ); // // std::ofstream geometryFile; // geometryFile.precision(30); // geometryFile.open("C:/Users/fetzer/Desktop/TEST/geometryFileOv.txt"); // // geometryFile<<"Offset: [ "<GetIndexToWorldTransform()->GetOffset()[0]<<", "<GetIndexToWorldTransform()->GetOffset()[1]<<", "<GetIndexToWorldTransform()->GetOffset()[2]<<" ]"<GetIndexToWorldTransform()->GetMatrix()<IndexToWorld( currentPointIn2D, worldPointIn3D ); // //typename itk::Image::IndexType outputIndex; // m_ImageGeometry3D->WorldToIndex( worldPointIn3D, outputIndex ); // // // Only access ITK image if it's inside // if ( m_ImageGeometry3D->IsIndexInside( outputIndex ) ) // { // //outputPixel = outputImage->GetPixel( outputIndex ); // outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); // /*if( inputIterator.Get() == mitk::paint::addPixelValue ) // { // outputImage->SetPixel( outputIndex, (TPixel2)( 1 ) ); // } // else if( inputIterator.Get() == mitk::paint::subPixelValue ) // { // outputImage->SetPixel( outputIndex, (TPixel2)( 0 ) ); // }*/ // } // ///****TEST***/ // ////typename itk::Image::IndexType outputIndex; // ////if ( columns == extent[0] ) ////{ //////If we are at the end of a row, then we have to go to the beginning of the next row ////currentImagePointIn3D = origin; ////currentImagePointIn3D += spacing[1]*bottom*currentPointIn2D[1]; //columns = 0; ////m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); ////} ////else ////{ ////if ( columns != 0 ) ////{ ////currentImagePointIn3D += spacing[0]*right; ////} ////m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); ////} // ////if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) ////{ ////outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); ////} ////else if (currentImagePointIn3D == origin) ////{ ////Point3D temp; ////temp[0] = bottom[0]*spacing[0]*0.5; ////temp[1] = bottom[1]*spacing[1]*0.5; ////temp[2] = bottom[2]*spacing[2]*0.5; ////origin[0] += temp[0]; ////origin[1] += temp[1]; ////origin[2] += temp[2]; ////currentImagePointIn3D = origin; ////m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); ////if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) ////{ ////outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); ////} ////} ////columns++; // ///****TEST ENDE****/ // ////* //// // Offset the world coordinate by one pixel to compensate for //// // index/world origin differences. //// Point3D offsetIndex; //// offsetIndex.Fill( 1 ); //// Point3D offsetWorld; //// offsetWorld.Fill( 0 ); //// m_PlaneGeometry->IndexToWorld( offsetIndex, offsetWorld ); //// // remove origin shift //// const Point3D origin = m_PlaneGeometry->GetOrigin(); //// offsetWorld[0] -= origin[0]; //// offsetWorld[1] -= origin[1]; //// offsetWorld[2] -= origin[2]; //// // offset world coordinate //// worldPointIn3D[ 0 ] += offsetWorld[0]; //// worldPointIn3D[ 1 ] += offsetWorld[1]; //// worldPointIn3D[ 2 ] += offsetWorld[2]; ////*/ // // Output index // // ////For the purpose of debug ////if( debugCounter%100 == 0) //////{ ////Point3D contIndex; ////m_ImageGeometry3D->WorldToIndex(worldPointIn3D,contIndex); ////overriderFile.precision(10); ////overriderFile<<"2D-Index: [ "<(inputIterator.Get() - outputPixel ) ); // oh oh, not good for bigger values // ++inputIterator; ////++debugCounter; // //++diffIterator; // } // /*overriderFile.close(); // overriderFileIndex.close();*/ // geometryFile.close(); // ///* // typename VolumeImageType::RegionType sliceInVolumeRegion; // // sliceInVolumeRegion = outputImage->GetLargestPossibleRegion(); // sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice // sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please // // OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion ); // outputIterator.SetFirstDirection(m_Dimension0); // outputIterator.SetSecondDirection(m_Dimension1); // // // iterate over output slice (and over input slice simultaneously) // outputIterator.GoToBegin(); // while ( !outputIterator.IsAtEnd() ) // { // while ( !outputIterator.IsAtEndOfSlice() ) // { // while ( !outputIterator.IsAtEndOfLine() ) // { // diffIterator.Set( static_cast(inputIterator.Get() - outputIterator.Get()) ); // oh oh, not good for bigger values // outputIterator.Set( (TPixel2) inputIterator.Get() ); // ++outputIterator; // ++inputIterator; // ++diffIterator; // } // outputIterator.NextLine(); // } // outputIterator.NextSlice(); // } // */ //} /* std::string mitk::OverwriteDirectedPlaneImageFilter::EventDescription( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ) { std::stringstream s; s << "Changed slice ("; switch (sliceDimension) { default: case 2: s << "T"; break; case 1: s << "C"; break; case 0: s << "S"; break; } s << " " << sliceIndex << " " << timeStep << ")"; return s.str(); } */ - \ No newline at end of file + diff --git a/Modules/MitkExt/Algorithms/mitkOverwriteSliceImageFilter.cpp b/Modules/MitkExt/Algorithms/mitkOverwriteSliceImageFilter.cpp index 58bd05baae..76d8bb8455 100644 --- a/Modules/MitkExt/Algorithms/mitkOverwriteSliceImageFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkOverwriteSliceImageFilter.cpp @@ -1,246 +1,247 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkOverwriteSliceImageFilter.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkSegmentationInterpolationController.h" #include "mitkApplyDiffImageOperation.h" #include "mitkOperationEvent.h" #include "mitkInteractionConst.h" #include "mitkUndoController.h" #include "mitkDiffImageApplier.h" #include "mitkImageTimeSelector.h" #include #include mitk::OverwriteSliceImageFilter::OverwriteSliceImageFilter() :m_SliceIndex(0), m_SliceDimension(0), m_TimeStep(0), m_Dimension0(0), m_Dimension1(1), m_CreateUndoInformation(false) { } mitk::OverwriteSliceImageFilter::~OverwriteSliceImageFilter() { } void mitk::OverwriteSliceImageFilter::GenerateData() { // // this is the place to implement the major part of undo functionality (bug #491) // here we have to create undo/do operations // // WHO is the operation actor? This object may not be destroyed ever (design of undo stack)! // -> some singleton method of this filter? // // neccessary additional objects: // - something that executes the operations // - the operation class (must hold a binary diff or something) // - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations from the undo stack) // Image::ConstPointer input = ImageToImageFilter::GetInput(0); Image::ConstPointer input3D = input; Image::ConstPointer slice = m_SliceImage; if ( input.IsNull() || slice.IsNull() ) return; switch (m_SliceDimension) { default: case 2: m_Dimension0 = 0; m_Dimension1 = 1; break; case 1: m_Dimension0 = 0; m_Dimension1 = 2; break; case 0: m_Dimension0 = 1; m_Dimension1 = 2; break; } if ( slice->GetDimension() < 2 || input->GetDimension() > 4 || slice->GetDimension(0) != input->GetDimension(m_Dimension0) || slice->GetDimension(1) != input->GetDimension(m_Dimension1) || m_SliceIndex >= input->GetDimension(m_SliceDimension) ) { itkExceptionMacro("Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this."); return; } if ( input->GetDimension() == 4 ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( input ); timeSelector->SetTimeNr( m_TimeStep ); timeSelector->UpdateLargestPossibleRegion(); input3D = timeSelector->GetOutput(); } if ( m_SliceDifferenceImage.IsNull() || m_SliceDifferenceImage->GetDimension(0) != m_SliceImage->GetDimension(0) || m_SliceDifferenceImage->GetDimension(1) != m_SliceImage->GetDimension(1) ) { m_SliceDifferenceImage = mitk::Image::New(); mitk::PixelType pixelType( typeid(short signed int) ); m_SliceDifferenceImage->Initialize( pixelType, 2, m_SliceImage->GetDimensions() ); } //MITK_INFO << "Overwriting slice " << m_SliceIndex << " in dimension " << m_SliceDimension << " at time step " << m_TimeStep << std::endl; // this will do a long long if/else to find out both pixel types AccessFixedDimensionByItk( input3D, ItkImageSwitch, 3 ); SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage( input ); if (interpolator) { interpolator->BlockModified(true); interpolator->SetChangedSlice( m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep ); } if ( m_CreateUndoInformation ) { // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image ApplyDiffImageOperation* doOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); ApplyDiffImageOperation* undoOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); undoOp->SetFactor( -1.0 ); OperationEvent* undoStackItem = new OperationEvent( DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, this->EventDescription(m_SliceDimension, m_SliceIndex, m_TimeStep) ); UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); } // this image is modified (good to know for the renderer) input->Modified(); if (interpolator) { interpolator->BlockModified(false); } } // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h #define myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \ if ( typeId == typeid(pixeltype) ) \ { \ typedef itk::Image ImageType; \ typedef mitk::ImageToItk ImageToItkType; \ itk::SmartPointer imagetoitk = ImageToItkType::New(); \ imagetoitk->SetInput(mitkImage); \ imagetoitk->Update(); \ itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \ } #define myMITKOverwriteSliceImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \ { \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \ } template void mitk::OverwriteSliceImageFilter::ItkImageSwitch( itk::Image* itkImage ) { const std::type_info& typeId=*(m_SliceImage->GetPixelType().GetTypeId()); myMITKOverwriteSliceImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageProcessing, 2, itkImage ); } template void mitk::OverwriteSliceImageFilter::ItkImageProcessing( itk::Image* inputImage, itk::Image* outputImage ) { typedef itk::Image SliceImageType; typedef itk::Image DiffImageType; typedef itk::Image VolumeImageType; typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< SliceImageType > InputSliceIteratorType; typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType; typename VolumeImageType::RegionType sliceInVolumeRegion; sliceInVolumeRegion = outputImage->GetLargestPossibleRegion(); sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion ); outputIterator.SetFirstDirection(m_Dimension0); outputIterator.SetSecondDirection(m_Dimension1); InputSliceIteratorType inputIterator( inputImage, inputImage->GetLargestPossibleRegion() ); typename DiffImageType::Pointer diffImage; CastToItkImage( m_SliceDifferenceImage, diffImage ); DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); // iterate over output slice (and over input slice simultaneously) outputIterator.GoToBegin(); inputIterator.GoToBegin(); diffIterator.GoToBegin(); while ( !outputIterator.IsAtEnd() ) { while ( !outputIterator.IsAtEndOfSlice() ) { while ( !outputIterator.IsAtEndOfLine() ) { diffIterator.Set( static_cast(inputIterator.Get() - outputIterator.Get()) ); // oh oh, not good for bigger values outputIterator.Set( (TPixel2) inputIterator.Get() ); ++outputIterator; ++inputIterator; ++diffIterator; } outputIterator.NextLine(); } outputIterator.NextSlice(); } } std::string mitk::OverwriteSliceImageFilter::EventDescription( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ) { std::stringstream s; s << "Changed slice ("; switch (sliceDimension) { default: case 2: s << "T"; break; case 1: s << "C"; break; case 0: s << "S"; break; } s << " " << sliceIndex << " " << timeStep << ")"; return s.str(); } diff --git a/Modules/MitkExt/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp b/Modules/MitkExt/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp index 7e249bbf06..af7b540e61 100644 --- a/Modules/MitkExt/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp +++ b/Modules/MitkExt/Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp @@ -1,72 +1,73 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkShapeBasedInterpolationAlgorithm.h" #include "mitkImageCast.h" +#include "mitkImageDataItem.h" #include "ipSegmentation.h" mitk::Image::Pointer mitk::ShapeBasedInterpolationAlgorithm::Interpolate( Image::ConstPointer lowerSlice, unsigned int lowerSliceIndex, Image::ConstPointer upperSlice, unsigned int upperSliceIndex, unsigned int requestedIndex, unsigned int /*sliceDimension*/, // commented variables are not used Image::Pointer resultImage, unsigned int /*timeStep*/, Image::ConstPointer /*referenceImage*/) { // convert these slices to the ipSegmentation data type (into an ITK image) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeLowerITKSlice; CastToItkImage( lowerSlice, correctPixelTypeLowerITKSlice ); assert ( correctPixelTypeLowerITKSlice.IsNotNull() ); itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeUpperITKSlice; CastToItkImage( upperSlice, correctPixelTypeUpperITKSlice ); assert ( correctPixelTypeUpperITKSlice.IsNotNull() ); // correct direction info itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeLowerITKSlice->SetDirection(imageDirection); correctPixelTypeUpperITKSlice->SetDirection(imageDirection); // back-convert to MITK images to access a mitkIpPicDescriptor Image::Pointer correctPixelTypeLowerMITKSlice = Image::New(); CastToMitkImage( correctPixelTypeLowerITKSlice, correctPixelTypeLowerMITKSlice ); mitkIpPicDescriptor* lowerPICSlice = correctPixelTypeLowerMITKSlice->GetSliceData()->GetPicDescriptor(); Image::Pointer correctPixelTypeUpperMITKSlice = Image::New(); CastToMitkImage( correctPixelTypeUpperITKSlice, correctPixelTypeUpperMITKSlice ); mitkIpPicDescriptor* upperPICSlice = correctPixelTypeUpperMITKSlice->GetSliceData()->GetPicDescriptor(); // calculate where the current slice is in comparison to the lower and upper neighboring slices float ratio = (float)(requestedIndex - lowerSliceIndex) / (float)(upperSliceIndex - lowerSliceIndex); mitkIpPicDescriptor* ipPicResult = ipMITKSegmentationInterpolate( lowerPICSlice, upperPICSlice, ratio ); // magic if (!ipPicResult) return NULL; Geometry3D::Pointer originalGeometry = resultImage->GetGeometry(); resultImage->Initialize( ipPicResult ); resultImage->SetPicSlice( ipPicResult ); resultImage->SetGeometry( originalGeometry ); mitkIpPicFree( ipPicResult ); return resultImage; } diff --git a/Modules/MitkExt/Controllers/mitkSegmentationInterpolationController.cpp b/Modules/MitkExt/Controllers/mitkSegmentationInterpolationController.cpp index 19a773abe2..794a202c4a 100644 --- a/Modules/MitkExt/Controllers/mitkSegmentationInterpolationController.cpp +++ b/Modules/MitkExt/Controllers/mitkSegmentationInterpolationController.cpp @@ -1,485 +1,486 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkSegmentationInterpolationController.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkExtractImageFilter.h" #include "mitkImageTimeSelector.h" #include "mitkShapeBasedInterpolationAlgorithm.h" #include #include #include mitk::SegmentationInterpolationController::InterpolatorMapType mitk::SegmentationInterpolationController::s_InterpolatorForImage; // static member initialization mitk::SegmentationInterpolationController* mitk::SegmentationInterpolationController::InterpolatorForImage(const Image* image) { InterpolatorMapType::iterator iter = s_InterpolatorForImage.find( image ); if ( iter != s_InterpolatorForImage.end() ) { return iter->second; } else { return NULL; } } mitk::SegmentationInterpolationController::SegmentationInterpolationController() :m_BlockModified(false) { } mitk::SegmentationInterpolationController::~SegmentationInterpolationController() { // remove this from the list of interpolators for ( InterpolatorMapType::iterator iter = s_InterpolatorForImage.begin(); iter != s_InterpolatorForImage.end(); ++iter ) { if (iter->second == this) { s_InterpolatorForImage.erase( iter ); break; } } } void mitk::SegmentationInterpolationController::OnImageModified(const itk::EventObject&) { if (!m_BlockModified && m_Segmentation.IsNotNull() ) { SetSegmentationVolume( m_Segmentation ); } } void mitk::SegmentationInterpolationController::BlockModified(bool block) { m_BlockModified = block; } void mitk::SegmentationInterpolationController::SetSegmentationVolume( const Image* segmentation ) { // clear old information (remove all time steps m_SegmentationCountInSlice.clear(); // delete this from the list of interpolators InterpolatorMapType::iterator iter = s_InterpolatorForImage.find( segmentation ); if ( iter != s_InterpolatorForImage.end() ) { s_InterpolatorForImage.erase( iter ); } if (!segmentation) return; if (segmentation->GetDimension() > 4 || segmentation->GetDimension() < 3) { itkExceptionMacro("SegmentationInterpolationController needs a 3D-segmentation or 3D+t, not 2D."); } if (m_Segmentation != segmentation) { // observe Modified() event of image itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &SegmentationInterpolationController::OnImageModified ); segmentation->AddObserver( itk::ModifiedEvent(), command ); } m_Segmentation = segmentation; m_SegmentationCountInSlice.resize( m_Segmentation->GetTimeSteps() ); for (unsigned int timeStep = 0; timeStep < m_Segmentation->GetTimeSteps(); ++timeStep) { m_SegmentationCountInSlice[timeStep].resize(3); for (unsigned int dim = 0; dim < 3; ++dim) { m_SegmentationCountInSlice[timeStep][dim].clear(); m_SegmentationCountInSlice[timeStep][dim].resize( m_Segmentation->GetDimension(dim) ); m_SegmentationCountInSlice[timeStep][dim].assign( m_Segmentation->GetDimension(dim), 0 ); } } s_InterpolatorForImage.insert( std::make_pair( m_Segmentation, this ) ); // for all timesteps // scan whole image for (unsigned int timeStep = 0; timeStep < m_Segmentation->GetTimeSteps(); ++timeStep) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( m_Segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer segmentation3D = timeSelector->GetOutput(); AccessFixedDimensionByItk_2( segmentation3D, ScanWholeVolume, 3, m_Segmentation, timeStep ); } //PrintStatus(); SetReferenceVolume( m_ReferenceImage ); Modified(); } void mitk::SegmentationInterpolationController::SetReferenceVolume( const Image* referenceImage ) { m_ReferenceImage = referenceImage; if ( m_ReferenceImage.IsNull() ) return; // no image set - ignore it then assert ( m_Segmentation.IsNotNull() ); // should never happen // ensure the reference image has the same dimensionality and extents as the segmentation image if ( m_ReferenceImage.IsNull() || m_Segmentation.IsNull() || m_ReferenceImage->GetDimension() != m_Segmentation->GetDimension() || m_ReferenceImage->GetPixelType().GetNumberOfComponents() != 1 || m_Segmentation->GetPixelType().GetNumberOfComponents() != 1 ) { MITK_ERROR << "original patient image does not match segmentation, ignoring patient image" << std::endl; m_ReferenceImage = NULL; return; } for (unsigned int dim = 0; dim < m_Segmentation->GetDimension(); ++dim) if ( m_ReferenceImage->GetDimension(dim) != m_Segmentation->GetDimension(dim) ) { MITK_ERROR << "original patient image does not match segmentation (different extent in dimension " << dim << "), ignoring patient image" << std::endl; m_ReferenceImage = NULL; return; } } void mitk::SegmentationInterpolationController::SetChangedVolume( const Image* sliceDiff, unsigned int timeStep ) { if ( !sliceDiff ) return; if ( sliceDiff->GetDimension() != 3 ) return; AccessFixedDimensionByItk_1( sliceDiff, ScanChangedVolume, 3, timeStep ); //PrintStatus(); Modified(); } void mitk::SegmentationInterpolationController::SetChangedSlice( const Image* sliceDiff, unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ) { if ( !sliceDiff ) return; if ( sliceDimension > 2 ) return; if ( timeStep >= m_SegmentationCountInSlice.size() ) return; if ( sliceIndex >= m_SegmentationCountInSlice[timeStep][sliceDimension].size() ) return; unsigned int dim0(0); unsigned int dim1(1); // determine the other two dimensions switch (sliceDimension) { default: case 2: dim0 = 0; dim1 = 1; break; case 1: dim0 = 0; dim1 = 2; break; case 0: dim0 = 1; dim1 = 2; break; } mitkIpPicDescriptor* rawSlice = const_cast(sliceDiff)->GetSliceData()->GetPicDescriptor(); // we promise not to change anything! if (!rawSlice) return; AccessFixedDimensionByItk_1( sliceDiff, ScanChangedSlice, 2, SetChangedSliceOptions(sliceDimension, sliceIndex, dim0, dim1, timeStep, rawSlice->data) ); //PrintStatus(); Modified(); } template < typename DATATYPE > void mitk::SegmentationInterpolationController::ScanChangedSlice( itk::Image*, const SetChangedSliceOptions& options ) { DATATYPE* pixelData( (DATATYPE*)options.pixelData ); unsigned int timeStep( options.timeStep ); unsigned int sliceDimension( options.sliceDimension ); unsigned int sliceIndex( options.sliceIndex ); if ( sliceDimension > 2 ) return; if ( sliceIndex >= m_SegmentationCountInSlice[timeStep][sliceDimension].size() ) return; unsigned int dim0( options.dim0 ); unsigned int dim1( options.dim1 ); int numberOfPixels(0); // number of pixels in this slice that are not 0 unsigned int dim0max = m_SegmentationCountInSlice[timeStep][dim0].size(); unsigned int dim1max = m_SegmentationCountInSlice[timeStep][dim1].size(); // scan the slice from two directions // and set the flags for the two dimensions of the slice for (unsigned int v = 0; v < dim1max; ++v) { for (unsigned int u = 0; u < dim0max; ++u) { DATATYPE value = *(pixelData + u + v * dim0max); assert ( (signed) m_SegmentationCountInSlice[timeStep][dim0][u] + (signed)value >= 0 ); // just for debugging. This must always be true, otherwise some counting is going wrong assert ( (signed) m_SegmentationCountInSlice[timeStep][dim1][v] + (signed)value >= 0 ); m_SegmentationCountInSlice[timeStep][dim0][u] = static_cast( m_SegmentationCountInSlice[timeStep][dim0][u] + value ); m_SegmentationCountInSlice[timeStep][dim1][v] = static_cast( m_SegmentationCountInSlice[timeStep][dim1][v] + value ); numberOfPixels += static_cast( value ); } } // flag for the dimension of the slice itself assert ( (signed) m_SegmentationCountInSlice[timeStep][sliceDimension][sliceIndex] + numberOfPixels >= 0 ); m_SegmentationCountInSlice[timeStep][sliceDimension][sliceIndex] += numberOfPixels; //MITK_INFO << "scan t=" << timeStep << " from (0,0) to (" << dim0max << "," << dim1max << ") (" << pixelData << "-" << pixelData+dim0max*dim1max-1 << ") in slice " << sliceIndex << " found " << numberOfPixels << " pixels" << std::endl; } template < typename TPixel, unsigned int VImageDimension > void mitk::SegmentationInterpolationController::ScanChangedVolume( itk::Image* diffImage, unsigned int timeStep ) { typedef itk::ImageSliceConstIteratorWithIndex< itk::Image > IteratorType; IteratorType iter( diffImage, diffImage->GetLargestPossibleRegion() ); iter.SetFirstDirection(0); iter.SetSecondDirection(1); int numberOfPixels(0); // number of pixels in this slice that are not 0 typename IteratorType::IndexType index; unsigned int x = 0; unsigned int y = 0; unsigned int z = 0; iter.GoToBegin(); while ( !iter.IsAtEnd() ) { while ( !iter.IsAtEndOfSlice() ) { while ( !iter.IsAtEndOfLine() ) { index = iter.GetIndex(); x = index[0]; y = index[1]; z = index[2]; TPixel value = iter.Get(); assert ( (signed) m_SegmentationCountInSlice[timeStep][0][x] + (signed)value >= 0 ); // just for debugging. This must always be true, otherwise some counting is going wrong assert ( (signed) m_SegmentationCountInSlice[timeStep][1][y] + (signed)value >= 0 ); m_SegmentationCountInSlice[timeStep][0][x] = static_cast( m_SegmentationCountInSlice[timeStep][0][x] + value ); m_SegmentationCountInSlice[timeStep][1][y] = static_cast( m_SegmentationCountInSlice[timeStep][1][y] + value ); numberOfPixels += static_cast( value ); ++iter; } iter.NextLine(); } assert ( (signed) m_SegmentationCountInSlice[timeStep][2][z] + numberOfPixels >= 0 ); m_SegmentationCountInSlice[timeStep][2][z] += numberOfPixels; numberOfPixels = 0; iter.NextSlice(); } } template < typename DATATYPE > void mitk::SegmentationInterpolationController::ScanWholeVolume( itk::Image*, const Image* volume, unsigned int timeStep ) { if (!volume) return; if ( timeStep >= m_SegmentationCountInSlice.size() ) return; for (unsigned int slice = 0; slice < volume->GetDimension(2); ++slice) { DATATYPE* rawVolume = static_cast( const_cast(volume)->GetVolumeData(timeStep)->GetData() ); // we again promise not to change anything, we'll just count //DATATYPE* rawSlice = static_cast( volume->GetSliceData(slice)->GetData() ); // TODO THIS wouldn't work. Did I mess up with some internal mitk::Image data structure? DATATYPE* rawSlice = rawVolume + ( volume->GetDimension(0) * volume->GetDimension(1) * slice ); ScanChangedSlice( NULL, SetChangedSliceOptions(2, slice, 0, 1, timeStep, rawSlice) ); } } void mitk::SegmentationInterpolationController::PrintStatus() { unsigned int timeStep(0); // if needed, put a loop over time steps around everyting, but beware, output will be long MITK_INFO << "Interpolator status (timestep 0): dimensions " << m_SegmentationCountInSlice[timeStep][0].size() << " " << m_SegmentationCountInSlice[timeStep][1].size() << " " << m_SegmentationCountInSlice[timeStep][2].size() << std::endl; MITK_INFO << "Slice 0: " << m_SegmentationCountInSlice[timeStep][2][0] << std::endl; // row "x" for (unsigned int index = 0; index < m_SegmentationCountInSlice[timeStep][0].size(); ++index) { if ( m_SegmentationCountInSlice[timeStep][0][index] > 0 ) MITK_INFO << "O"; else MITK_INFO << "."; } MITK_INFO << std::endl; // rows "y" and "z" (diagonal) for (unsigned int index = 1; index < m_SegmentationCountInSlice[timeStep][1].size(); ++index) { if ( m_SegmentationCountInSlice[timeStep][1][index] > 0 ) MITK_INFO << "O"; else MITK_INFO << "."; if ( m_SegmentationCountInSlice[timeStep][2].size() > index ) // if we also have a z value here, then print it, too { for (unsigned int indent = 1; indent < index; ++indent) MITK_INFO << " "; if ( m_SegmentationCountInSlice[timeStep][2][index] > 0 ) MITK_INFO << m_SegmentationCountInSlice[timeStep][2][index];//"O"; else MITK_INFO << "."; } MITK_INFO << std::endl; } // z indices that are larger than the biggest y index for (unsigned int index = m_SegmentationCountInSlice[timeStep][1].size(); index < m_SegmentationCountInSlice[timeStep][2].size(); ++index) { for (unsigned int indent = 0; indent < index; ++indent) MITK_INFO << " "; if ( m_SegmentationCountInSlice[timeStep][2][index] > 0 ) MITK_INFO << m_SegmentationCountInSlice[timeStep][2][index];//"O"; else MITK_INFO << "."; MITK_INFO << std::endl; } } mitk::Image::Pointer mitk::SegmentationInterpolationController::Interpolate( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ) { if (m_Segmentation.IsNull()) return NULL; if ( timeStep >= m_SegmentationCountInSlice.size() ) return NULL; if ( sliceDimension > 2 ) return NULL; unsigned int upperLimit = m_SegmentationCountInSlice[timeStep][sliceDimension].size(); if ( sliceIndex >= upperLimit - 1 ) return NULL; // can't interpolate first and last slice if ( sliceIndex < 1 ) return NULL; if ( m_SegmentationCountInSlice[timeStep][sliceDimension][sliceIndex] > 0 ) return NULL; // slice contains a segmentation, won't interpolate anything then unsigned int lowerBound(0); unsigned int upperBound(0); bool bounds( false ); for (lowerBound = sliceIndex - 1; /*lowerBound >= 0*/; --lowerBound) { if ( m_SegmentationCountInSlice[timeStep][sliceDimension][lowerBound] > 0 ) { bounds = true; break; } if (lowerBound == 0) break; // otherwise overflow and start at something like 4294967295 } if (!bounds) return NULL; bounds = false; for (upperBound = sliceIndex + 1 ; upperBound < upperLimit; ++upperBound) { if ( m_SegmentationCountInSlice[timeStep][sliceDimension][upperBound] > 0 ) { bounds = true; break; } } if (!bounds) return NULL; // ok, we have found two neighboring slices with segmentations (and we made sure that the current slice does NOT contain anything //MITK_INFO << "Interpolate in timestep " << timeStep << ", dimension " << sliceDimension << ": estimate slice " << sliceIndex << " from slices " << lowerBound << " and " << upperBound << std::endl; mitk::Image::Pointer lowerMITKSlice; mitk::Image::Pointer upperMITKSlice; mitk::Image::Pointer resultImage; try { // extract the two neighoring slices from the segmentation volume ExtractImageFilter::Pointer extractor= ExtractImageFilter::New(); extractor->SetInput( m_Segmentation ); extractor->SetSliceDimension( sliceDimension ); extractor->SetSliceIndex( lowerBound ); extractor->SetTimeStep( timeStep ); extractor->Update(); lowerMITKSlice = extractor->GetOutput(); lowerMITKSlice->DisconnectPipeline(); // otherwise the next output of the filter will overwrite this pointer, too extractor->SetInput( m_Segmentation ); extractor->SetSliceDimension( sliceDimension ); extractor->SetSliceIndex( sliceIndex ); extractor->SetTimeStep( timeStep ); extractor->Update(); resultImage = extractor->GetOutput(); resultImage->DisconnectPipeline(); extractor->SetInput( m_Segmentation ); extractor->SetSliceDimension( sliceDimension ); extractor->SetSliceIndex( upperBound ); extractor->SetTimeStep( timeStep ); extractor->Update(); upperMITKSlice = extractor->GetOutput(); if ( lowerMITKSlice.IsNull() || upperMITKSlice.IsNull() ) return NULL; } catch(...) { return NULL; } // interpolation algorithm gets some inputs // two segmentations (guaranteed to be of the same data type, but no special data type guaranteed) // orientation (sliceDimension) of the segmentations // position of the two slices (sliceIndices) // one volume image (original patient image) // // interpolation algorithm can use e.g. itk::ImageSliceConstIteratorWithIndex to // inspect the original patient image at appropriate positions mitk::SegmentationInterpolationAlgorithm::Pointer algorithm = mitk::ShapeBasedInterpolationAlgorithm::New().GetPointer(); return algorithm->Interpolate( lowerMITKSlice.GetPointer(), lowerBound, upperMITKSlice.GetPointer(), upperBound, sliceIndex, sliceDimension, resultImage, timeStep, m_ReferenceImage ); } diff --git a/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp b/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp index 0721b4fe08..415e038983 100644 --- a/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp +++ b/Modules/MitkExt/Interactions/mitkBinaryThresholdTool.cpp @@ -1,311 +1,312 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkBinaryThresholdTool.h" #include "mitkBinaryThresholdTool.xpm" #include "mitkToolManager.h" #include "mitkBoundingObjectToSegmentationFilter.h" #include #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkOrganTypeProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkImageTimeSelector.h" #include #include #include "mitkPadImageFilter.h" #include "mitkMaskAndCutRoiImageFilter.h" namespace mitk { MITK_TOOL_MACRO(MitkExt_EXPORT, BinaryThresholdTool, "Thresholding tool"); } mitk::BinaryThresholdTool::BinaryThresholdTool() :m_SensibleMinimumThresholdValue(-100), m_SensibleMaximumThresholdValue(+100), m_CurrentThresholdValue(1) { this->SupportRoiOn(); m_ThresholdFeedbackNode = DataNode::New(); mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_ThresholdFeedbackNode ); m_ThresholdFeedbackNode->SetProperty( "color", ColorProperty::New(1.0, 0.0, 0.0) ); m_ThresholdFeedbackNode->SetProperty( "texture interpolation", BoolProperty::New(false) ); m_ThresholdFeedbackNode->SetProperty( "layer", IntProperty::New( 100 ) ); m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(100, 1) ) ); m_ThresholdFeedbackNode->SetProperty( "name", StringProperty::New("Thresholding feedback") ); m_ThresholdFeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) ); m_ThresholdFeedbackNode->SetProperty( "helper object", BoolProperty::New(true) ); } mitk::BinaryThresholdTool::~BinaryThresholdTool() { } const char** mitk::BinaryThresholdTool::GetXPM() const { return mitkBinaryThresholdTool_xpm; } const char* mitk::BinaryThresholdTool::GetName() const { return "Thresholding"; } void mitk::BinaryThresholdTool::Activated() { m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::BinaryThresholdTool::OnRoiDataChanged); m_OriginalImageNode = m_ToolManager->GetReferenceData(0); m_NodeForThresholding = m_OriginalImageNode; if ( m_NodeForThresholding.IsNotNull() ) { SetupPreviewNodeFor( m_NodeForThresholding ); } else { m_ToolManager->ActivateTool(-1); } } void mitk::BinaryThresholdTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::BinaryThresholdTool::OnRoiDataChanged); m_NodeForThresholding = NULL; m_OriginalImageNode = NULL; try { if (DataStorage* storage = m_ToolManager->GetDataStorage()) { storage->Remove( m_ThresholdFeedbackNode ); RenderingManager::GetInstance()->RequestUpdateAll(); } } catch(...) { // don't care } m_ThresholdFeedbackNode->SetData(NULL); } void mitk::BinaryThresholdTool::SetThresholdValue(int value) { if (m_ThresholdFeedbackNode.IsNotNull()) { m_CurrentThresholdValue = value; m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(m_CurrentThresholdValue, 1) ) ); RenderingManager::GetInstance()->RequestUpdateAll(); } } void mitk::BinaryThresholdTool::AcceptCurrentThresholdValue(const std::string& organName, const Color& color) { CreateNewSegmentationFromThreshold(m_NodeForThresholding, organName, color ); RenderingManager::GetInstance()->RequestUpdateAll(); m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdTool::CancelThresholding() { m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdTool::SetupPreviewNodeFor( DataNode* nodeForThresholding ) { if (nodeForThresholding) { Image::Pointer image = dynamic_cast( nodeForThresholding->GetData() ); Image::Pointer originalImage = dynamic_cast (m_OriginalImageNode->GetData()); if (image.IsNotNull()) { // initialize and a new node with the same image as our reference image // use the level window property of this image copy to display the result of a thresholding operation m_ThresholdFeedbackNode->SetData( image ); int layer(50); nodeForThresholding->GetIntProperty("layer", layer); m_ThresholdFeedbackNode->SetIntProperty("layer", layer+1); if (DataStorage* storage = m_ToolManager->GetDataStorage()) { if (storage->Exists(m_ThresholdFeedbackNode)) storage->Remove(m_ThresholdFeedbackNode); storage->Add( m_ThresholdFeedbackNode, m_OriginalImageNode ); } if (image.GetPointer() == originalImage.GetPointer()) { m_SensibleMinimumThresholdValue = static_cast( originalImage->GetScalarValueMin() ); m_SensibleMaximumThresholdValue = static_cast( originalImage->GetScalarValueMax() ); } LevelWindowProperty::Pointer lwp = dynamic_cast( m_ThresholdFeedbackNode->GetProperty( "levelwindow" )); if (lwp) { m_CurrentThresholdValue = static_cast( lwp->GetLevelWindow().GetLevel() ); } else { m_CurrentThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue)/2; } IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue); ThresholdingValueChanged.Send(m_CurrentThresholdValue); } } } void mitk::BinaryThresholdTool::CreateNewSegmentationFromThreshold(DataNode* node, const std::string& organName, const Color& color) { if (node) { Image::Pointer image = dynamic_cast( m_NodeForThresholding->GetData() ); if (image.IsNotNull()) { // create a new image of the same dimensions and smallest possible pixel type DataNode::Pointer emptySegmentation = Tool::CreateEmptySegmentationNode( image, organName, color ); if (emptySegmentation) { // actually perform a thresholding and ask for an organ type for (unsigned int timeStep = 0; timeStep < image->GetTimeSteps(); ++timeStep) { try { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( image ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer image3D = timeSelector->GetOutput(); AccessFixedDimensionByItk_2( image3D, ITKThresholding, 3, dynamic_cast(emptySegmentation->GetData()), timeStep ); } catch(...) { Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation."); } } if (m_OriginalImageNode.GetPointer() != m_NodeForThresholding.GetPointer()) { mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New(); padFilter->SetInput(0, dynamic_cast (emptySegmentation->GetData())); padFilter->SetInput(1, dynamic_cast (m_OriginalImageNode->GetData())); padFilter->SetBinaryFilter(true); padFilter->SetUpperThreshold(1); padFilter->SetLowerThreshold(1); padFilter->Update(); emptySegmentation->SetData(padFilter->GetOutput()); } if (DataStorage::Pointer storage = m_ToolManager->GetDataStorage()) { storage->Add( emptySegmentation, m_OriginalImageNode ); // add as a child, because the segmentation "derives" from the original } m_ToolManager->SetWorkingData( emptySegmentation ); } } } } template void mitk::BinaryThresholdTool::ITKThresholding( itk::Image* originalImage, Image* segmentation, unsigned int timeStep ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer segmentation3D = timeSelector->GetOutput(); typedef itk::Image< Tool::DefaultSegmentationDataType, 3> SegmentationType; // this is sure for new segmentations SegmentationType::Pointer itkSegmentation; CastToItkImage( segmentation3D, itkSegmentation ); // iterate over original and segmentation typedef itk::ImageRegionConstIterator< itk::Image > InputIteratorType; typedef itk::ImageRegionIterator< SegmentationType > SegmentationIteratorType; InputIteratorType inputIterator( originalImage, originalImage->GetLargestPossibleRegion() ); SegmentationIteratorType outputIterator( itkSegmentation, itkSegmentation->GetLargestPossibleRegion() ); inputIterator.GoToBegin(); outputIterator.GoToBegin(); while (!outputIterator.IsAtEnd()) { if ( (signed)inputIterator.Get() >= m_CurrentThresholdValue ) { outputIterator.Set( 1 ); } else { outputIterator.Set( 0 ); } ++inputIterator; ++outputIterator; } } void mitk::BinaryThresholdTool::OnRoiDataChanged() { mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0); if (node.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast (m_NodeForThresholding->GetData()); if (image.IsNull()) return; mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New(); roiFilter->SetInput(image); roiFilter->SetRegionOfInterest(node->GetData()); roiFilter->Update(); mitk::DataNode::Pointer tmpNode = mitk::DataNode::New(); mitk::Image::Pointer tmpImage = roiFilter->GetOutput(); tmpNode->SetData(tmpImage); m_SensibleMaximumThresholdValue = static_cast (roiFilter->GetMaxValue()); m_SensibleMinimumThresholdValue = static_cast (roiFilter->GetMinValue()); SetupPreviewNodeFor( tmpNode ); m_NodeForThresholding = tmpNode; return; } else { this->SetupPreviewNodeFor(m_OriginalImageNode); m_NodeForThresholding = m_OriginalImageNode; return; } } diff --git a/Modules/MitkExt/Interactions/mitkBinaryThresholdULTool.cpp b/Modules/MitkExt/Interactions/mitkBinaryThresholdULTool.cpp index 24031b11a0..14c785035f 100644 --- a/Modules/MitkExt/Interactions/mitkBinaryThresholdULTool.cpp +++ b/Modules/MitkExt/Interactions/mitkBinaryThresholdULTool.cpp @@ -1,319 +1,320 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.0 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkBinaryThresholdULTool.h" #include "mitkBinaryThresholdULTool.xpm" #include "mitkToolManager.h" #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkImageTimeSelector.h" #include #include #include "mitkMaskAndCutRoiImageFilter.h" #include "mitkPadImageFilter.h" namespace mitk { MITK_TOOL_MACRO(MitkExt_EXPORT, BinaryThresholdULTool, "ThresholdingUL tool"); } mitk::BinaryThresholdULTool::BinaryThresholdULTool() :m_SensibleMinimumThresholdValue(-100), m_SensibleMaximumThresholdValue(+100), m_CurrentLowerThresholdValue(1), m_CurrentUpperThresholdValue(1) { this->SupportRoiOn(); m_ThresholdFeedbackNode = DataNode::New(); m_ThresholdFeedbackNode->SetProperty( "color", ColorProperty::New(1.0, 0.0, 0.0) ); m_ThresholdFeedbackNode->SetProperty( "name", StringProperty::New("Thresholding feedback") ); m_ThresholdFeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) ); m_ThresholdFeedbackNode->SetProperty("binary", BoolProperty::New(true)); m_ThresholdFeedbackNode->SetProperty( "helper object", BoolProperty::New(true) ); } mitk::BinaryThresholdULTool::~BinaryThresholdULTool() { } const char** mitk::BinaryThresholdULTool::GetXPM() const { return mitkBinaryThresholdULTool_xpm; } const char* mitk::BinaryThresholdULTool::GetName() const { return "ThresholdingUL"; } void mitk::BinaryThresholdULTool::Activated() { m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::BinaryThresholdULTool::OnRoiDataChanged); m_OriginalImageNode = m_ToolManager->GetReferenceData(0); m_NodeForThresholding = m_OriginalImageNode; if ( m_NodeForThresholding.IsNotNull() ) { SetupPreviewNode(); } else { m_ToolManager->ActivateTool(-1); } } void mitk::BinaryThresholdULTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::BinaryThresholdULTool::OnRoiDataChanged); m_NodeForThresholding = NULL; m_OriginalImageNode = NULL; try { if (DataStorage* storage = m_ToolManager->GetDataStorage()) { storage->Remove( m_ThresholdFeedbackNode ); RenderingManager::GetInstance()->RequestUpdateAll(); } } catch(...) { // don't care } m_ThresholdFeedbackNode->SetData(NULL); } void mitk::BinaryThresholdULTool::SetThresholdValues(int lower, int upper) { if (m_ThresholdFeedbackNode.IsNotNull()) { m_CurrentLowerThresholdValue = lower; m_CurrentUpperThresholdValue = upper; UpdatePreview(); } } void mitk::BinaryThresholdULTool::AcceptCurrentThresholdValue(const std::string& organName, const Color& color) { CreateNewSegmentationFromThreshold(m_NodeForThresholding, organName, color ); RenderingManager::GetInstance()->RequestUpdateAll(); m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdULTool::CancelThresholding() { m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdULTool::SetupPreviewNode() { if (m_NodeForThresholding.IsNotNull()) { Image::Pointer image = dynamic_cast( m_NodeForThresholding->GetData() ); Image::Pointer originalImage = dynamic_cast (m_OriginalImageNode->GetData()); if (image.IsNotNull()) { // initialize and a new node with the same image as our reference image // use the level window property of this image copy to display the result of a thresholding operation m_ThresholdFeedbackNode->SetData( image ); int layer(50); m_NodeForThresholding->GetIntProperty("layer", layer); m_ThresholdFeedbackNode->SetIntProperty("layer", layer+1); if (DataStorage* ds = m_ToolManager->GetDataStorage()) { if (!ds->Exists(m_ThresholdFeedbackNode)) ds->Add( m_ThresholdFeedbackNode, m_OriginalImageNode ); } if (image.GetPointer() == originalImage.GetPointer()) { m_SensibleMinimumThresholdValue = static_cast( originalImage->GetScalarValueMin() ); m_SensibleMaximumThresholdValue = static_cast( originalImage->GetScalarValueMax() ); } m_CurrentLowerThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue) / 3; m_CurrentUpperThresholdValue = 2*m_CurrentLowerThresholdValue; IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue); ThresholdingValuesChanged.Send(m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue); } } } void mitk::BinaryThresholdULTool::CreateNewSegmentationFromThreshold(DataNode* node, const std::string& organName, const Color& color) { if (node) { Image::Pointer image = dynamic_cast( m_NodeForThresholding->GetData() ); if (image.IsNotNull()) { // create a new image of the same dimensions and smallest possible pixel type DataNode::Pointer emptySegmentation = Tool::CreateEmptySegmentationNode( image, organName, color ); if (emptySegmentation) { // actually perform a thresholding and ask for an organ type for (unsigned int timeStep = 0; timeStep < image->GetTimeSteps(); ++timeStep) { try { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( image ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer image3D = timeSelector->GetOutput(); AccessFixedDimensionByItk_2( image3D, ITKThresholding, 3, dynamic_cast(emptySegmentation->GetData()), timeStep ); } catch(...) { Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation."); } } //since we are maybe working on a smaller image, pad it to the size of the original image if (m_OriginalImageNode.GetPointer() != m_NodeForThresholding.GetPointer()) { mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New(); padFilter->SetInput(0, dynamic_cast (emptySegmentation->GetData())); padFilter->SetInput(1, dynamic_cast (m_OriginalImageNode->GetData())); padFilter->SetBinaryFilter(true); padFilter->SetUpperThreshold(1); padFilter->SetLowerThreshold(1); padFilter->Update(); emptySegmentation->SetData(padFilter->GetOutput()); } if (DataStorage* ds = m_ToolManager->GetDataStorage()) { ds->Add( emptySegmentation, m_OriginalImageNode ); } m_ToolManager->SetWorkingData( emptySegmentation ); } } } } template void mitk::BinaryThresholdULTool::ITKThresholding( itk::Image* originalImage, Image* segmentation, unsigned int timeStep ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer segmentation3D = timeSelector->GetOutput(); typedef itk::Image< Tool::DefaultSegmentationDataType, 3> SegmentationType; // this is sure for new segmentations SegmentationType::Pointer itkSegmentation; CastToItkImage( segmentation3D, itkSegmentation ); // iterate over original and segmentation typedef itk::ImageRegionConstIterator< itk::Image > InputIteratorType; typedef itk::ImageRegionIterator< SegmentationType > SegmentationIteratorType; InputIteratorType inputIterator( originalImage, originalImage->GetLargestPossibleRegion() ); SegmentationIteratorType outputIterator( itkSegmentation, itkSegmentation->GetLargestPossibleRegion() ); inputIterator.GoToBegin(); outputIterator.GoToBegin(); while (!outputIterator.IsAtEnd()) { if ( (signed)inputIterator.Get() >= m_CurrentLowerThresholdValue && (signed)inputIterator.Get() <= m_CurrentUpperThresholdValue ) { outputIterator.Set( 1 ); } else { outputIterator.Set( 0 ); } ++inputIterator; ++outputIterator; } } void mitk::BinaryThresholdULTool::OnRoiDataChanged() { mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0); if (node.IsNotNull()) { mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New(); mitk::Image::Pointer image = dynamic_cast (m_NodeForThresholding->GetData()); if (image.IsNull()) return; roiFilter->SetInput(image); roiFilter->SetRegionOfInterest(node->GetData()); roiFilter->Update(); mitk::DataNode::Pointer tmpNode = mitk::DataNode::New(); tmpNode->SetData(roiFilter->GetOutput()); m_SensibleMinimumThresholdValue = static_cast( roiFilter->GetMinValue()); m_SensibleMaximumThresholdValue = static_cast( roiFilter->GetMaxValue()); m_NodeForThresholding = tmpNode; } else m_NodeForThresholding = m_OriginalImageNode; this->SetupPreviewNode(); this->UpdatePreview(); } void mitk::BinaryThresholdULTool::UpdatePreview() { typedef itk::Image ImageType; typedef itk::Image SegmentationType; typedef itk::BinaryThresholdImageFilter ThresholdFilterType; mitk::Image::Pointer thresholdimage = dynamic_cast (m_NodeForThresholding->GetData()); if(thresholdimage) { ImageType::Pointer itkImage = ImageType::New(); CastToItkImage(thresholdimage, itkImage); ThresholdFilterType::Pointer filter = ThresholdFilterType::New(); filter->SetInput(itkImage); filter->SetLowerThreshold(m_CurrentLowerThresholdValue); filter->SetUpperThreshold(m_CurrentUpperThresholdValue); filter->SetInsideValue(1); filter->SetOutsideValue(0); filter->Update(); mitk::Image::Pointer new_image = mitk::Image::New(); CastToMitkImage(filter->GetOutput(), new_image); m_ThresholdFeedbackNode->SetData(new_image); } RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Modules/MitkExt/Interactions/mitkCalculateGrayValueStatisticsTool.cpp b/Modules/MitkExt/Interactions/mitkCalculateGrayValueStatisticsTool.cpp index 1df9e39241..0f5d664ecc 100644 --- a/Modules/MitkExt/Interactions/mitkCalculateGrayValueStatisticsTool.cpp +++ b/Modules/MitkExt/Interactions/mitkCalculateGrayValueStatisticsTool.cpp @@ -1,340 +1,341 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkCalculateGrayValueStatisticsTool.h" #include "mitkCalculateGrayValueStatisticsTool.xpm" +#include "mitkImageAccessByItk.h" #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkImageTimeSelector.h" #include "mitkImageCast.h" #include "mitkToolManager.h" #include #include namespace mitk { MITK_TOOL_MACRO(MitkExt_EXPORT, CalculateGrayValueStatisticsTool, "Statistics tool"); } mitk::CalculateGrayValueStatisticsTool::CalculateGrayValueStatisticsTool() { } mitk::CalculateGrayValueStatisticsTool::~CalculateGrayValueStatisticsTool() { } const char** mitk::CalculateGrayValueStatisticsTool::GetXPM() const { return mitkCalculateGrayValueStatisticsTool_xpm; } const char* mitk::CalculateGrayValueStatisticsTool::GetName() const { return "Statistics"; } std::string mitk::CalculateGrayValueStatisticsTool::GetErrorMessage() { return "No statistics generated for these segmentations:"; } void mitk::CalculateGrayValueStatisticsTool::StartProcessingAllData() { // clear/prepare report m_CompleteReport.str(""); } bool mitk::CalculateGrayValueStatisticsTool::ProcessOneWorkingData( DataNode* node ) { if (node) { Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNull()) return false; DataNode* referencenode = m_ToolManager->GetReferenceData(0); if (!referencenode) return false; try { ProgressBar::GetInstance()->AddStepsToDo(1); // add to report std::string nodename("structure"); node->GetName(nodename); std::string message = "Calculating statistics for "; message += nodename; StatusBar::GetInstance()->DisplayText(message.c_str()); Image::Pointer refImage = dynamic_cast( referencenode->GetData() ); Image::Pointer image = dynamic_cast( node->GetData() ); m_CompleteReport << "======== Gray value analysis of " << nodename << " ========\n"; if (image.IsNotNull() && refImage.IsNotNull() ) { for (unsigned int timeStep = 0; timeStep < image->GetTimeSteps(); ++timeStep) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( refImage ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer refImage3D = timeSelector->GetOutput(); ImageTimeSelector::Pointer timeSelector2 = ImageTimeSelector::New(); timeSelector2->SetInput( image ); timeSelector2->SetTimeNr( timeStep ); timeSelector2->UpdateLargestPossibleRegion(); Image::Pointer image3D = timeSelector2->GetOutput(); if (image3D.IsNotNull() && refImage3D.IsNotNull() ) { m_CompleteReport << "=== " << nodename << ", time step " << timeStep << " ===\n"; AccessFixedDimensionByItk_2( refImage3D, ITKHistogramming, 3, image3D, m_CompleteReport ); } } } m_CompleteReport << "======== End of analysis for " << nodename << " ===========\n\n\n"; ProgressBar::GetInstance()->Progress(); } catch(...) { return false; } } return true; } void mitk::CalculateGrayValueStatisticsTool::FinishProcessingAllData() { SegmentationsProcessingTool::FinishProcessingAllData(); // show/send results StatisticsCompleted.Send(); //MITK_INFO << m_CompleteReport.str() << std::endl; } #define ROUND_P(x) ((int)((x)+0.5)) template void mitk::CalculateGrayValueStatisticsTool::CalculateMinMax( itk::Image* referenceImage, Image* segmentation, TPixel& minimum, TPixel& maximum) { typedef itk::Image ImageType; typedef itk::Image SegmentationType; typename SegmentationType::Pointer segmentationItk; CastToItkImage(segmentation, segmentationItk); typename SegmentationType::RegionType segmentationRegion = segmentationItk->GetLargestPossibleRegion(); segmentationRegion.Crop(referenceImage->GetLargestPossibleRegion()); itk::ImageRegionConstIteratorWithIndex segmentationIterator(segmentationItk, segmentationRegion); itk::ImageRegionConstIteratorWithIndex referenceIterator(referenceImage, segmentationRegion); segmentationIterator.GoToBegin(); referenceIterator.GoToBegin(); minimum = std::numeric_limits::max(); maximum = std::numeric_limits::min(); while (!segmentationIterator.IsAtEnd()) { itk::Point pt; segmentationItk->TransformIndexToPhysicalPoint(segmentationIterator.GetIndex(), pt); typename ImageType::IndexType ind; itk::ContinuousIndex contInd; if (referenceImage->TransformPhysicalPointToContinuousIndex(pt, contInd)) { for (unsigned int i = 0; i < 3; ++i) ind[i] = ROUND_P(contInd[i]); referenceIterator.SetIndex(ind); if (segmentationIterator.Get() > 0) { if (referenceIterator.Get() < minimum) minimum = referenceIterator.Get(); if (referenceIterator.Get() > maximum) maximum = referenceIterator.Get(); } } ++segmentationIterator; } } template void mitk::CalculateGrayValueStatisticsTool::ITKHistogramming( itk::Image* referenceImage, Image* segmentation, std::stringstream& report) { typedef itk::Image ImageType; typedef itk::Image SegmentationType; typename SegmentationType::Pointer segmentationItk; CastToItkImage( segmentation, segmentationItk ); // generate histogram typename SegmentationType::RegionType segmentationRegion = segmentationItk->GetLargestPossibleRegion(); segmentationRegion.Crop( referenceImage->GetLargestPossibleRegion() ); itk::ImageRegionConstIteratorWithIndex< SegmentationType > segmentationIterator( segmentationItk, segmentationRegion); itk::ImageRegionConstIteratorWithIndex< ImageType > referenceIterator( referenceImage, segmentationRegion); segmentationIterator.GoToBegin(); referenceIterator.GoToBegin(); m_ITKHistogram = HistogramType::New(); TPixel minimum = std::numeric_limits::max(); TPixel maximum = std::numeric_limits::min(); CalculateMinMax(referenceImage, segmentation, minimum, maximum); //initialize the histogram to the range of the cropped region HistogramType::SizeType size; #if defined(ITK_USE_REVIEW_STATISTICS) typedef typename HistogramType::SizeType::ValueType HSizeValueType; #else typedef typename HistogramType::SizeType::SizeValueType HSizeValueType; #endif size.Fill(static_cast (maximum - minimum + 1)); HistogramType::MeasurementVectorType lowerBound; HistogramType::MeasurementVectorType upperBound; lowerBound[0] = minimum; upperBound[0] = maximum; m_ITKHistogram->Initialize(size, lowerBound, upperBound); double mean(0.0); double sd(0.0); double voxelCount(0.0); //iterate through the cropped region add the values to the histogram while (!segmentationIterator.IsAtEnd()) { itk::Point< float, 3 > pt; segmentationItk->TransformIndexToPhysicalPoint( segmentationIterator.GetIndex(), pt ); typename ImageType::IndexType ind; itk::ContinuousIndex contInd; if (referenceImage->TransformPhysicalPointToContinuousIndex(pt, contInd)) { for (unsigned int i = 0; i < 3; ++i) ind[i] = ROUND_P(contInd[i]); referenceIterator.SetIndex( ind ); if ( segmentationIterator.Get() > 0 ) { HistogramType::MeasurementVectorType currentMeasurementVector; currentMeasurementVector[0] = static_cast (referenceIterator.Get()); m_ITKHistogram->IncreaseFrequency(currentMeasurementVector, 1); mean = (mean * (static_cast (voxelCount) / static_cast (voxelCount + 1))) // 3 points: old center * 2/3 + currentPoint * 1/3; + static_cast (referenceIterator.Get()) / static_cast (voxelCount + 1); voxelCount += 1.0; } } ++segmentationIterator; } // second pass for SD segmentationIterator.GoToBegin(); referenceIterator.GoToBegin(); while ( !segmentationIterator.IsAtEnd() ) { itk::Point< float, 3 > pt; segmentationItk->TransformIndexToPhysicalPoint( segmentationIterator.GetIndex(), pt ); typename ImageType::IndexType ind; itk::ContinuousIndex contInd; if (referenceImage->TransformPhysicalPointToContinuousIndex(pt, contInd)) { for (unsigned int i = 0; i < 3; ++i) ind[i] = ROUND_P(contInd[i]); referenceIterator.SetIndex( ind ); if ( segmentationIterator.Get() > 0 ) { sd += ((static_cast(referenceIterator.Get() ) - mean)*(static_cast(referenceIterator.Get() ) - mean)); } } ++segmentationIterator; } sd /= static_cast(voxelCount - 1); sd = sqrt( sd ); // generate quantiles TPixel histogramQuantileValues[5]; histogramQuantileValues[0] = m_ITKHistogram->Quantile(0, 0.05); histogramQuantileValues[1] = m_ITKHistogram->Quantile(0, 0.25); histogramQuantileValues[2] = m_ITKHistogram->Quantile(0, 0.50); histogramQuantileValues[3] = m_ITKHistogram->Quantile(0, 0.75); histogramQuantileValues[4] = m_ITKHistogram->Quantile(0, 0.95); // report histogram values std::locale C("C"); std::locale originalLocale = report.getloc(); report.imbue(C); report << " Minimum:" << minimum << "\n 5% quantile: " << histogramQuantileValues[0] << "\n 25% quantile: " << histogramQuantileValues[1] << "\n 50% quantile: " << histogramQuantileValues[2] << "\n 75% quantile: " << histogramQuantileValues[3] << "\n 95% quantile: " << histogramQuantileValues[4] << "\n Maximum: " << maximum << "\n Mean: " << mean << "\n SD: " << sd << "\n"; report.imbue(originalLocale); } std::string mitk::CalculateGrayValueStatisticsTool::GetReport() const { return m_CompleteReport.str(); } mitk::CalculateGrayValueStatisticsTool::HistogramType::ConstPointer mitk::CalculateGrayValueStatisticsTool::GetHistogram() { return m_ITKHistogram.GetPointer(); } diff --git a/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp b/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp index fe495a898a..8f3fe8e8b9 100644 --- a/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp +++ b/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp @@ -1,352 +1,353 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkPaintbrushTool.h" #include "mitkToolManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkBaseRenderer.h" +#include "mitkImageDataItem.h" #include "ipSegmentation.h" #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) int mitk::PaintbrushTool::m_Size = 1; mitk::PaintbrushTool::PaintbrushTool(int paintingPixelValue) :FeedbackContourTool("PressMoveReleaseWithCTRLInversionAllMouseMoves"), m_PaintingPixelValue(paintingPixelValue), m_LastContourSize(0) // other than initial mitk::PaintbrushTool::m_Size (around l. 28) { m_MasterContour = Contour::New(); m_MasterContour->Initialize(); } mitk::PaintbrushTool::~PaintbrushTool() { } void mitk::PaintbrushTool::Activated() { Superclass::Activated(); FeedbackContourTool::SetFeedbackContourVisible(true); SizeChanged.Send(m_Size); } void mitk::PaintbrushTool::Deactivated() { FeedbackContourTool::SetFeedbackContourVisible(false); Superclass::Deactivated(); } void mitk::PaintbrushTool::SetSize(int value) { m_Size = value; } void mitk::PaintbrushTool::UpdateContour(const StateEvent* stateEvent) { // examine stateEvent and create a contour that matches the pixel mask that we are going to draw const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return; Image::Pointer m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent ); if (m_WorkingSlice.IsNull()) return; // create a copy of this slice (at least match the pixel sizes/spacings), // then draw the desired mask on it and create a contour from it // Convert to ipMITKSegmentationTYPE (because getting pixels relys on that data type) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage( m_WorkingSlice, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeImage->SetDirection(imageDirection); Image::Pointer temporarySlice = Image::New(); CastToMitkImage( correctPixelTypeImage, temporarySlice ); mitkIpPicDescriptor* stupidClone = mitkIpPicClone( temporarySlice->GetSliceData()->GetPicDescriptor() ); unsigned int pixelWidth = m_Size + 1; unsigned int pixelHeight = m_Size + 1; if ( stupidClone->n[0] <= pixelWidth || stupidClone->n[1] <= pixelHeight ) { MITK_INFO << "Brush size is bigger than your working image. Reconsider this...\n" "(Or tell your progammer until (s)he fixes this message.)" << std::endl; mitkIpPicFree( stupidClone ); return; } unsigned int lineLength( stupidClone->n[0] ); unsigned int oneContourOffset(0); float circleCenterX = (float)m_Size / 2.0; float circleCenterY = (float)m_Size / 2.0; for (unsigned int x = 0; x <= pixelWidth; ++x) { for (unsigned int y = 0; y <= pixelHeight; ++y) { unsigned int offset = lineLength * y + x; ipMITKSegmentationTYPE* current = (ipMITKSegmentationTYPE*)stupidClone->data + offset; float pixelCenterX = x + 0.5; float pixelCenterY = y + 0.5; float xoff = pixelCenterX - circleCenterX; float yoff = pixelCenterY - circleCenterY; bool inside = xoff * xoff + yoff * yoff < (m_Size * m_Size) / 4.0; // no idea, if this would work for ellipses if (inside) { *current = 1; oneContourOffset = offset; } else { *current = 0; } } } int numberOfContourPoints( 0 ); int newBufferSize( 0 ); float* contourPoints = ipMITKSegmentationGetContour8N( stupidClone, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc if (!contourPoints) { mitkIpPicFree( stupidClone ); return; } // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; //ipMITKSegmentationGetContour8N returns all points, which causes vtk warnings, since the first and the last points are coincident. //leaving the last point out, the contour is still drawn correctly for (int index = 0; index < numberOfContourPoints-1; ++index) { newPoint[0] = contourPoints[ 2 * index + 0 ] - circleCenterX; // master contour should be centered around (0,0) newPoint[1] = contourPoints[ 2 * index + 1] - circleCenterY; newPoint[2] = 0.0; MITK_DEBUG << "Point [" << index << "] (" << newPoint[0] << ", " << newPoint[1] << ")" << std::endl; contourInImageIndexCoordinates->AddVertex( newPoint ); } free(contourPoints); m_MasterContour = contourInImageIndexCoordinates; mitkIpPicFree( stupidClone ); } /** Just show the contour, get one point as the central point and add surrounding points to the contour. */ bool mitk::PaintbrushTool::OnMousePressed (Action* action, const StateEvent* stateEvent) { if (FeedbackContourTool::OnMousePressed( action, stateEvent )) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (positionEvent) { UpdateContour( stateEvent ); } } return this->OnMouseMoved(action, stateEvent); /* return true; */ } /** Insert the point to the feedback contour,finish to build the contour and at the same time the painting function */ bool mitk::PaintbrushTool::OnMouseMoved (Action* itkNotUsed(action), const StateEvent* stateEvent) { bool leftMouseButtonPressed( stateEvent->GetId() == 530 || stateEvent->GetId() == 1 || stateEvent->GetId() == 5 ); const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if ( m_LastContourSize != m_Size ) { UpdateContour( stateEvent ); m_LastContourSize = m_Size; } DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if (!workingNode) return false; Image* image = dynamic_cast(workingNode->GetData()); const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); if ( !image || !planeGeometry ) return false; int affectedDimension( -1 ); int affectedSlice( -1 ); if ( !SegTool2D::DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ) ) return false; Point3D worldCoordinates = positionEvent->GetWorldPosition(); Point3D indexCoordinates; image->GetGeometry()->WorldToIndex( worldCoordinates, indexCoordinates ); MITK_DEBUG << "Mouse at W " << worldCoordinates << std::endl; MITK_DEBUG << "Mouse at I " << indexCoordinates << std::endl; unsigned int firstDimension(0); unsigned int secondDimension(1); switch( affectedDimension ) { case 2: // transversal default: firstDimension = 0; secondDimension = 1; break; case 1: // frontal firstDimension = 0; secondDimension = 2; break; case 0: // sagittal firstDimension = 1; secondDimension = 2; break; } // round to nearest voxel center (abort if this hasn't changed) if ( m_Size % 2 == 0 ) // even { indexCoordinates[firstDimension] = ROUND( indexCoordinates[firstDimension] + 0.5); indexCoordinates[secondDimension] = ROUND( indexCoordinates[secondDimension] + 0.5 ); } else // odd { indexCoordinates[firstDimension] = ROUND( indexCoordinates[firstDimension] ) ; indexCoordinates[secondDimension] = ROUND( indexCoordinates[secondDimension] ) ; } static Point3D lastPos; // uninitialized: if somebody finds out how this can be initialized in a one-liner, tell me static bool lastLeftMouseButtonPressed(false); if ( fabs(indexCoordinates[0] - lastPos[0]) > mitk::eps || fabs(indexCoordinates[1] - lastPos[1]) > mitk::eps || fabs(indexCoordinates[2] - lastPos[2]) > mitk::eps || leftMouseButtonPressed != lastLeftMouseButtonPressed ) { lastPos = indexCoordinates; lastLeftMouseButtonPressed = leftMouseButtonPressed; } else { MITK_DEBUG << "." << std::flush; return false; } MITK_DEBUG << "Mouse at C " << indexCoordinates; Contour::Pointer contour = Contour::New(); contour->Initialize(); for (unsigned int index = 0; index < m_MasterContour->GetNumberOfPoints(); ++index) { Point3D point = m_MasterContour->GetPoints()->ElementAt(index); point[0] += indexCoordinates[ firstDimension ]; point[1] += indexCoordinates[ secondDimension ]; MITK_DEBUG << "Contour point [" << index << "] :" << point; contour->AddVertex( point ); } Image::Pointer slice = SegTool2D::GetAffectedImageSliceAs2DImage( positionEvent, image ); if ( slice.IsNull() ) return false; if (leftMouseButtonPressed) { FeedbackContourTool::FillContourInSlice( contour, slice, m_PaintingPixelValue ); OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New(); slicewriter->SetInput( image ); slicewriter->SetCreateUndoInformation( true ); slicewriter->SetSliceImage( slice ); slicewriter->SetSliceDimension( affectedDimension ); slicewriter->SetSliceIndex( affectedSlice ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( image ) ); slicewriter->Update(); } // visualize contour Contour::Pointer displayContour = Contour::New(); displayContour->Initialize(); for (unsigned int index = 0; index < contour->GetNumberOfPoints(); ++index) { Point3D point = contour->GetPoints()->ElementAt(index); /*if ( m_Size % 2 != 0 ) // even { point[0] += 0.5; point[1] += 0.5; }*/ displayContour->AddVertex( point ); } displayContour = FeedbackContourTool::BackProjectContourFrom2DSlice( slice->GetGeometry(), displayContour ); SetFeedbackContour( *displayContour ); assert( positionEvent->GetSender()->GetRenderWindow() ); RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::PaintbrushTool::OnMouseReleased(Action* /*action*/, const StateEvent* /*stateEvent*/) { //FeedbackContourTool::SetFeedbackContourVisible(false); return true; } /** Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0. */ bool mitk::PaintbrushTool::OnInvertLogic(Action* action, const StateEvent* stateEvent) { if (!FeedbackContourTool::OnInvertLogic(action, stateEvent)) return false; // Inversion only for 0 and 1 as painting values if (m_PaintingPixelValue == 1) { m_PaintingPixelValue = 0; FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 ); } else if (m_PaintingPixelValue == 0) { m_PaintingPixelValue = 1; FeedbackContourTool::SetFeedbackContourColorDefault(); } return true; } diff --git a/Modules/MitkExt/Interactions/mitkPixelManipulationTool.cpp b/Modules/MitkExt/Interactions/mitkPixelManipulationTool.cpp index 2598485567..609fa1923f 100644 --- a/Modules/MitkExt/Interactions/mitkPixelManipulationTool.cpp +++ b/Modules/MitkExt/Interactions/mitkPixelManipulationTool.cpp @@ -1,171 +1,172 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 28959 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkPixelManipulationTool.h" #include "mitkToolManager.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkProperties.h" #include "mitkBoundingObjectToSegmentationFilter.h" #include #include "mitkPixelManipulationTool.xpm" namespace mitk { MITK_TOOL_MACRO(MitkExt_EXPORT, PixelManipulationTool, "Pixel manipulation tool"); } mitk::PixelManipulationTool::PixelManipulationTool() : Tool("dummy"), m_Value(0), m_FixedValue(false) { this->SupportRoiOn(); } mitk::PixelManipulationTool::~PixelManipulationTool() { } void mitk::PixelManipulationTool::Activated() { m_ToolManager->RoiDataChanged += mitk::MessageDelegate (this,&mitk::PixelManipulationTool::OnRoiDataChanged); m_OriginalImageNode = m_ToolManager->GetReferenceData(0); if (m_OriginalImageNode.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast (m_OriginalImageNode->GetData()); if ( image.IsNotNull()) { //mitk::ScalarType scalar = image->GetScalarValueMax(); } } else m_ToolManager->ActivateTool(-1); } void mitk::PixelManipulationTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate (this,&mitk::PixelManipulationTool::OnRoiDataChanged); } const char* mitk::PixelManipulationTool::GetName() const { return "pixelmanipulation"; } const char** mitk::PixelManipulationTool::GetXPM() const { return mitkPixelManipulationTool_xpm; } void mitk::PixelManipulationTool::OnRoiDataChanged() { } void mitk::PixelManipulationTool::CalculateImage() { if (m_OriginalImageNode.IsNotNull()) { mitk::Image::Pointer image = dynamic_cast (m_OriginalImageNode->GetData()); mitk::DataNode* maskNode = m_ToolManager->GetRoiData(0); mitk::Image::Pointer roi = mitk::Image::New(); if (maskNode) { mitk::BoundingObject* boundingObject = dynamic_cast (maskNode->GetData()); if (boundingObject) { mitk::BoundingObjectToSegmentationFilter::Pointer filter = mitk::BoundingObjectToSegmentationFilter::New(); filter->SetBoundingObject( boundingObject); filter->SetInput(image); filter->Update(); roi = filter->GetOutput(); } else roi = dynamic_cast (maskNode->GetData()); mitk::Image::Pointer newImage = mitk::Image::New(); newImage->Initialize(image); if (image) { AccessByItk_3(image, ITKPixelManipulation, roi, newImage, m_Value); this->AddImageToDataStorage(newImage); } } } } template void mitk::PixelManipulationTool::ITKPixelManipulation( itk::Image* originalImage, Image* maskImage, Image* newImage, int newValue) { typedef itk::Image< TPixel, VImageDimension> itkImageType; typedef itk::Image< unsigned char, 3> itkMaskType; typename itkImageType::Pointer itkImage; typename itkMaskType::Pointer itkMask; CastToItkImage( newImage, itkImage); CastToItkImage( maskImage, itkMask); typedef itk::ImageRegionConstIterator< itkImageType > InputIteratorType; typedef itk::ImageRegionIterator< itkImageType > OutputIteratorType; typedef itk::ImageRegionConstIterator< itkMaskType > MaskIteratorType; MaskIteratorType maskIterator ( itkMask, itkMask->GetLargestPossibleRegion() ); InputIteratorType inputIterator( originalImage, originalImage->GetLargestPossibleRegion() ); OutputIteratorType outputIterator( itkImage, itkImage->GetLargestPossibleRegion() ); inputIterator.GoToBegin(); outputIterator.GoToBegin(); maskIterator.GoToBegin(); while (!outputIterator.IsAtEnd()) { if (maskIterator.Get()) { if (m_FixedValue) outputIterator.Set(newValue); else outputIterator.Set( inputIterator.Get()+ newValue); } else outputIterator.Set( inputIterator.Get()); ++inputIterator; ++outputIterator; ++maskIterator; } } void mitk::PixelManipulationTool::AddImageToDataStorage(mitk::Image::Pointer image) { if (image.IsNotNull()) { mitk::DataNode::Pointer node = mitk::DataNode::New(); std::string name = m_OriginalImageNode->GetName(); name.append("_modified"); node->SetName(name); node->SetProperty("binary", mitk::BoolProperty::New(false)); node->SetData(image); if (m_ToolManager) m_ToolManager->GetDataStorage()->Add(node, m_OriginalImageNode); } -} \ No newline at end of file +} diff --git a/Modules/MitkExt/Interactions/mitkRegionGrow3DTool.cpp b/Modules/MitkExt/Interactions/mitkRegionGrow3DTool.cpp index 576f6b8683..e4a0b9e01d 100644 --- a/Modules/MitkExt/Interactions/mitkRegionGrow3DTool.cpp +++ b/Modules/MitkExt/Interactions/mitkRegionGrow3DTool.cpp @@ -1,441 +1,442 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 28959 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkRegionGrow3DTool.h" #include "mitkToolManager.h" #include "mitkRenderingManager.h" #include "mitkLevelWindowProperty.h" #include "mitkPointSetInteractor.h" #include "mitkGlobalInteraction.h" #include "mitkITKImageImport.h" #include "itkImage.h" #include "itkBinaryThresholdImageFilter.h" #include "itkConnectedAdaptiveThresholdImageFilter.h" #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include "mitkMaskAndCutRoiImageFilter.h" #include "mitkPadImageFilter.h" #include "mitkRegionGrow3DTool.xpm" namespace mitk { MITK_TOOL_MACRO(MitkExt_EXPORT, RegionGrow3DTool, "RegionGrower 3D"); } mitk::RegionGrow3DTool::RegionGrow3DTool(): Tool("PressMoveRelease"), m_LowerThreshold(-5000), m_UpperThreshold(5000), m_CurrentRGDirectionIsUpwards(false) { CONNECT_ACTION( 42, OnMouseReleased ); this->SupportRoiOn(); m_FeedbackNode = DataNode::New(); m_FeedbackNode->SetProperty( "color", ColorProperty::New(1.0, 0.0, 0.0) ); m_FeedbackNode->SetProperty( "texture interpolation", BoolProperty::New(false) ); m_FeedbackNode->SetProperty( "layer", IntProperty::New( 100 ) ); m_FeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(100, 1) ) ); m_FeedbackNode->SetProperty( "name", StringProperty::New("failsafe region grow feedback") ); m_FeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) ); m_FeedbackNode->SetProperty( "helper object", BoolProperty::New(true) ); m_FeedbackNode->SetVisibility(false); m_PointSetNode = mitk::DataNode::New(); m_PointSetNode->SetName("regiongrow3d pointset"); m_PointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_PointSetNode->SetProperty("layer", mitk::IntProperty::New(2)); mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); m_PointSetNode->SetData(pointSet); } mitk::RegionGrow3DTool::~RegionGrow3DTool() { } bool mitk::RegionGrow3DTool::OnMouseReleased(Action*, const StateEvent* stateEvent) { mitk::PointSetInteractor::Pointer interactor = dynamic_cast (m_PointSetNode->GetInteractor()); if (interactor.IsNotNull()) { mitk::PointSet::Pointer pointSet = dynamic_cast (m_PointSetNode->GetData()); if (pointSet.IsNotNull()) { if (pointSet->GetSize() == 1) { //check if we have a valid picture this->RunSegmentation(); SeedButtonToggled.Send(false); } } } return true; } void mitk::RegionGrow3DTool::Activated() { if (m_ToolManager) { m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::RegionGrow3DTool::UpdatePreview); m_OriginalImageNode = m_ToolManager->GetReferenceData(0); m_NodeToProceed = m_OriginalImageNode; if (m_NodeToProceed.IsNotNull()) { SetupPreviewNodeFor(m_NodeToProceed); mitk::Image::Pointer image = dynamic_cast (m_OriginalImageNode->GetData()); if (image.IsNotNull()) { m_RoiMin = image->GetScalarValueMin(); m_RoiMax = image->GetScalarValueMax(); } } else m_ToolManager->ActivateTool(-1); } } void mitk::RegionGrow3DTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::RegionGrow3DTool::UpdatePreview); if (mitk::DataStorage* ds = m_ToolManager->GetDataStorage()) { ds->Remove(m_PointSetNode); ds->Remove(m_FeedbackNode); } m_FeedbackNode->SetData(NULL); m_FeedbackNode->SetLevelWindow(NULL); m_FeedbackNode->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } const char* mitk::RegionGrow3DTool::GetName() const { return "RegionGrower 3D"; } const char** mitk::RegionGrow3DTool::GetXPM() const { return mitkRegionGrow3DTool_xpm; } void mitk::RegionGrow3DTool::SetSeedPoint(bool toggled) { if (!m_ToolManager->GetDataStorage()->Exists(m_PointSetNode)) //no pointSet present m_ToolManager->GetDataStorage()->Add(m_PointSetNode, m_OriginalImageNode); //add Interactor if there is none and add it to GlobalInteraction if (toggled == true) // button is down { mitk::PointSetInteractor::Pointer interactor = dynamic_cast (m_PointSetNode->GetInteractor()); if (interactor.IsNull()) { //create a new interactor and add it to node interactor = mitk::PointSetInteractor::New("singlepointinteractorwithoutshiftclick", m_PointSetNode, 1); } mitk::GlobalInteraction::GetInstance()->AddInteractor(interactor); } else { mitk::PointSetInteractor::Pointer interactor = dynamic_cast (m_PointSetNode->GetInteractor()); if (interactor.IsNotNull()) { m_PointSetNode->SetInteractor(NULL); mitk::GlobalInteraction::GetInstance()->RemoveInteractor(interactor); } } } void mitk::RegionGrow3DTool::RunSegmentation() { //safety if no pointSet or pointSet empty mitk::PointSet::Pointer seedPointSet = dynamic_cast (m_PointSetNode->GetData()); if (seedPointSet.IsNull()) { return; } if (!(seedPointSet->GetSize() > 0)) { return; } mitk::PointSet::PointType seedPoint = seedPointSet->GetPointSet()->GetPoints()->Begin().Value(); mitk::Image::Pointer image = dynamic_cast (m_NodeToProceed->GetData()); if (image.IsNotNull()) { m_LowerThreshold = static_cast (m_RoiMin); m_UpperThreshold = static_cast (m_RoiMax); AccessByItk_2(image, StartRegionGrowing, image->GetGeometry(), seedPoint); } } template void mitk::RegionGrow3DTool::StartRegionGrowing(itk::Image* itkImage, mitk::Geometry3D* imageGeometry, mitk::PointSet::PointType seedPoint) { typedef itk::Image InputImageType; typedef typename InputImageType::IndexType IndexType; typedef itk::ConnectedAdaptiveThresholdImageFilter RegionGrowingFilterType; typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); if ( !imageGeometry->IsInside(seedPoint) ) { return; } IndexType seedIndex; imageGeometry->WorldToIndex( seedPoint, seedIndex);// convert world coordinates to image indices //int seedValue = itkImage->GetPixel(seedIndex); regionGrower->SetInput( itkImage ); regionGrower->AddSeed( seedIndex ); regionGrower->SetLower( m_LowerThreshold ); regionGrower->SetUpper( m_UpperThreshold ); regionGrower->SetGrowingDirectionIsUpwards( m_CurrentRGDirectionIsUpwards ); try { regionGrower->Update(); } catch( ... ) { MITK_ERROR << "Something went wrong!" << endl; return; } m_SeedpointValue = regionGrower->GetSeedpointValue(); //initialize slider if(m_CurrentRGDirectionIsUpwards) { UpperThresholdValueChanged.Send(m_UpperThreshold); LowerThresholdValueChanged.Send(m_SeedpointValue); } else { UpperThresholdValueChanged.Send(m_SeedpointValue); LowerThresholdValueChanged.Send(m_LowerThreshold); } m_DetectedLeakagePoint = regionGrower->GetLeakagePoint(); mitk::Image::Pointer resultImage = mitk::ImportItkImage( regionGrower->GetOutput() ); m_FeedbackNode->SetData( resultImage ); m_FeedbackNode->SetVisibility(true); InitializeLevelWindow(); } void mitk::RegionGrow3DTool::InitializeLevelWindow() { mitk::LevelWindow tempLevelWindow; m_FeedbackNode->GetLevelWindow(tempLevelWindow, NULL, "levelWindow"); mitk::ScalarType* level = new mitk::ScalarType(0.5); mitk::ScalarType* window = new mitk::ScalarType(1); int upper; if (m_CurrentRGDirectionIsUpwards) { upper = m_UpperThreshold - m_SeedpointValue; } else { upper = m_SeedpointValue - m_LowerThreshold; } tempLevelWindow.SetRangeMinMax(mitk::ScalarType(0), mitk::ScalarType(upper)); tempLevelWindow.SetLevelWindow(*level, *window); m_FeedbackNode->SetLevelWindow(tempLevelWindow, NULL, "levelWindow"); //get the suggested threshold from the detected leakage-point and adjust the slider if (m_CurrentRGDirectionIsUpwards) { SliderValueChanged.Send(m_SeedpointValue + m_DetectedLeakagePoint -1); } else { SliderValueChanged.Send(m_SeedpointValue - m_DetectedLeakagePoint +1); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void mitk::RegionGrow3DTool::ChangeLevelWindow(int value) { if (m_FeedbackNode.IsNull()) return; mitk::LevelWindow tempLevelWindow; m_FeedbackNode->GetLevelWindow(tempLevelWindow, NULL, "levelWindow"); //get the levelWindow associated with the preview mitk::ScalarType level;// = this->m_UPPERTHRESHOLD - newValue + 0.5; mitk::ScalarType* window = new mitk::ScalarType(1); //adjust the levelwindow according to the position of the slider (newvalue) if (m_CurrentRGDirectionIsUpwards) { level = m_UpperThreshold - value + 0.5; tempLevelWindow.SetLevelWindow(level, *window); } else { level = value - m_LowerThreshold +0.5; tempLevelWindow.SetLevelWindow(level, *window); } m_FeedbackNode->SetLevelWindow(tempLevelWindow, NULL, "levelWindow"); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void mitk::RegionGrow3DTool::ConfirmSegmentation( std::string name, mitk::Color color) { mitk::DataNode::Pointer new_node = mitk::DataNode::New(); new_node->SetColor(color); new_node->SetName(name); new_node->SetProperty("binary", mitk::BoolProperty::New("true")); mitk::Image* image = dynamic_cast (m_FeedbackNode->GetData()); mitk::LevelWindow tempLevelWindow; m_FeedbackNode->GetLevelWindow( tempLevelWindow, NULL, "levelWindow"); int upperThresholdLabeledImage = (short int) tempLevelWindow.GetRangeMax(); int lowerThresholdLabeledImage = (short int) tempLevelWindow.GetLowerWindowBound() + 1; typedef itk::Image InputImageType; typedef itk::Image SegmentationType; typedef itk::BinaryThresholdImageFilter ThresholdFilterType; ThresholdFilterType::Pointer filter = ThresholdFilterType::New(); InputImageType::Pointer itkImage; mitk::CastToItkImage(image, itkImage); filter->SetInput(itkImage); filter->SetInsideValue(1); filter->SetOutsideValue(0); filter->SetUpperThreshold(upperThresholdLabeledImage); filter->SetLowerThreshold(lowerThresholdLabeledImage); filter->Update(); mitk::Image::Pointer new_image = mitk::Image::New(); mitk::CastToMitkImage(filter->GetOutput(), new_image); //pad to original size if (m_OriginalImageNode.GetPointer() != m_NodeToProceed.GetPointer()) { mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New(); padFilter->SetInput(0, new_image); padFilter->SetInput(1, dynamic_cast (m_OriginalImageNode->GetData())); padFilter->SetBinaryFilter(true); padFilter->SetUpperThreshold(1); padFilter->SetLowerThreshold(1); padFilter->Update(); new_image = padFilter->GetOutput(); } new_node->SetData(new_image); m_ToolManager->GetDataStorage()->Add(new_node); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_ToolManager->ActivateTool(-1); } void mitk::RegionGrow3DTool::CancelSegmentation() { m_ToolManager->ActivateTool(-1); } void mitk::RegionGrow3DTool::SetupPreviewNodeFor( DataNode* nodeToProceed) { if (nodeToProceed) { Image::Pointer image = dynamic_cast( nodeToProceed->GetData() ); if (image.IsNotNull()) { m_FeedbackNode->SetData( image ); int layer(50); nodeToProceed->GetIntProperty("layer", layer); m_FeedbackNode->SetIntProperty("layer", layer+1); m_FeedbackNode->SetLevelWindow(NULL); if (DataStorage* storage = m_ToolManager->GetDataStorage()) { if (storage->Exists(m_FeedbackNode)) storage->Remove(m_FeedbackNode); storage->Add( m_FeedbackNode, nodeToProceed ); } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void mitk::RegionGrow3DTool::UpdatePreview() { typedef itk::Image ItkImageType; typedef itk::Image ItkMaskType; mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0); if (node.IsNull()) { this->SetupPreviewNodeFor(m_OriginalImageNode); m_NodeToProceed = m_OriginalImageNode; mitk::Image::Pointer image = dynamic_cast (m_OriginalImageNode->GetData()); if (image.IsNotNull()) { m_RoiMin = image->GetScalarValueMin(); m_RoiMax = image->GetScalarValueMax(); } return; } mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New(); roiFilter->SetInput(dynamic_cast (m_NodeToProceed->GetData())); roiFilter->SetRegionOfInterest(node->GetData()); roiFilter->Update(); mitk::DataNode::Pointer new_node = mitk::DataNode::New(); mitk::Image::Pointer tmpImage = roiFilter->GetOutput(); new_node->SetData(tmpImage); m_RoiMax = roiFilter->GetMaxValue(); m_RoiMin = roiFilter->GetMinValue(); this->SetupPreviewNodeFor(new_node); m_NodeToProceed = new_node; //this->RunSegmentation(); } void mitk::RegionGrow3DTool::SetCurrentRGDirectionIsUpwards(bool flag) { m_CurrentRGDirectionIsUpwards = flag; } diff --git a/Modules/MitkExt/Interactions/mitkRegionGrowingTool.cpp b/Modules/MitkExt/Interactions/mitkRegionGrowingTool.cpp index de9b6efa1f..3c098bb5a0 100644 --- a/Modules/MitkExt/Interactions/mitkRegionGrowingTool.cpp +++ b/Modules/MitkExt/Interactions/mitkRegionGrowingTool.cpp @@ -1,711 +1,712 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkRegionGrowingTool.h" #include "mitkToolManager.h" #include "mitkOverwriteSliceImageFilter.h" +#include "mitkImageDataItem.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkApplicationCursor.h" #include "ipSegmentation.h" #include "mitkRegionGrowingTool.xpm" #include "mitkOverwriteDirectedPlaneImageFilter.h" #include "mitkExtractDirectedPlaneImageFilterNew.h" namespace mitk { MITK_TOOL_MACRO(MitkExt_EXPORT, RegionGrowingTool, "Region growing tool"); } #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) mitk::RegionGrowingTool::RegionGrowingTool() :FeedbackContourTool("PressMoveRelease"), m_LowerThreshold(200), m_UpperThreshold(200), m_InitialLowerThreshold(200), m_InitialUpperThreshold(200), m_ScreenYDifference(0), m_OriginalPicSlice(NULL), m_SeedPointMemoryOffset(0), m_VisibleWindow(0), m_DefaultWindow(0), m_MouseDistanceScaleFactor(3.0), m_LastWorkingSeed(-1), m_FillFeedbackContour(true) { } mitk::RegionGrowingTool::~RegionGrowingTool() { } const char** mitk::RegionGrowingTool::GetXPM() const { return mitkRegionGrowingTool_xpm; } const char* mitk::RegionGrowingTool::GetName() const { return "Region Growing"; } void mitk::RegionGrowingTool::Activated() { Superclass::Activated(); } void mitk::RegionGrowingTool::Deactivated() { Superclass::Deactivated(); } /** 1 Determine which slice is clicked into 2 Determine if the user clicked inside or outside of the segmentation 3 Depending on the pixel value under the mouse click position, two different things happen: (separated out into OnMousePressedInside and OnMousePressedOutside) 3.1 Create a skeletonization of the segmentation and try to find a nice cut 3.1.1 Call a ipSegmentation algorithm to create a nice cut 3.1.2 Set the result of this algorithm as the feedback contour 3.2 Initialize region growing 3.2.1 Determine memory offset inside the original image 3.2.2 Determine initial region growing parameters from the level window settings of the image 3.2.3 Perform a region growing (which generates a new feedback contour) */ bool mitk::RegionGrowingTool::OnMousePressed (Action* action, const StateEvent* stateEvent) { //ToolLogger::SetVerboseness(3); MITK_INFO << "OnMousePressed" << std::endl; if (FeedbackContourTool::OnMousePressed( action, stateEvent )) { MITK_INFO << "OnMousePressed: FeedbackContourTool says ok" << std::endl; // 1. Find out which slice the user clicked, find out which slice of the toolmanager's reference and working image corresponds to that const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (positionEvent) { MITK_INFO << "OnMousePressed: got positionEvent" << std::endl; m_ReferenceSlice = FeedbackContourTool::GetAffectedReferenceSlice( positionEvent ); m_WorkingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent ); if ( m_WorkingSlice.IsNotNull() ) // can't do anything without the segmentation { MITK_INFO << "OnMousePressed: got working slice" << std::endl; // 2. Determine if the user clicked inside or outside of the segmentation const Geometry3D* workingSliceGeometry = m_WorkingSlice->GetGeometry(); Point3D mprojectedPointIn2D; workingSliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D); itk::Index<2> projectedPointInWorkingSlice2D; projectedPointInWorkingSlice2D[0] = static_cast( mprojectedPointIn2D[0] - 0.5 ); projectedPointInWorkingSlice2D[1] = static_cast( mprojectedPointIn2D[1] - 0.5 ); if ( workingSliceGeometry->IsIndexInside( projectedPointInWorkingSlice2D ) ) { MITK_INFO << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << projectedPointInWorkingSlice2D << ") IS in working slice" << std::endl; // Convert to ipMITKSegmentationTYPE (because getting pixels relys on that data type) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage( m_WorkingSlice, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); // possible bug in CastToItkImage ? // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479: // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed // solution here: we overwrite it with an unity matrix itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeImage->SetDirection(imageDirection); Image::Pointer temporarySlice = Image::New(); // temporarySlice = ImportItkImage( correctPixelTypeImage ); CastToMitkImage( correctPixelTypeImage, temporarySlice ); mitkIpPicDescriptor* workingPicSlice = temporarySlice->GetSliceData()->GetPicDescriptor(); int initialWorkingOffset = projectedPointInWorkingSlice2D[1] * workingPicSlice->n[0] + projectedPointInWorkingSlice2D[0]; if ( initialWorkingOffset < static_cast( workingPicSlice->n[0] * workingPicSlice->n[1] ) && initialWorkingOffset >= 0 ) { // 3. determine the pixel value under the last click bool inside = static_cast(workingPicSlice->data)[initialWorkingOffset] != 0; m_PaintingPixelValue = inside ? 0 : 1; // if inside, we want to remove a part, otherwise we want to add something if ( m_LastWorkingSeed >= static_cast( workingPicSlice->n[0] * workingPicSlice->n[1] ) || m_LastWorkingSeed < 0 ) { inside = false; } if ( m_ReferenceSlice.IsNotNull() ) { MITK_INFO << "OnMousePressed: got reference slice" << std::endl; m_OriginalPicSlice = m_ReferenceSlice->GetSliceData()->GetPicDescriptor(); // 3.1. Switch depending on the pixel value if (inside) { OnMousePressedInside(action, stateEvent, workingPicSlice, initialWorkingOffset); } else { OnMousePressedOutside(action, stateEvent); } } } } } } } MITK_INFO << "end OnMousePressed" << std::endl; return true; } /** 3.1 Create a skeletonization of the segmentation and try to find a nice cut 3.1.1 Call a ipSegmentation algorithm to create a nice cut 3.1.2 Set the result of this algorithm as the feedback contour */ bool mitk::RegionGrowingTool::OnMousePressedInside(Action* itkNotUsed( action ), const StateEvent* stateEvent, mitkIpPicDescriptor* workingPicSlice, int initialWorkingOffset) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); // checked in OnMousePressed // 3.1.1. Create a skeletonization of the segmentation and try to find a nice cut // apply the skeletonization-and-cut algorithm // generate contour to remove // set m_ReferenceSlice = NULL so nothing will happen during mouse move // remember to fill the contour with 0 in mouserelease mitkIpPicDescriptor* segmentationHistory = ipMITKSegmentationCreateGrowerHistory( workingPicSlice, m_LastWorkingSeed, NULL ); // free again if (segmentationHistory) { tCutResult cutContour = ipMITKSegmentationGetCutPoints( workingPicSlice, segmentationHistory, initialWorkingOffset ); // tCutResult is a ipSegmentation type mitkIpPicFree( segmentationHistory ); if (cutContour.cutIt) { // 3.1.2 copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < cutContour.deleteSize; ++index) { newPoint[0] = cutContour.deleteCurve[ 2 * index + 0 ]; newPoint[1] = cutContour.deleteCurve[ 2 * index + 1 ]; newPoint[2] = 0.0; contourInImageIndexCoordinates->AddVertex( newPoint - 0.5 ); } free(cutContour.traceline); free(cutContour.deleteCurve); // perhaps visualize this for fun? free(cutContour.onGradient); Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correction FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates ); FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); m_FillFeedbackContour = true; } else { m_FillFeedbackContour = false; } } else { m_FillFeedbackContour = false; } m_ReferenceSlice = NULL; return true; } /** 3.2 Initialize region growing 3.2.1 Determine memory offset inside the original image 3.2.2 Determine initial region growing parameters from the level window settings of the image 3.2.3 Perform a region growing (which generates a new feedback contour) */ bool mitk::RegionGrowingTool::OnMousePressedOutside(Action* itkNotUsed( action ), const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); // checked in OnMousePressed // 3.2 If we have a reference image, then perform an initial region growing, considering the reference image's level window // if click was outside the image, don't continue const Geometry3D* sliceGeometry = m_ReferenceSlice->GetGeometry(); Point3D mprojectedPointIn2D; sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), mprojectedPointIn2D ); itk::Index<2> projectedPointIn2D; projectedPointIn2D[0] = static_cast( mprojectedPointIn2D[0] - 0.5 ); projectedPointIn2D[1] = static_cast( mprojectedPointIn2D[1] - 0.5 ); if ( sliceGeometry->IsIndexInside( mprojectedPointIn2D ) ) { MITK_INFO << "OnMousePressed: point " << positionEvent->GetWorldPosition() << " (index coordinates " << mprojectedPointIn2D << ") IS in reference slice" << std::endl; // 3.2.1 Remember Y cursor position and initial seed point //m_ScreenYPositionAtStart = static_cast(positionEvent->GetDisplayPosition()[1]); m_LastScreenPosition = ApplicationCursor::GetInstance()->GetCursorPosition(); m_ScreenYDifference = 0; m_SeedPointMemoryOffset = projectedPointIn2D[1] * m_OriginalPicSlice->n[0] + projectedPointIn2D[0]; m_LastWorkingSeed = m_SeedPointMemoryOffset; // remember for skeletonization if ( m_SeedPointMemoryOffset < static_cast( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] ) && m_SeedPointMemoryOffset >= 0 ) { // 3.2.2 Get level window from reference DataNode // Use some logic to determine initial gray value bounds LevelWindow lw(0, 500); m_ToolManager->GetReferenceData(0)->GetLevelWindow(lw); // will fill lw if levelwindow property is present, otherwise won't touch it. m_VisibleWindow = lw.GetWindow(); // necessary for limiting the upper and lower threshold to the maximum gray values m_DefaultWindow = lw.GetDefaultWindow(); static bool initializedAlready = false; // just evaluated once if (!initializedAlready) { m_InitialLowerThreshold = static_cast(m_VisibleWindow / 10.0); // 20% of the visible gray values m_InitialUpperThreshold = static_cast(m_VisibleWindow / 10.0); initializedAlready = true; } m_LowerThreshold = m_InitialLowerThreshold; m_UpperThreshold = m_InitialUpperThreshold; DisplayGeometry* displayGeometry = positionEvent->GetSender()->GetDisplayGeometry(); if (displayGeometry) { m_MouseDistanceScaleFactor = m_VisibleWindow / ( 3.0 * displayGeometry->GetDisplayHeight() ); } // 3.2.3. Actually perform region growing mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(); ipMITKSegmentationFree( result); // display the contour FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); m_FillFeedbackContour = true; } } return true; } /** If in region growing mode (m_ReferenceSlice != NULL), then 1. Calculate the new thresholds from mouse position (relative to first position) 2. Perform a new region growing and update the feedback contour */ bool mitk::RegionGrowingTool::OnMouseMoved (Action* action, const StateEvent* stateEvent) { if (FeedbackContourTool::OnMouseMoved( action, stateEvent )) { if ( m_ReferenceSlice.IsNotNull() && m_OriginalPicSlice ) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (positionEvent) { ApplicationCursor* cursor = ApplicationCursor::GetInstance(); if (!cursor) return false; m_ScreenYDifference += cursor->GetCursorPosition()[1] - m_LastScreenPosition[1]; cursor->SetCursorPosition( m_LastScreenPosition ); m_LowerThreshold = m_InitialLowerThreshold + static_cast( m_ScreenYDifference * m_MouseDistanceScaleFactor ); if (m_LowerThreshold < 1) m_LowerThreshold = 1; if (m_LowerThreshold > m_VisibleWindow / 2) m_LowerThreshold = m_VisibleWindow / 2; m_UpperThreshold = m_InitialUpperThreshold + static_cast( m_ScreenYDifference * m_MouseDistanceScaleFactor ); if (m_UpperThreshold < 1) m_UpperThreshold = 1; if (m_UpperThreshold > m_VisibleWindow / 2) m_UpperThreshold = m_VisibleWindow / 2; //MITK_INFO << "new interval: l " << m_LowerThreshold << " u " << m_UpperThreshold << std::endl; // 2. Perform region growing again and show the result mitkIpPicDescriptor* result = PerformRegionGrowingAndUpdateContour(); ipMITKSegmentationFree( result ); // 3. Update the contour mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(positionEvent->GetSender()->GetRenderWindow()); } } } return true; } /** If the feedback contour should be filled, then it is done here. (Contour is NOT filled, when skeletonization is done but no nice cut was found) */ bool mitk::RegionGrowingTool::OnMouseReleased(Action* action, const StateEvent* stateEvent) { if (FeedbackContourTool::OnMouseReleased( action, stateEvent )) { // 1. If we have a working slice, use the contour to fill a new piece on segmentation on it (or erase a piece that was selected by ipMITKSegmentationGetCutPoints) if ( m_WorkingSlice.IsNotNull() && m_OriginalPicSlice ) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (positionEvent) { // remember parameters for next time m_InitialLowerThreshold = m_LowerThreshold; m_InitialUpperThreshold = m_UpperThreshold; if (m_FillFeedbackContour) { // 3. use contour to fill a region in our working slice Contour* feedbackContour( FeedbackContourTool::GetFeedbackContour() ); if (feedbackContour) { Contour::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( m_WorkingSlice, feedbackContour, false, false ); // false: don't add any 0.5 // false: don't constrain the contour to the image's inside if (projectedContour.IsNotNull()) { FeedbackContourTool::FillContourInSlice( projectedContour, m_WorkingSlice, m_PaintingPixelValue ); // 4. write working slice back into image volume int affectedDimension( -1 ); int affectedSlice( -1 ); const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); FeedbackContourTool::DetermineAffectedImageSlice( dynamic_cast( m_ToolManager->GetWorkingData(0)->GetData() ), planeGeometry, affectedDimension, affectedSlice ); MITK_INFO << "OnMouseReleased: writing back to dimension " << affectedDimension << ", slice " << affectedSlice << " in working image" << std::endl; //If dazu gemacht Image::Pointer workingImage = dynamic_cast( m_ToolManager->GetWorkingData(0)->GetData() ); if ( affectedDimension != -1 ) { OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New(); slicewriter->SetInput( workingImage ); slicewriter->SetCreateUndoInformation( true ); slicewriter->SetSliceImage( m_WorkingSlice ); slicewriter->SetSliceDimension( affectedDimension ); slicewriter->SetSliceIndex( affectedSlice ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( workingImage ) ); slicewriter->Update(); if ( m_ToolManager->GetRememberContourPosition() ) { this->AddContourmarker(positionEvent); } } else { OverwriteDirectedPlaneImageFilter::Pointer slicewriter = OverwriteDirectedPlaneImageFilter::New(); slicewriter->SetInput( workingImage ); slicewriter->SetCreateUndoInformation( false ); slicewriter->SetSliceImage( m_WorkingSlice ); slicewriter->SetPlaneGeometry3D( m_WorkingSlice->GetGeometry() ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( workingImage ) ); slicewriter->Update(); if ( m_ToolManager->GetRememberContourPosition() ) { this->AddContourmarker(positionEvent); } } } } } FeedbackContourTool::SetFeedbackContourVisible(false); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); } } } m_ReferenceSlice = NULL; // don't leak m_WorkingSlice = NULL; m_OriginalPicSlice = NULL; return true; } /** Uses ipSegmentation algorithms to do the actual region growing. The result (binary image) is first smoothed by a 5x5 circle mask, then its contour is extracted and converted to MITK coordinates. */ mitkIpPicDescriptor* mitk::RegionGrowingTool::PerformRegionGrowingAndUpdateContour() { // 1. m_OriginalPicSlice and m_SeedPointMemoryOffset are set to sensitive values, as well as m_LowerThreshold and m_UpperThreshold assert (m_OriginalPicSlice); if (m_OriginalPicSlice->n[0] != 256 || m_OriginalPicSlice->n[1] != 256) // ??? assert( (m_SeedPointMemoryOffset < static_cast( m_OriginalPicSlice->n[0] * m_OriginalPicSlice->n[1] )) && (m_SeedPointMemoryOffset >= 0) ); // inside the image // 2. ipSegmentation is used to perform region growing float ignored; int oneContourOffset( 0 ); mitkIpPicDescriptor* regionGrowerResult = ipMITKSegmentationGrowRegion4N( m_OriginalPicSlice, m_SeedPointMemoryOffset, // seed point true, // grayvalue interval relative to seed point gray value? m_LowerThreshold, m_UpperThreshold, 0, // continue until done (maxIterations == 0) NULL, // allocate new memory (only this time, on mouse move we'll reuse the old buffer) oneContourOffset, // a pixel that is near the resulting contour ignored // ignored by us ); if (!regionGrowerResult || oneContourOffset == -1) { Contour::Pointer dummyContour = Contour::New(); dummyContour->Initialize(); FeedbackContourTool::SetFeedbackContour( *dummyContour ); if (regionGrowerResult) ipMITKSegmentationFree(regionGrowerResult); return NULL; } // 3. We smooth the result a little to reduce contour complexity bool smoothResult( true ); // currently fixed, perhaps remove else block mitkIpPicDescriptor* smoothedRegionGrowerResult; if (smoothResult) { // Smooth the result (otherwise very detailed contour) smoothedRegionGrowerResult = SmoothIPPicBinaryImage( regionGrowerResult, oneContourOffset ); ipMITKSegmentationFree( regionGrowerResult ); } else { smoothedRegionGrowerResult = regionGrowerResult; } // 4. convert the result of region growing into a mitk::Contour // At this point oneContourOffset could be useless, if smoothing destroyed a thin bridge. In these // cases, we have two or more unconnected segmentation regions, and we don't know, which one is touched by oneContourOffset. // In the bad case, the contour is not the one around our seedpoint, so the result looks very strange to the user. // -> we remove the point where the contour started so far. Then we look from the bottom of the image for the first segmentation pixel // and start another contour extraction from there. This is done, until the seedpoint is inside the contour int numberOfContourPoints( 0 ); int newBufferSize( 0 ); float* contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc if (contourPoints) { while ( !ipMITKSegmentationIsInsideContour( contourPoints, // contour numberOfContourPoints, // points in contour m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0], // test point x m_SeedPointMemoryOffset / smoothedRegionGrowerResult->n[0] // test point y ) ) { // we decide that this cannot be part of the segmentation because the seedpoint is not contained in the contour (fill the 4-neighborhood with 0) ipMITKSegmentationReplaceRegion4N( smoothedRegionGrowerResult, oneContourOffset, 0 ); // move the contour offset to the last row (x position of the seed point) int rowLength = smoothedRegionGrowerResult->n[0]; // number of pixels in a row oneContourOffset = m_SeedPointMemoryOffset % smoothedRegionGrowerResult->n[0] // x of seed point + rowLength*(smoothedRegionGrowerResult->n[1]-1); // y of last row while ( oneContourOffset >=0 && (*(static_cast(smoothedRegionGrowerResult->data) + oneContourOffset) == 0) ) { oneContourOffset -= rowLength; // if pixel at data+oneContourOffset is 0, then move up one row } if ( oneContourOffset < 0 ) { break; // just use the last contour we found } free(contourPoints); // release contour memory contourPoints = ipMITKSegmentationGetContour8N( smoothedRegionGrowerResult, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc } // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < numberOfContourPoints; ++index) { newPoint[0] = contourPoints[ 2 * index + 0 ]; newPoint[1] = contourPoints[ 2 * index + 1 ]; newPoint[2] = 0; contourInImageIndexCoordinates->AddVertex( newPoint - 0.5); } free(contourPoints); Contour::Pointer contourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( m_ReferenceSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true: sub 0.5 for ipSegmentation correctio FeedbackContourTool::SetFeedbackContour( *contourInWorldCoordinates ); } // 5. Result HAS TO BE freed by caller, contains the binary region growing result return smoothedRegionGrowerResult; } /** Helper method for SmoothIPPicBinaryImage. Smoothes a given part of and image. \param sourceImage The original binary image. \param dest The smoothed image (will be written without bounds checking). \param contourOfs One offset of the contour. Is updated if a pixel is changed (which might change the contour). \param maskOffsets Memory offsets that describe the smoothing mask. \param maskSize Entries of the mask. \param startOffset First pixel that should be smoothed using this mask. \param endOffset Last pixel that should be smoothed using this mask. */ void mitk::RegionGrowingTool::SmoothIPPicBinaryImageHelperForRows( mitkIpPicDescriptor* sourceImage, mitkIpPicDescriptor* dest, int &contourOfs, int* maskOffsets, int maskSize, int startOffset, int endOffset ) { // work on the very first row ipMITKSegmentationTYPE* current; ipMITKSegmentationTYPE* source = ((ipMITKSegmentationTYPE*)sourceImage->data) + startOffset; // + 1! don't read at start-1 ipMITKSegmentationTYPE* end = ((ipMITKSegmentationTYPE*)dest->data) + endOffset; int ofs = startOffset; int minority = (maskSize - 1) / 2; for (current = ((ipMITKSegmentationTYPE*)dest->data) + startOffset; current minority) { *current = 1; contourOfs = ofs; } else { *current = 0; } ++source; ++ofs; } } /** Smoothes a binary ipPic image with a 5x5 mask. The image borders (some first and last rows) are treated differently. */ mitkIpPicDescriptor* mitk::RegionGrowingTool::SmoothIPPicBinaryImage( mitkIpPicDescriptor* image, int &contourOfs, mitkIpPicDescriptor* dest ) { if (!image) return NULL; // Original code from /trunk/mbi-qm/Qmitk/Qmitk2DSegTools/RegionGrowerTool.cpp (first version by T. Boettger?). Reformatted and documented and restructured. #define MSK_SIZE5x5 21 #define MSK_SIZE3x3 5 #define MSK_SIZE3x1 3 // mask is an array of coordinates that form a rastered circle like this // // OOO // OOOOO // OOOOO // OOOOO // OOO // // int mask5x5[MSK_SIZE5x5][2] = { /******/ {-1,-2}, {0,-2}, {1,-2}, /*****/ {-2,-1}, {-1,-1}, {0,-1}, {1,-1}, {2,-1}, {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, /******/ {-1, 2}, {0, 2}, {1, 2} /*****/ }; int mask3x3[MSK_SIZE3x3][2] = { /******/ {0,-1}, /*****/ {-1, 0}, {0, 0}, {1, 0}, /******/ {0, 1} /*****/ }; int mask3x1[MSK_SIZE3x1][2] = { {-1, 0}, {0, 0}, {1, 0} }; // The following lines iterate over all the pixels of a (sliced) image (except the first and last three rows). // For each pixel, all the coordinates around it (according to mask) are evaluated (this means 21 pixels). // If more than 10 of the evaluated pixels are non-zero, then the central pixel is set to 1, else to 0. // This is determining a majority. If there is no clear majority, then the central pixel itself "decides". int maskOffset5x5[MSK_SIZE5x5]; int line = image->n[0]; for (int i=0; in[0]; int spareOut1Rows = 1*image->n[0]; if ( image->n[1] > 0 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, 1, dest->n[0] ); if ( image->n[1] > 3 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, spareOut1Rows, dest->n[0]*3 ); if ( image->n[1] > 6 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset5x5, MSK_SIZE5x5, spareOut3Rows, dest->n[0]*dest->n[1] - spareOut3Rows ); if ( image->n[1] > 8 ) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x3, MSK_SIZE3x3, dest->n[0]*dest->n[1] -spareOut3Rows, dest->n[0]*dest->n[1] - spareOut1Rows ); if ( image->n[1] > 10) SmoothIPPicBinaryImageHelperForRows( image, dest, contourOfs, maskOffset3x1, MSK_SIZE3x1, dest->n[0]*dest->n[1] -spareOut1Rows, dest->n[0]*dest->n[1] - 1 ); // correction for first pixel (sorry for the ugliness) if ( *((ipMITKSegmentationTYPE*)(dest->data)+1) == 1 ) { *((ipMITKSegmentationTYPE*)(dest->data)+0) = 1; } if (dest->n[0] * dest->n[1] > 2) { // correction for last pixel if ( *((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-2) == 1 ) { *((ipMITKSegmentationTYPE*)(dest->data)+dest->n[0]*dest->n[1]-1) = 1; } } return dest; } diff --git a/Modules/MitkExt/Interactions/mitkSetRegionTool.cpp b/Modules/MitkExt/Interactions/mitkSetRegionTool.cpp index 0b054eedf1..cc442927ac 100644 --- a/Modules/MitkExt/Interactions/mitkSetRegionTool.cpp +++ b/Modules/MitkExt/Interactions/mitkSetRegionTool.cpp @@ -1,351 +1,352 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkSetRegionTool.h" #include "mitkToolManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "ipSegmentation.h" #include "mitkBaseRenderer.h" +#include "mitkImageDataItem.h" #include "mitkOverwriteDirectedPlaneImageFilter.h" mitk::SetRegionTool::SetRegionTool(int paintingPixelValue) :FeedbackContourTool("PressMoveReleaseWithCTRLInversion"), m_PaintingPixelValue(paintingPixelValue), m_FillContour(false), m_StatusFillWholeSlice(false) { } mitk::SetRegionTool::~SetRegionTool() { } void mitk::SetRegionTool::Activated() { Superclass::Activated(); } void mitk::SetRegionTool::Deactivated() { Superclass::Deactivated(); } bool mitk::SetRegionTool::OnMousePressed (Action* action, const StateEvent* stateEvent) { if (!FeedbackContourTool::OnMousePressed( action, stateEvent )) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; // 1. Get the working image Image::Pointer workingSlice = FeedbackContourTool::GetAffectedWorkingSlice( positionEvent ); if ( workingSlice.IsNull() ) return false; // can't do anything without the segmentation // if click was outside the image, don't continue const Geometry3D* sliceGeometry = workingSlice->GetGeometry(); itk::Index<2> projectedPointIn2D; sliceGeometry->WorldToIndex( positionEvent->GetWorldPosition(), projectedPointIn2D ); if ( !sliceGeometry->IsIndexInside( projectedPointIn2D ) ) { MITK_ERROR << "point apparently not inside segmentation slice" << std::endl; return false; // can't use that as a seed point } // Convert to ipMITKSegmentationTYPE (because ipMITKSegmentationGetContour8N relys on that data type) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage( workingSlice, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); // possible bug in CastToItkImage ? // direction maxtrix is wrong/broken/not working after CastToItkImage, leading to a failed assertion in // mitk/Core/DataStructures/mitkSlicedGeometry3D.cpp, 479: // virtual void mitk::SlicedGeometry3D::SetSpacing(const mitk::Vector3D&): Assertion `aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0' failed // solution here: we overwrite it with an unity matrix itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeImage->SetDirection(imageDirection); Image::Pointer temporarySlice = Image::New(); // temporarySlice = ImportItkImage( correctPixelTypeImage ); CastToMitkImage( correctPixelTypeImage, temporarySlice ); // check index positions mitkIpPicDescriptor* originalPicSlice = temporarySlice->GetSliceData()->GetPicDescriptor(); int m_SeedPointMemoryOffset = projectedPointIn2D[1] * originalPicSlice->n[0] + projectedPointIn2D[0]; if ( m_SeedPointMemoryOffset >= static_cast( originalPicSlice->n[0] * originalPicSlice->n[1] ) || m_SeedPointMemoryOffset < 0 ) { MITK_ERROR << "Memory offset calculation if mitk::SetRegionTool has some serious flaw! Aborting.." << std::endl; return false; } // 2. Determine the contour that surronds the selected "piece of the image" // find a contour seed point unsigned int oneContourOffset = static_cast( m_SeedPointMemoryOffset ); // safe because of earlier check if m_SeedPointMemoryOffset < 0 /** * The logic of finding a starting point for the contour is the following: * * - If the initial seed point is 0, we are either inside a hole or outside of every segmentation. * We move to the right until we hit a 1, which must be part of a contour. * * - If the initial seed point is 1, then ... * we now do the same (running to the right) until we hit a 1 * * In both cases the found contour point is used to extract a contour and * then a test is applied to find out if the initial seed point is contained * in the contour. If this is the case, filling should be applied, otherwise * nothing is done. */ unsigned int size = originalPicSlice->n[0] * originalPicSlice->n[1]; /* unsigned int rowSize = originalPicSlice->n[0]; */ ipMITKSegmentationTYPE* data = static_cast(originalPicSlice->data); if ( data[oneContourOffset] == 0 ) // initial seed 0 { for ( ; oneContourOffset < size; ++oneContourOffset ) { if ( data[oneContourOffset] > 0 ) break; } } else if ( data[oneContourOffset] == 1 ) // initial seed 1 { unsigned int lastValidPixel = size-1; // initialization, will be changed lateron bool inSeg = true; // inside segmentation? for ( ; oneContourOffset < size; ++oneContourOffset ) { if ( ( data[oneContourOffset] == 0 ) && inSeg ) // pixel 0 and inside-flag set: this happens at the first pixel outside a filled region { inSeg = false; lastValidPixel = oneContourOffset - 1; // store the last pixel position inside a filled region break; } else // pixel 1, inside-flag doesn't matter: this happens while we are inside a filled region { inSeg = true; // first iteration lands here } } oneContourOffset = lastValidPixel; } else { MITK_ERROR << "Fill/Erase was never intended to work with other than binary images." << std::endl; m_FillContour = false; return false; } if (oneContourOffset == size) // nothing found until end of slice { m_FillContour = false; return false; } int numberOfContourPoints( 0 ); int newBufferSize( 0 ); //MITK_INFO << "getting contour from offset " << oneContourOffset << " ("<n[0]<<","<n[0]<<")"< 0); bool cursorInsideContour = ipMITKSegmentationIsInsideContour( contourPoints, numberOfContourPoints, projectedPointIn2D[0], projectedPointIn2D[1]); // decide if contour should be filled or not m_FillContour = cursorInsideContour; if (m_FillContour) { // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; for (int index = 0; index < numberOfContourPoints; ++index) { newPoint[0] = contourPoints[ 2 * index + 0 ]; newPoint[1] = contourPoints[ 2 * index + 1]; newPoint[2] = 0; contourInImageIndexCoordinates->AddVertex( newPoint - 0.5 ); } m_SegmentationContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N // 3. Show the contour FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates ); FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); } // always generate a second contour, containing the whole image (used when CTRL is pressed) { // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; newPoint[0] = 0; newPoint[1] = 0; newPoint[2] = 0.0; contourInImageIndexCoordinates->AddVertex( newPoint ); newPoint[0] = originalPicSlice->n[0]; newPoint[1] = 0; newPoint[2] = 0.0; contourInImageIndexCoordinates->AddVertex( newPoint ); newPoint[0] = originalPicSlice->n[0]; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0; contourInImageIndexCoordinates->AddVertex( newPoint ); newPoint[0] = 0; newPoint[1] = originalPicSlice->n[1]; newPoint[2] = 0.0; contourInImageIndexCoordinates->AddVertex( newPoint ); m_WholeImageContourInWorldCoordinates = FeedbackContourTool::BackProjectContourFrom2DSlice( workingSlice->GetGeometry(), contourInImageIndexCoordinates, true ); // true, correct the result from ipMITKSegmentationGetContour8N // 3. Show the contour FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates ); FeedbackContourTool::SetFeedbackContourVisible(true); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); } free(contourPoints); return true; } bool mitk::SetRegionTool::OnMouseReleased(Action* action, const StateEvent* stateEvent) { // 1. Hide the feedback contour, find out which slice the user clicked, find out which slice of the toolmanager's working image corresponds to that FeedbackContourTool::SetFeedbackContourVisible(false); const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); if (!m_FillContour && !m_StatusFillWholeSlice) return true; if (!FeedbackContourTool::OnMouseReleased( action, stateEvent )) return false; DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if (!workingNode) return false; Image* image = dynamic_cast(workingNode->GetData()); const PlaneGeometry* planeGeometry( dynamic_cast (positionEvent->GetSender()->GetCurrentWorldGeometry2D() ) ); if ( !image || !planeGeometry ) return false; int affectedDimension( -1 ); int affectedSlice( -1 ); FeedbackContourTool::DetermineAffectedImageSlice( image, planeGeometry, affectedDimension, affectedSlice ); Image::Pointer slice = FeedbackContourTool::GetAffectedImageSliceAs2DImage( positionEvent, image ); if ( slice.IsNull() ) { MITK_ERROR << "Unable to extract slice." << std::endl; return false; } Contour* feedbackContour( FeedbackContourTool::GetFeedbackContour() ); Contour::Pointer projectedContour = FeedbackContourTool::ProjectContourTo2DSlice( slice, feedbackContour, false, false ); // false: don't add 0.5 (done by FillContourInSlice) // false: don't constrain the contour to the image's inside if (projectedContour.IsNull()) return false; FeedbackContourTool::FillContourInSlice( projectedContour, slice, m_PaintingPixelValue ); if ( affectedDimension != -1 ) { // 5. Write the modified 2D working data slice back into the image OverwriteSliceImageFilter::Pointer slicewriter = OverwriteSliceImageFilter::New(); slicewriter->SetInput( image ); slicewriter->SetCreateUndoInformation( true ); slicewriter->SetSliceImage( slice ); slicewriter->SetSliceDimension( affectedDimension ); slicewriter->SetSliceIndex( affectedSlice ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( image ) ); slicewriter->Update(); if ( m_ToolManager->GetRememberContourPosition() ) { this->AddContourmarker(positionEvent); } } else if ( affectedDimension == -1 ) { OverwriteDirectedPlaneImageFilter::Pointer slicewriter = OverwriteDirectedPlaneImageFilter::New(); slicewriter->SetInput( image ); slicewriter->SetCreateUndoInformation( false ); slicewriter->SetSliceImage( slice ); slicewriter->SetPlaneGeometry3D( slice->GetGeometry() ); slicewriter->SetTimeStep( positionEvent->GetSender()->GetTimeStep( image ) ); slicewriter->Update(); if ( m_ToolManager->GetRememberContourPosition() ) { this->AddContourmarker(positionEvent); } } else { MITK_ERROR << "FeedbackContourTool could not determine which slice of the image you are drawing on." << std::endl; } // 6. Make sure the result is drawn again --> is visible then. assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); m_WholeImageContourInWorldCoordinates = NULL; m_SegmentationContourInWorldCoordinates = NULL; return true; } /** Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0. */ bool mitk::SetRegionTool::OnInvertLogic(Action* action, const StateEvent* stateEvent) { if (!FeedbackContourTool::OnInvertLogic(action, stateEvent)) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if (m_StatusFillWholeSlice) { // use contour extracted from image data if (m_SegmentationContourInWorldCoordinates.IsNotNull()) FeedbackContourTool::SetFeedbackContour( *m_SegmentationContourInWorldCoordinates ); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); } else { // use some artificial contour if (m_WholeImageContourInWorldCoordinates.IsNotNull()) FeedbackContourTool::SetFeedbackContour( *m_WholeImageContourInWorldCoordinates ); mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); } m_StatusFillWholeSlice = !m_StatusFillWholeSlice; return true; } diff --git a/Modules/MitkExt/Testing/mitkCompareImageSliceTestHelper.h b/Modules/MitkExt/Testing/mitkCompareImageSliceTestHelper.h index 4762e50a45..2f2b4cf113 100644 --- a/Modules/MitkExt/Testing/mitkCompareImageSliceTestHelper.h +++ b/Modules/MitkExt/Testing/mitkCompareImageSliceTestHelper.h @@ -1,161 +1,163 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef mitkCompareImageSliceTestHelperhincluded #define mitkCompareImageSliceTestHelperhincluded #include "mitkImageCast.h" +#include "mitkImageAccessByItk.h" #include #include // copied from mitk/Core/Algorithms/mitkOverwriteSliceImageFilter.cpp // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h #define myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \ if ( typeId == typeid(pixeltype) ) \ { \ typedef itk::Image ImageType; \ typedef mitk::ImageToItk ImageToItkType; \ itk::SmartPointer imagetoitk = ImageToItkType::New(); \ imagetoitk->SetInput(mitkImage); \ imagetoitk->Update(); \ itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \ } #define myMITKOverwriteSliceImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \ { \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \ } class CompareImageSliceTestHelper { private: /* variables to be used by CompareSlice only */ static unsigned int m_Dimension0; static unsigned int m_Dimension1; static unsigned int m_SliceDimension; static unsigned int m_SliceIndex; static bool m_ComparisonResult; static mitk::Image* m_SliceImage; public: template static void ItkImageCompare( itk::Image* inputImage, itk::Image* outputImage ) { m_ComparisonResult = false; typedef itk::Image SliceImageType; typedef itk::Image VolumeImageType; typedef itk::ImageSliceConstIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< SliceImageType > InputSliceIteratorType; typename VolumeImageType::RegionType sliceInVolumeRegion; sliceInVolumeRegion = outputImage->GetLargestPossibleRegion(); sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion ); outputIterator.SetFirstDirection(m_Dimension0); outputIterator.SetSecondDirection(m_Dimension1); InputSliceIteratorType inputIterator( inputImage, inputImage->GetLargestPossibleRegion() ); // iterate over output slice (and over input slice simultaneously) outputIterator.GoToBegin(); inputIterator.GoToBegin(); while ( !outputIterator.IsAtEnd() ) { while ( !outputIterator.IsAtEndOfSlice() ) { while ( !outputIterator.IsAtEndOfLine() ) { m_ComparisonResult = outputIterator.Get() == (TPixel2) inputIterator.Get(); if (!m_ComparisonResult) return; // return on first mismatch ++outputIterator; ++inputIterator; } outputIterator.NextLine(); } outputIterator.NextSlice(); } } template static void ItkImageSwitch( itk::Image* itkImage ) { const std::type_info& typeId=*(m_SliceImage->GetPixelType().GetTypeId()); - myMITKOverwriteSliceImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageCompare, 2, itkImage ); + //myMITKOverwriteSliceImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageCompare, 2, itkImage ); + AccessFixedDimensionByItk_n(m_SliceImage, ItkImageCompare, 2, itkImage) } static bool CompareSlice( mitk::Image* image, unsigned int sliceDimension, unsigned int sliceIndex, mitk::Image* slice ) { if ( !image || ! slice ) return false; switch (sliceDimension) { default: case 2: m_Dimension0 = 0; m_Dimension1 = 1; break; case 1: m_Dimension0 = 0; m_Dimension1 = 2; break; case 0: m_Dimension0 = 1; m_Dimension1 = 2; break; } if ( slice->GetDimension() != 2 || image->GetDimension() != 3 || slice->GetDimension(0) != image->GetDimension(m_Dimension0) || slice->GetDimension(1) != image->GetDimension(m_Dimension1) ) { std::cerr << "Slice and image dimensions differ. Sorry, cannot work like this." << std::endl; return false; } // this will do a long long if/else to find out both pixel typesA m_SliceImage = slice; m_SliceIndex = sliceIndex; m_SliceDimension = sliceDimension; m_ComparisonResult = false; AccessFixedDimensionByItk( image, ItkImageSwitch, 3 ); return m_ComparisonResult; } }; // end class #endif diff --git a/Modules/QmitkExt/QmitkFunctionalityComponents/QmitkThresholdComponent.cpp b/Modules/QmitkExt/QmitkFunctionalityComponents/QmitkThresholdComponent.cpp index 6d2d791c2e..459944acad 100644 --- a/Modules/QmitkExt/QmitkFunctionalityComponents/QmitkThresholdComponent.cpp +++ b/Modules/QmitkExt/QmitkFunctionalityComponents/QmitkThresholdComponent.cpp @@ -1,637 +1,638 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkThresholdComponent.h" #include "ui_QmitkThresholdComponentControls.h" #include #include #include "mitkRenderingManager.h" #include "mitkProperties.h" #include "mitkDataNodeFactory.h" #include "mitkImageTimeSelector.h" #include "mitkLevelWindowProperty.h" #include #include #include #include #include #include #include +#include #include //#include #include /*************** CONSTRUCTOR ***************/ QmitkThresholdComponent::QmitkThresholdComponent(QObject * parent, const char * parentName, bool updateSelector, bool showSelector, QmitkStdMultiWidget * /*mitkStdMultiWidget*/) : QmitkFunctionalityComponentContainer(parent, parentName, updateSelector, showSelector), m_ThresholdImageNode(NULL), m_ThresholdComponentGUI(NULL), m_ThresholdNodeExisting(false) { SetAvailability(true); SetComponentName("ThresholdFinder"); } /*************** DESTRUCTOR ***************/ QmitkThresholdComponent::~QmitkThresholdComponent() { } /************** SET SELECTOR VISIBILITY ***************/ void QmitkThresholdComponent::SetSelectorVisibility(bool /*visibility*/) { if(m_ThresholdComponentGUI) { //m_ImageContent->setShown(visibility); m_ImageContent->setShown(true); } } /*************** GET IMAGE CONTENT ***************/ QGroupBox* QmitkThresholdComponent::GetImageContent() { return (QGroupBox*) m_ImageContent; } /*************** GET TREE NODE SELECTOR ***************/ QmitkDataStorageComboBox* QmitkThresholdComponent::GetTreeNodeSelector() { return m_TreeNodeSelector; } /*************** CONNECTIONS ***************/ void QmitkThresholdComponent::CreateConnections() { if ( m_ThresholdComponentGUI ) { connect( (QObject*)(m_TreeNodeSelector), SIGNAL(OnSelectionChanged (const mitk::DataNode *)), (QObject*) this, SLOT(ImageSelected(const mitk::DataNode *))); connect( (QObject*)(m_ThresholdFinder), SIGNAL(toggled(bool)), (QObject*) this, SLOT(ShowThresholdFinderContent(bool))); connect( (QObject*)(m_ThresholdSelectDataGroupBox), SIGNAL(toggled(bool)), (QObject*) this, SLOT(ShowImageContent(bool))); connect( (QObject*)(m_ThresholdInputSlider), SIGNAL(sliderMoved(int)), (QObject*) this, SLOT(ThresholdSliderChanged(int))); connect( (QObject*)(m_ThresholdInputNumber), SIGNAL(returnPressed()), (QObject*) this, SLOT(ThresholdValueChanged())); //connect( (QObject*)( m_ShowThresholdGroupBox), SIGNAL(toggled(bool)), (QObject*) this, SLOT(ShowThreshold(bool))); //to connect the toplevel checkable GroupBox with the method SetContentContainerVisibility to inform all containing komponent to shrink or to expand connect( (QObject*)(m_ThresholdFinder), SIGNAL(toggled(bool)), (QObject*) this, SLOT(SetContentContainerVisibility(bool))); connect( (QObject*)(m_CreateSegmentationButton), SIGNAL(released()), (QObject*) this, SLOT(CreateThresholdSegmentation())); } } /*************** DATA STORAGE CHANGED ***************/ void QmitkThresholdComponent::DataStorageChanged(mitk::DataStorage::Pointer ds) { if(!ds) return; m_DataStorage = ds; m_TreeNodeSelector->SetDataStorage(ds); if(m_ThresholdComponentGUI != NULL) { for(unsigned int i = 0; i < m_AddedChildList.size(); i++) { QmitkBaseFunctionalityComponent* functionalityComponent = dynamic_cast(m_AddedChildList[i]); if (functionalityComponent != NULL) functionalityComponent->DataStorageChanged(ds); } } if(!ds) return; DataObjectSelected(); SetSliderRange(); ShowThreshold(); } /*************** IMAGE SELECTED ***************/ void QmitkThresholdComponent::ImageSelected(const mitk::DataNode* item) { if(m_ThresholdComponentGUI != NULL) { mitk::DataNode::Pointer selectedItem = const_cast< mitk::DataNode*>(item); m_TreeNodeSelector->SetSelectedNode(selectedItem); for(unsigned int i = 0; i < m_AddedChildList.size(); i++) { QmitkBaseFunctionalityComponent* functionalityComponent = dynamic_cast(m_AddedChildList[i]); if (functionalityComponent != NULL) functionalityComponent->ImageSelected(item); } } DataObjectSelected(); SetSliderRange(); ShowThreshold(); } /*************** DATA OBJECT SELECTED **************/ void QmitkThresholdComponent::DataObjectSelected() { if(m_Active) { if(m_ThresholdNodeExisting) { m_ThresholdImageNode->SetData(m_TreeNodeSelector->GetSelectedNode()->GetData()); } else { CreateThresholdImageNode(); m_ThresholdImageNode->SetData(m_TreeNodeSelector->GetSelectedNode()->GetData()); } ShowThreshold(); } } /** \brief Method to set the DataStorage*/ void QmitkThresholdComponent::SetDataStorage(mitk::DataStorage::Pointer dataStorage) { m_DataStorage = dataStorage; } /** \brief Method to get the DataStorage*/ mitk::DataStorage::Pointer QmitkThresholdComponent::GetDataStorage() { return m_DataStorage; } /*************** CREATE CONTAINER WIDGET **************/ void QmitkThresholdComponent::CreateQtPartControl(QWidget * /*parent*/, mitk::DataStorage::Pointer dataStorage) { m_GUI = new QWidget; m_ThresholdComponentGUI = new Ui::QmitkThresholdComponentControls; m_ThresholdComponentGUI->setupUi(m_GUI); /*CREATE GUI ELEMENTS*/ m_ThresholdFinder = new QGroupBox("2. Find Threshold", m_GUI); m_ThresholdSelectDataGroupBox = new QGroupBox("Show Image Selector", m_ThresholdFinder); m_TreeNodeSelector = new QmitkDataStorageComboBox(m_ThresholdSelectDataGroupBox); m_ImageContent = new QGroupBox("m_ImageContent", m_ThresholdSelectDataGroupBox); m_ContainerContent = new QGroupBox(m_ImageContent); m_ShowThresholdGroupBox = new QGroupBox("m_ShowThresholdGroupBox", m_ContainerContent); m_ThresholdInputNumber = new QLineEdit(m_ShowThresholdGroupBox); m_ThresholdInputSlider = new QSlider(m_ShowThresholdGroupBox); m_ThresholdInputSlider->setOrientation(Qt::Horizontal); m_ThresholdValueContent = new QGroupBox("m_ThresholdValueContent", m_ShowThresholdGroupBox); m_CreateSegmentationButton = new QPushButton("Create Segmentation", m_ThresholdValueContent); m_DeleateImageIfDeactivatedCheckBox = new QCheckBox("Deleate Threshold Image if \nComponent is deactivated", m_ThresholdValueContent); m_ThresholdFinder->setCheckable(true); m_ThresholdFinder->setChecked(true); m_ThresholdSelectDataGroupBox->setCheckable(true); m_ThresholdSelectDataGroupBox->setChecked(true); m_ThresholdInputNumber->setFixedSize(40, 20); QIntValidator* intValid = new QIntValidator(-32000, 5000, m_ThresholdInputNumber); m_ThresholdInputNumber->setValidator(intValid); m_ThresholdInputNumber->setText("0"); m_ThresholdValueContent->setMaximumHeight(90); // m_ThresholdSelectDataGroupBox->setContentsMargins(0,9,9,9); // m_ImageContent->setContentsMargins(0,9,9,9); // m_ContainerContent->setContentsMargins(0,9,9,9); // m_ShowThresholdGroupBox->setContentsMargins(0,9,9,9); //m_ThresholdValueContent->setContentsMargins(0,9,9,9); //m_ThresholdFinder->setFlat(true); //m_ThresholdSelectDataGroupBox->setFlat(true); //m_ImageContent->setFlat(true); //m_ContainerContent->setFlat(true); //m_ShowThresholdGroupBox->setFlat(true); //m_ThresholdValueContent->setFlat(true); QVBoxLayout* guiLayout = new QVBoxLayout(m_GUI); m_GUI->setLayout(guiLayout); guiLayout->addWidget(m_ThresholdFinder); QVBoxLayout* thresholdFinderLayout = new QVBoxLayout(m_ThresholdFinder); thresholdFinderLayout->setContentsMargins(0,9,0,9); m_ThresholdFinder->setLayout(thresholdFinderLayout); thresholdFinderLayout->addWidget(m_ThresholdSelectDataGroupBox); thresholdFinderLayout->addWidget(m_ImageContent); QVBoxLayout* thresholdSelectDataGroupBoxLayout = new QVBoxLayout(m_ThresholdSelectDataGroupBox); thresholdSelectDataGroupBoxLayout->setContentsMargins(0,9,0,9); m_ThresholdSelectDataGroupBox->setLayout(thresholdSelectDataGroupBoxLayout); thresholdSelectDataGroupBoxLayout->addWidget(m_TreeNodeSelector); QVBoxLayout* imageContentLayout = new QVBoxLayout(m_ImageContent); imageContentLayout->setContentsMargins(0,9,0,9); m_ImageContent->setLayout(imageContentLayout); imageContentLayout->addWidget(m_ContainerContent); QVBoxLayout* containerContentLayout = new QVBoxLayout(m_ContainerContent); containerContentLayout->setContentsMargins(0,9,0,9); m_ContainerContent->setLayout(containerContentLayout); containerContentLayout->addWidget(m_ShowThresholdGroupBox); QVBoxLayout* showThresholdGroupBoxLayout = new QVBoxLayout(m_ShowThresholdGroupBox); showThresholdGroupBoxLayout->setContentsMargins(0,9,0,9); m_ShowThresholdGroupBox->setLayout(showThresholdGroupBoxLayout); QHBoxLayout* thresholdInputLayout = new QHBoxLayout(m_ShowThresholdGroupBox); thresholdInputLayout->addWidget(m_ThresholdInputNumber); thresholdInputLayout->addWidget(m_ThresholdInputSlider); showThresholdGroupBoxLayout->addLayout(thresholdInputLayout); showThresholdGroupBoxLayout->addWidget(m_ThresholdValueContent); QVBoxLayout* thresholdValueContentLayout = new QVBoxLayout(m_ThresholdValueContent); thresholdValueContentLayout->setContentsMargins(0,9,0,9); m_ThresholdValueContent->setLayout(thresholdValueContentLayout); thresholdValueContentLayout->addWidget(m_DeleateImageIfDeactivatedCheckBox); thresholdValueContentLayout->addWidget(m_CreateSegmentationButton); this->CreateConnections(); SetDataStorage(dataStorage); m_TreeNodeSelector->SetDataStorage(dataStorage); m_TreeNodeSelector->SetPredicate(mitk::NodePredicateDataType::New("Image")); if(m_ShowSelector) { m_ImageContent->setShown( m_ThresholdSelectDataGroupBox->isChecked()); //m_ImageContent->setShown(true); } else { m_ThresholdSelectDataGroupBox->setShown(m_ShowSelector); //m_ThresholdSelectDataGroupBox->setShown(true); } } /*************** GET CONTENT CONTAINER ***************/ QGroupBox * QmitkThresholdComponent::GetContentContainer() { return m_ContainerContent; } /************ GET MAIN CHECK BOX CONTAINER ************/ QGroupBox * QmitkThresholdComponent::GetMainCheckBoxContainer() { return m_ThresholdFinder; } ///*********** SET CONTENT CONTAINER VISIBLE ************/ //void QmitkThresholdComponent::SetContentContainerVisibility() //{ // for(unsigned int i = 0; i < m_AddedChildList.size(); i++) // { // if(m_AddedChildList[i]->GetContentContainer() != NULL) // { // m_AddedChildList[i]->GetContentContainer()->setShown(GetMainCheckBoxContainer()->isChecked()); // } // } //} /*************** ACTIVATED ***************/ void QmitkThresholdComponent::Activated() { QmitkBaseFunctionalityComponent::Activated(); m_Active = true; for(unsigned int i = 0; i < m_AddedChildList.size(); i++) { m_AddedChildList[i]->Activated(); } CreateThresholdImageNode(); ShowThreshold(); SetSliderRange(); } /*************** DEACTIVATED ***************/ void QmitkThresholdComponent::Deactivated() { QmitkBaseFunctionalityComponent::Deactivated(); m_Active = false; for(unsigned int i = 0; i < m_AddedChildList.size(); i++) { m_AddedChildList[i]->Deactivated(); } ShowThreshold(); if( m_DeleateImageIfDeactivatedCheckBox->isChecked()) { DeleteThresholdNode(); } } ///************ SHOW THRESHOLD FINDER CONTENT ***********/ void QmitkThresholdComponent::ShowThresholdFinderContent(bool) { // m_ShowThresholdGroupBox->setShown( m_ThresholdFinder->isChecked()); // m_ContainerContent->setShown( m_ThresholdSelectDataGroupBox->isChecked()); m_ContainerContent->setShown( m_ThresholdFinder->isChecked()); if(m_ShowSelector) { //m_ThresholdSelectDataGroupBox->setShown( m_ThresholdSelectDataGroupBox->isChecked()); //m_ThresholdSelectDataGroupBox->setShown( true); m_ThresholdSelectDataGroupBox->setShown(m_ThresholdFinder->isChecked()); } //ShowThreshold(); } ///*************** SHOW IMAGE CONTENT **************/ void QmitkThresholdComponent::ShowImageContent(bool) { //m_ImageContent->setShown( m_ThresholdSelectDataGroupBox->isChecked()); m_ImageContent->setShown( true); if(m_ShowSelector) { //m_ImageContent->setShown( m_ThresholdSelectDataGroupBox->isChecked()); m_ImageContent->setShown( true); } else { //m_ThresholdSelectDataGroupBox->setShown(m_ShowSelector); m_ThresholdSelectDataGroupBox->setShown(true); } } ///*************** SHOW THRESHOLD **************/ void QmitkThresholdComponent::ShowThreshold(bool) { if(m_ThresholdImageNode) { if(m_Active == true) { m_ThresholdImageNode->SetProperty("visible", mitk::BoolProperty::New(( m_ThresholdFinder->isChecked())) ); } else { if( m_DeleateImageIfDeactivatedCheckBox->isChecked()) { m_ThresholdImageNode->SetProperty("visible", mitk::BoolProperty::New((false)) ); } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } ///*************** THRESHOLD VALUE CHANGED **************/ //By Slider void QmitkThresholdComponent::ThresholdSliderChanged(int) { int value = m_ThresholdInputSlider->value(); if (m_ThresholdImageNode) { m_ThresholdImageNode->SetLevelWindow(mitk::LevelWindow(value,1)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } m_ThresholdInputNumber->setText(QString::number(value)); } ///*************** THRESHOLD VALUE CHANGED **************/ //By LineEdit void QmitkThresholdComponent::ThresholdValueChanged( ) { int value = atoi( m_ThresholdInputNumber->text().toLocal8Bit().constData() ); if (m_ThresholdImageNode) { m_ThresholdImageNode->SetLevelWindow(mitk::LevelWindow(value,1)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } m_ThresholdInputSlider->setValue(value); } ///*************** SET SLIDER RANGE **************/ void QmitkThresholdComponent::SetSliderRange() { if(m_Active) { if( m_ThresholdFinder->isChecked()==true) { if(!m_TreeNodeSelector->GetSelectedNode()) return; if(!m_TreeNodeSelector->GetSelectedNode()->GetData()) return; mitk::Image* currentImage = dynamic_cast(m_TreeNodeSelector->GetSelectedNode()->GetData()); if(currentImage) { int min = (int) currentImage->GetScalarValueMin(); int max = (int) currentImage->GetScalarValueMaxNoRecompute(); //int realMax = currentImage->GetScalarValueMax(); if(min < -32000) { min = (int) currentImage->GetScalarValue2ndMin(); max = (int) currentImage->GetScalarValue2ndMaxNoRecompute(); } QIntValidator* intValid = new QIntValidator(min-150, max+150, m_ThresholdInputNumber); m_ThresholdInputNumber->setValidator(intValid); m_ThresholdInputNumber->setText("1"); m_ThresholdInputSlider->setMinimum(min-150); m_ThresholdInputSlider->setMaximum(max+150); m_ThresholdInputSlider->setRange(min-150, max+150); m_ThresholdInputSlider->setPageStep(1); m_ThresholdInputSlider->setValue(1); m_GUI->repaint(); //m_ThresholdInputSlider->resize(); /* m_ThresholdInputSlider->setMinValue((int)currentImage->GetScalarValueMin()); m_ThresholdInputSlider->setMaxValue((int)currentImage->GetScalarValueMaxNoRecompute());*/ } } } } ///*************** DELETE THRESHOLD NODE **************/ void QmitkThresholdComponent::DeleteThresholdNode() { if(m_ThresholdImageNode) { mitk::DataNode::Pointer foundNode = m_DataStorage->GetNamedNode("Thresholdview image"); foundNode->Delete(); m_ThresholdNodeExisting = false; return; } } ///*************CREATE THRESHOLD IMAGE NODE************/ void QmitkThresholdComponent::CreateThresholdImageNode() { if(m_Active) { if( m_ThresholdNodeExisting) return; if(!m_TreeNodeSelector) return; if(!m_TreeNodeSelector->GetSelectedNode()) return; m_ThresholdImageNode = mitk::DataNode::New(); mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New("Thresholdview image" ); m_ThresholdImageNode->SetProperty( "name", nameProp ); mitk::BoolProperty::Pointer componentThresholdImageProp = mitk::BoolProperty::New(true); m_ThresholdImageNode->SetProperty( "isComponentThresholdImage", componentThresholdImageProp ); m_ThresholdImageNode->SetData(m_TreeNodeSelector->GetSelectedNode()->GetData()); m_ThresholdImageNode->SetColor(0.0,1.0,0.0); m_ThresholdImageNode->SetOpacity(.25); int layer = 0; m_ThresholdImageNode->GetIntProperty("layer", layer); m_ThresholdImageNode->SetIntProperty("layer", layer+1); m_ThresholdImageNode->SetLevelWindow(mitk::LevelWindow(atoi( m_ThresholdInputNumber->text().toLocal8Bit().constData()),1)); m_ThresholdNodeExisting = true; m_DataStorage->Add(m_ThresholdImageNode); } } /*************CREAET THRESHOLD SEGMENTATION************/ void QmitkThresholdComponent::CreateThresholdSegmentation() { mitk::Image::Pointer original = dynamic_cast(m_TreeNodeSelector->GetSelectedNode()->GetData()); // we NEED a reference image for size etc. if (!original) return; // actually create a new empty segmentation mitk::PixelType pixelType( typeid(DefaultSegmentationDataType) ); mitk::Image::Pointer segmentation = mitk::Image::New(); //segmentation->SetProperty( "organ type", OrganTypeProperty::New( organType ) ); segmentation->Initialize( pixelType, original->GetDimension(), original->GetDimensions() ); unsigned int byteSize = sizeof(DefaultSegmentationDataType); for (unsigned int dim = 0; dim < segmentation->GetDimension(); ++dim) { byteSize *= segmentation->GetDimension(dim); } memset( segmentation->GetData(), 0, byteSize ); if (original->GetTimeSlicedGeometry() ) { mitk::AffineGeometryFrame3D::Pointer originalGeometryAGF = original->GetTimeSlicedGeometry()->Clone(); mitk::TimeSlicedGeometry::Pointer originalGeometry = dynamic_cast( originalGeometryAGF.GetPointer() ); segmentation->SetGeometry( originalGeometry ); } else { MITK_INFO<<"Original image does not have a 'Time sliced geometry'! Cannot create a segmentation."; return ; } mitk::DataNode::Pointer emptySegmentationNode = CreateSegmentationNode( segmentation); if (emptySegmentationNode) { // actually perform a thresholding and ask for an organ type for (unsigned int timeStep = 0; timeStep < original->GetTimeSteps(); ++timeStep) { try { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput( original ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); mitk::Image::Pointer image3D = timeSelector->GetOutput(); AccessFixedDimensionByItk_2( image3D, ITKThresholding, 3, dynamic_cast(emptySegmentationNode->GetData()), timeStep ); } catch(...) { MITK_INFO<<"Error accessing single time steps of the original image. Cannot create segmentation."; } } mitk::DataNode::Pointer originalNode = m_TreeNodeSelector->GetSelectedNode(); m_DataStorage->Add( emptySegmentationNode, originalNode ); // add as a child, because the segmentation "derives" from the original } } mitk::DataNode::Pointer QmitkThresholdComponent::CreateSegmentationNode( mitk::Image* image) { if (!image) return NULL; // decorate the datatreenode with some properties mitk::DataNode::Pointer segmentationNode = mitk::DataNode::New(); segmentationNode->SetData( image ); // name segmentationNode->SetProperty( "name", mitk::StringProperty::New( "TH segmentation from ThresholdFinder" ) ); // visualization properties segmentationNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); segmentationNode->SetProperty( "color", mitk::ColorProperty::New(0.0, 1.0, 0.0) ); segmentationNode->SetProperty( "texture interpolation", mitk::BoolProperty::New(false) ); segmentationNode->SetProperty( "layer", mitk::IntProperty::New(10) ); segmentationNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0.5, 1) ) ); segmentationNode->SetProperty( "opacity", mitk::FloatProperty::New(0.3) ); segmentationNode->SetProperty( "segmentation", mitk::BoolProperty::New(true) ); segmentationNode->SetProperty( "showVolume", mitk::BoolProperty::New( false ) ); return segmentationNode; } template void QmitkThresholdComponent::ITKThresholding( itk::Image* originalImage, mitk::Image* segmentation, unsigned int timeStep ) { mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput( segmentation ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); mitk::Image::Pointer segmentation3D = timeSelector->GetOutput(); typedef itk::Image< DefaultSegmentationDataType, 3> SegmentationType; // this is sure for new segmentations SegmentationType::Pointer itkSegmentation; CastToItkImage( segmentation3D, itkSegmentation ); // iterate over original and segmentation typedef itk::ImageRegionConstIterator< itk::Image > InputIteratorType; typedef itk::ImageRegionIterator< SegmentationType > SegmentationIteratorType; InputIteratorType inputIterator( originalImage, originalImage->GetLargestPossibleRegion() ); SegmentationIteratorType outputIterator( itkSegmentation, itkSegmentation->GetLargestPossibleRegion() ); inputIterator.GoToBegin(); outputIterator.GoToBegin(); while (!outputIterator.IsAtEnd()) { if ( (signed)inputIterator.Get() >= atoi( m_ThresholdInputNumber->text().toLocal8Bit().constData()) ) { outputIterator.Set( 1 ); } else { outputIterator.Set( 0 ); } ++inputIterator; ++outputIterator; } } diff --git a/Modules/RigidRegistration/mitkImageRegistrationMethod-TYPE.cpp b/Modules/RigidRegistration/mitkImageRegistrationMethod-TYPE.cpp index c0e6f779c8..dd77931bd4 100644 --- a/Modules/RigidRegistration/mitkImageRegistrationMethod-TYPE.cpp +++ b/Modules/RigidRegistration/mitkImageRegistrationMethod-TYPE.cpp @@ -1,23 +1,24 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include +#include #define InstantiateAccessFunction_RegistrationAccessItkImage(pixelType, dim) \ template void mitk::ImageRegistrationMethodAccessFunctor::AccessItkImage(itk::Image* itkImage1, mitk::ImageRegistrationMethod* method); InstantiateAccessFunctionForFixedPixelType(RegistrationAccessItkImage, @TYPE@) diff --git a/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.h b/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.h index 2fe79a01b7..cd3a7dbbbd 100644 --- a/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.h +++ b/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.h @@ -1,43 +1,43 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKIMAGEREGISTRATIONMETHODACCESSFUNCTOR_H #define MITKIMAGEREGISTRATIONMETHODACCESSFUNCTOR_H #include namespace mitk { class ImageRegistrationMethod; struct ImageRegistrationMethodAccessFunctor { typedef ImageRegistrationMethodAccessFunctor Self; void operator()(const mitk::Image* img, ImageRegistrationMethod* method) { - AccessDefaultPixelTypesByItk_1(img, ImageRegistrationMethod*, method) + AccessByItk_1(img, AccessItkImage, method) } template < typename TPixel, unsigned int VImageDimension > void AccessItkImage( itk::Image* itkImage1, ImageRegistrationMethod* method); }; } #endif // MITKIMAGEREGISTRATIONMETHODACCESSFUNCTOR_H diff --git a/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.txx b/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.txx index 8a8cef1b0d..7351fede91 100644 --- a/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.txx +++ b/Modules/RigidRegistration/mitkImageRegistrationMethodAccessFunctor.txx @@ -1,155 +1,157 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. method software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkImageRegistrationMethodAccessFunctor.h" #include "mitkImageRegistrationMethod.h" +#include + #include namespace mitk { template void ImageRegistrationMethodAccessFunctor::AccessItkImage(itk::Image* itkImage1, ImageRegistrationMethod* method) { //convert mitk masks to itk masks typedef typename itk::Image FixedImageType; typedef typename itk::Image MovingImageType; typedef typename itk::Image< unsigned char, VImageDimension > MaskImageType; typedef typename itk::ImageMaskSpatialObject< VImageDimension > ImageMaskType; typename ImageMaskType::Pointer movingImageMask; if(method->m_MovingMask.IsNotNull()) { typename MovingImageType::Pointer movingMask = MovingImageType::New(); mitk::CastToItkImage(method->m_MovingMask, movingMask); typename itk::CastImageFilter::Pointer maskImageCaster = itk::CastImageFilter::New(); maskImageCaster->SetInput(movingMask); maskImageCaster->UpdateLargestPossibleRegion(); movingImageMask = ImageMaskType::New(); movingImageMask->SetImage(maskImageCaster->GetOutput()); } typename ImageMaskType::Pointer fixedImageMask; if(method->m_FixedMask.IsNotNull()) { typename FixedImageType::Pointer fixedMask = FixedImageType::New(); mitk::CastToItkImage(method->m_FixedMask, fixedMask); typename itk::CastImageFilter::Pointer maskImageCaster = itk::CastImageFilter::New(); maskImageCaster->SetInput(fixedMask); maskImageCaster->UpdateLargestPossibleRegion(); fixedImageMask = ImageMaskType::New(); fixedImageMask->SetImage(maskImageCaster->GetOutput()); } // typedefs typedef typename itk::Image FixedImageType; typedef typename itk::Image MovingImageType; typedef typename itk::LinearInterpolateImageFunction InterpolatorType; typedef itk::NearestNeighborInterpolateImageFunction InterpolatorType2; typedef typename itk::ImageRegistrationMethod RegistrationType; typedef typename itk::Transform< double, VImageDimension, VImageDimension > TransformType; typedef typename TransformType::Pointer TransformPointer; typedef typename itk::ImageToImageMetric MetricType; typedef typename MetricType::Pointer MetricPointer; typedef typename itk::SingleValuedNonLinearOptimizer OptimizerType; // the fixed and the moving image typename FixedImageType::Pointer fixedImage = FixedImageType::New(); typename MovingImageType::Pointer movingImage = itkImage1; mitk::CastToItkImage(method->m_ReferenceImage, fixedImage); // the metric MetricPointer metric = dynamic_cast(method->m_Metric.GetPointer()); if(movingImageMask.IsNotNull()) metric->SetMovingImageMask(movingImageMask); if(fixedImageMask.IsNotNull()) metric->SetFixedImageMask(fixedImageMask); // the transform TransformPointer transform = dynamic_cast(method->m_Transform.GetPointer()); // the optimizer typename OptimizerType::Pointer optimizer = dynamic_cast(method->m_Optimizer.GetPointer()); // optimizer scales if (method->m_OptimizerScales.Size() != 0) { typename OptimizerType::ScalesType scales( transform->GetNumberOfParameters() ); for (unsigned int i = 0; i < scales.Size(); i++) { scales[i] = method->m_OptimizerScales[i]; } optimizer->SetScales( scales ); } // the registration method typename RegistrationType::Pointer registration = RegistrationType::New(); registration->SetMetric(metric); registration->SetOptimizer(optimizer); registration->SetTransform(transform); registration->SetFixedImage(fixedImage); registration->SetMovingImage(movingImage); registration->SetFixedImageRegion(fixedImage->GetBufferedRegion()); // if(transFac->GetTransformParameters()->GetInitialParameters().size()) // { // registration->SetInitialTransformParameters( transFac->GetTransformParameters()->GetInitialParameters() ); // } // else // { itk::Array zeroInitial; zeroInitial.set_size(transform->GetNumberOfParameters()); zeroInitial.fill(0.0); if (zeroInitial.size() >= 1) { zeroInitial[0] = 1.0; } if (zeroInitial.size() >= 5) { zeroInitial[4] = 1.0; } if (zeroInitial.size() >= 9) { zeroInitial[8] = 1.0; } registration->SetInitialTransformParameters( zeroInitial ); optimizer->SetInitialPosition( zeroInitial ); // } if (method->m_Interpolator == ImageRegistrationMethod::LINEARINTERPOLATOR) { typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); registration->SetInterpolator(interpolator); } else if (method->m_Interpolator == ImageRegistrationMethod::NEARESTNEIGHBORINTERPOLATOR) { typename InterpolatorType2::Pointer interpolator = InterpolatorType2::New(); registration->SetInterpolator(interpolator); } // registering command observer with the optimizer if (method->m_Observer.IsNotNull()) { method->m_Observer->AddStepsToDo(20); optimizer->AddObserver(itk::AnyEvent(), method->m_Observer); registration->AddObserver(itk::AnyEvent(), method->m_Observer); transform->AddObserver(itk::AnyEvent(), method->m_Observer); } registration->Update(); if (method->m_Observer.IsNotNull()) { optimizer->RemoveAllObservers(); registration->RemoveAllObservers(); transform->RemoveAllObservers(); method->m_Observer->SetRemainingProgress(15); } if (method->m_Observer.IsNotNull()) { method->m_Observer->SetRemainingProgress(5); } } } // end namespace diff --git a/Modules/RigidRegistration/mitkPyramidalRegistrationMethod-TYPE.cpp b/Modules/RigidRegistration/mitkPyramidalRegistrationMethod-TYPE.cpp index 465dd1ad5b..354cc3ebad 100644 --- a/Modules/RigidRegistration/mitkPyramidalRegistrationMethod-TYPE.cpp +++ b/Modules/RigidRegistration/mitkPyramidalRegistrationMethod-TYPE.cpp @@ -1,24 +1,25 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date: 2009-05-28 17:19:30 +0200 (Thu, 28 May 2009) $ Version: $Revision: 17495 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include +#include #define InstantiateAccessFunction_PyramidalAccessItkImage(pixelType, dim) \ template void mitk::PyramidalRegistrationMethodAccessFunctor::AccessItkImage(itk::Image* itkImage1, mitk::PyramidalRegistrationMethod* method); InstantiateAccessFunctionForFixedPixelType(PyramidalAccessItkImage, @TYPE@) diff --git a/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.h b/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.h index 1c99643253..4af7b03769 100644 --- a/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.h +++ b/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.h @@ -1,43 +1,43 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKPYRAMIDALREGISTRATIONMETHODACCESSFUNCTOR_H #define MITKPYRAMIDALREGISTRATIONMETHODACCESSFUNCTOR_H #include namespace mitk { class PyramidalRegistrationMethod; struct PyramidalRegistrationMethodAccessFunctor { typedef PyramidalRegistrationMethodAccessFunctor Self; void operator()(const mitk::Image* img, PyramidalRegistrationMethod* method) { - AccessDefaultPixelTypesByItk_1(img, PyramidalRegistrationMethod*, method) + AccessByItk_n(img, AccessItkImage, method) } template < typename TPixel, unsigned int VImageDimension > void AccessItkImage( itk::Image* itkImage1, PyramidalRegistrationMethod* method); }; } #endif // MITKPYRAMIDALREGISTRATIONMETHODACCESSFUNCTOR_H diff --git a/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.txx b/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.txx index 6d95648563..c5668e93be 100644 --- a/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.txx +++ b/Modules/RigidRegistration/mitkPyramidalRegistrationMethodAccessFunctor.txx @@ -1,246 +1,248 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. method software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkPyramidalRegistrationMethodAccessFunctor.h" #include "mitkPyramidalRegistrationMethod.h" +#include + #include #include #include #include #include "mitkMetricFactory.h" #include "mitkTransformFactory.h" #include "mitkOptimizerFactory.h" #include "mitkRegistrationInterfaceCommand.h" namespace mitk { template void PyramidalRegistrationMethodAccessFunctor::AccessItkImage(itk::Image* itkImage1, PyramidalRegistrationMethod* method) { // TYPEDEFS typedef itk::Image< TPixel, VImageDimension > ImageType; typedef float InternalPixelType; typedef itk::Image InternalImageType; typedef typename itk::Transform TransformType; typedef mitk::TransformFactory TransformFactoryType; typedef itk::LinearInterpolateImageFunction InterpolatorType; typedef mitk::MetricFactory MetricFactoryType; typedef itk::RecursiveMultiResolutionPyramidImageFilter ImagePyramidType; typedef itk::DiscreteGaussianImageFilter GaussianFilterType; typedef itk::MultiResolutionImageRegistrationMethod RegistrationType; typedef RegistrationInterfaceCommand CommandType; typedef itk::CastImageFilter CastImageFilterType; itk::Array initialParameters; if(method->m_TransformParameters->GetInitialParameters().size()) { initialParameters = method->m_TransformParameters->GetInitialParameters(); } // LOAD PARAMETERS itk::Array transformValues = method->m_Preset->getTransformValues(method->m_Presets[0]); itk::Array metricValues = method->m_Preset->getMetricValues(method->m_Presets[0]); itk::Array optimizerValues = method->m_Preset->getOptimizerValues(method->m_Presets[0]); method->m_TransformParameters = method->ParseTransformParameters(transformValues); method->m_MetricParameters = method->ParseMetricParameters(metricValues); method->m_OptimizerParameters = method->ParseOptimizerParameters(optimizerValues); // The fixed and the moving image typename InternalImageType::Pointer fixedImage = InternalImageType::New(); typename InternalImageType::Pointer movingImage = InternalImageType::New(); mitk::CastToItkImage(method->m_ReferenceImage, fixedImage); // Blur the moving image if(method->m_BlurMovingImage) { typename GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New(); gaussianFilter->SetInput(itkImage1); gaussianFilter->SetVariance(6.0); gaussianFilter->SetMaximumError( 0.1 ); //gaussianFilter->SetMaximumKernelWidth ( 3 ); gaussianFilter->Update(); movingImage = gaussianFilter->GetOutput(); } else { typename CastImageFilterType::Pointer castImageFilter = CastImageFilterType::New(); castImageFilter->SetInput(itkImage1); castImageFilter->Update(); movingImage = castImageFilter->GetOutput(); } if(method->m_MatchHistograms) { typedef itk::RescaleIntensityImageFilter FilterType; typedef itk::HistogramMatchingImageFilter HEFilterType; typename FilterType::Pointer inputRescaleFilter = FilterType::New(); typename FilterType::Pointer referenceRescaleFilter = FilterType::New(); referenceRescaleFilter->SetInput(fixedImage); inputRescaleFilter->SetInput(movingImage); const float desiredMinimum = 0.0; const float desiredMaximum = 255.0; referenceRescaleFilter->SetOutputMinimum( desiredMinimum ); referenceRescaleFilter->SetOutputMaximum( desiredMaximum ); referenceRescaleFilter->UpdateLargestPossibleRegion(); inputRescaleFilter->SetOutputMinimum( desiredMinimum ); inputRescaleFilter->SetOutputMaximum( desiredMaximum ); inputRescaleFilter->UpdateLargestPossibleRegion(); // Histogram match the images typename HEFilterType::Pointer intensityEqualizeFilter = HEFilterType::New(); intensityEqualizeFilter->SetReferenceImage( inputRescaleFilter->GetOutput() ); intensityEqualizeFilter->SetInput( referenceRescaleFilter->GetOutput() ); intensityEqualizeFilter->SetNumberOfHistogramLevels( 64 ); intensityEqualizeFilter->SetNumberOfMatchPoints( 12 ); intensityEqualizeFilter->ThresholdAtMeanIntensityOn(); intensityEqualizeFilter->Update(); //fixedImage = referenceRescaleFilter->GetOutput(); //movingImage = IntensityEqualizeFilter->GetOutput(); fixedImage = intensityEqualizeFilter->GetOutput(); movingImage = inputRescaleFilter->GetOutput(); } typename TransformFactoryType::Pointer transFac = TransformFactoryType::New(); transFac->SetTransformParameters(method->m_TransformParameters); transFac->SetFixedImage(fixedImage); transFac->SetMovingImage(movingImage); typename TransformType::Pointer transform = transFac->GetTransform(); typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); typename MetricFactoryType::Pointer metFac = MetricFactoryType::New(); metFac->SetMetricParameters(method->m_MetricParameters); typename OptimizerFactory::Pointer optFac = OptimizerFactory::New(); optFac->SetOptimizerParameters(method->m_OptimizerParameters); optFac->SetNumberOfTransformParameters(transform->GetNumberOfParameters()); typename PyramidalRegistrationMethod::OptimizerType::Pointer optimizer = optFac->GetOptimizer(); // optimizer scales if (method->m_TransformParameters->GetUseOptimizerScales()) { itk::Array optimizerScales = method->m_TransformParameters->GetScales(); typename PyramidalRegistrationMethod::OptimizerType::ScalesType scales( transform->GetNumberOfParameters() ); for (unsigned int i = 0; i < scales.Size(); i++) { scales[i] = optimizerScales[i]; } optimizer->SetScales( scales ); } typename ImagePyramidType::Pointer fixedImagePyramid = ImagePyramidType::New(); typename ImagePyramidType::Pointer movingImagePyramid = ImagePyramidType::New(); if(method->m_FixedSchedule.size() > 0 && method->m_MovingSchedule.size() > 0) { fixedImagePyramid->SetSchedule(method->m_FixedSchedule); movingImagePyramid->SetSchedule(method->m_MovingSchedule); // Otherwise just use the default schedule } typename RegistrationType::Pointer registration = RegistrationType::New(); registration->SetOptimizer( optimizer ); registration->SetTransform( transform ); registration->SetInterpolator( interpolator ); registration->SetMetric( metFac->GetMetric() ); registration->SetFixedImagePyramid( fixedImagePyramid ); registration->SetMovingImagePyramid( movingImagePyramid ); registration->SetFixedImage( fixedImage ); registration->SetMovingImage( movingImage ); registration->SetFixedImageRegion( fixedImage->GetBufferedRegion() ); if(transFac->GetTransformParameters()->GetInitialParameters().size()) { registration->SetInitialTransformParameters( transFac->GetTransformParameters()->GetInitialParameters() ); } else { itk::Array zeroInitial; zeroInitial.set_size(transform->GetNumberOfParameters()); zeroInitial.fill(0.0); zeroInitial[0] = 1.0; zeroInitial[4] = 1.0; zeroInitial[8] = 1.0; registration->SetInitialTransformParameters( zeroInitial ); } if(method->m_UseMask) { itk::ImageMaskSpatialObject< VImageDimension>* mask = dynamic_cast< itk::ImageMaskSpatialObject< VImageDimension>* > ( method->m_BrainMask.GetPointer() ); registration->GetMetric()->SetFixedImageMask(mask); } // registering command observer with the optimizer if (method->m_Observer.IsNotNull()) { method->m_Observer->AddStepsToDo(20); optimizer->AddObserver(itk::AnyEvent(), method->m_Observer); registration->AddObserver(itk::AnyEvent(), method->m_Observer); transform->AddObserver(itk::AnyEvent(), method->m_Observer); } typename CommandType::Pointer command = CommandType::New(); command->observer = method->m_Observer; command->m_Presets = method->m_Presets; command->m_UseMask = method->m_UseMask; command->m_BrainMask = method->m_BrainMask; registration->AddObserver( itk::IterationEvent(), command ); registration->SetSchedules(method->m_FixedSchedule, method->m_MovingSchedule); // Start the registration process try { registration->StartRegistration(); } catch( itk::ExceptionObject & err ) { std::cout << "ExceptionObject caught !" << std::endl; std::cout << err << std::endl; } if (method->m_Observer.IsNotNull()) { optimizer->RemoveAllObservers(); registration->RemoveAllObservers(); transform->RemoveAllObservers(); method->m_Observer->SetRemainingProgress(15); } if (method->m_Observer.IsNotNull()) { method->m_Observer->SetRemainingProgress(5); } } } // end namespace diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkAffineTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkAffineTransformView.cpp index 1a482db407..e12d9ef343 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkAffineTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkAffineTransformView.cpp @@ -1,258 +1,259 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkAffineTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkAffineTransformView::QmitkAffineTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkAffineTransformView::~QmitkAffineTransformView() { } mitk::TransformParameters::TransformType QmitkAffineTransformView::GetTransformType() { return mitk::TransformParameters::AFFINETRANSFORM; } itk::Object::Pointer QmitkAffineTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkAffineTransformView::GetTransform2(itk::Image* /*itkImage1*/) { typedef typename itk::Image< TPixelType, VImageDimension > FixedImageType; typedef typename itk::Image< TPixelType, VImageDimension > MovingImageType; typename FixedImageType::Pointer fixedImage; mitk::CastToItkImage(m_FixedImage, fixedImage); typename MovingImageType::Pointer movingImage; mitk::CastToItkImage(m_MovingImage, movingImage); typename itk::AffineTransform< double, VImageDimension>::Pointer transformPointer = itk::AffineTransform< double, VImageDimension>::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerAffine->isChecked()) { typedef typename itk::AffineTransform< double, VImageDimension > AffineTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage ); transformInitializer->SetMovingImage( movingImage ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsAffine->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_CenterZ = transformPointer->GetCenter()[2]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } itk::Array QmitkAffineTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(15); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesAffine->isChecked(); transformValues[1] = m_Controls.m_ScalesAffineTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesAffineTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesAffineTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_ScalesAffineTransformScale4->text().toDouble(); transformValues[5] = m_Controls.m_ScalesAffineTransformScale5->text().toDouble(); transformValues[6] = m_Controls.m_ScalesAffineTransformScale6->text().toDouble(); transformValues[7] = m_Controls.m_ScalesAffineTransformScale7->text().toDouble(); transformValues[8] = m_Controls.m_ScalesAffineTransformScale8->text().toDouble(); transformValues[9] = m_Controls.m_ScalesAffineTransformScale9->text().toDouble(); transformValues[10] = m_Controls.m_ScalesAffineTransformScaleTranslationX->text().toDouble(); transformValues[11] = m_Controls.m_ScalesAffineTransformScaleTranslationY->text().toDouble(); transformValues[12] = m_Controls.m_ScalesAffineTransformScaleTranslationZ->text().toDouble(); transformValues[13] = m_Controls.m_CenterForInitializerAffine->isChecked(); transformValues[14] = m_Controls.m_MomentsAffine->isChecked(); return transformValues; } void QmitkAffineTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesAffine->setChecked(transformValues[0]); m_Controls.m_ScalesAffineTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesAffineTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesAffineTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_ScalesAffineTransformScale4->setText(QString::number(transformValues[4])); m_Controls.m_ScalesAffineTransformScale5->setText(QString::number(transformValues[5])); m_Controls.m_ScalesAffineTransformScale6->setText(QString::number(transformValues[6])); m_Controls.m_ScalesAffineTransformScale7->setText(QString::number(transformValues[7])); m_Controls.m_ScalesAffineTransformScale8->setText(QString::number(transformValues[8])); m_Controls.m_ScalesAffineTransformScale9->setText(QString::number(transformValues[9])); m_Controls.m_ScalesAffineTransformScaleTranslationX->setText(QString::number(transformValues[10])); m_Controls.m_ScalesAffineTransformScaleTranslationY->setText(QString::number(transformValues[11])); m_Controls.m_ScalesAffineTransformScaleTranslationZ->setText(QString::number(transformValues[12])); m_Controls.m_CenterForInitializerAffine->setChecked(transformValues[13]); m_Controls.m_MomentsAffine->setChecked(transformValues[14]); m_Controls.m_GeometryAffine->setChecked(!transformValues[14]); } QString QmitkAffineTransformView::GetName() { return "Affine"; } void QmitkAffineTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesAffineTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale3->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale4->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale5->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale6->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale7->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale8->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScale9->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesAffineTransformScaleTranslationZ->setValidator(validatorLineEditInputFloat); } itk::Array QmitkAffineTransformView::GetScales() { itk::Array scales; scales.SetSize(12); scales.Fill(1.0); scales[0] = m_Controls.m_ScalesAffineTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesAffineTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesAffineTransformScale3->text().toDouble(); scales[3] = m_Controls.m_ScalesAffineTransformScale4->text().toDouble(); scales[4] = m_Controls.m_ScalesAffineTransformScale5->text().toDouble(); scales[5] = m_Controls.m_ScalesAffineTransformScale6->text().toDouble(); scales[6] = m_Controls.m_ScalesAffineTransformScale7->text().toDouble(); scales[7] = m_Controls.m_ScalesAffineTransformScale8->text().toDouble(); scales[8] = m_Controls.m_ScalesAffineTransformScale9->text().toDouble(); scales[9] = m_Controls.m_ScalesAffineTransformScaleTranslationX->text().toDouble(); scales[10] = m_Controls.m_ScalesAffineTransformScaleTranslationY->text().toDouble(); scales[11] = m_Controls.m_ScalesAffineTransformScaleTranslationZ->text().toDouble(); return scales; } vtkTransform* QmitkAffineTransformView::Transform(vtkMatrix4x4* vtkmatrix, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { // - the 9 rotation-coefficients are copied // directly to the top left part of the matrix int m = 0; for (unsigned int i = 0; i < m_FixedImage->GetDimension(); i++) { for (unsigned int j = 0; j < m_FixedImage->GetDimension(); j++) { vtkmatrix->SetElement(i, j, transformParams[m]); m++; } } // - the 3 translation-coefficients are corrected to take // into account the center of the transformation float center[4]; center[0] = m_CenterX; center[1] = m_CenterY; center[2] = m_CenterZ; center[3] = 1; std::cout<< "rotation center: " << center[0] << " " << center[1] << " " << center [2] << std::endl; float translation[4]; vtkmatrix->MultiplyPoint(center, translation); if (m_FixedImage->GetDimension() == 2) { vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[4]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[5]); } else if (m_FixedImage->GetDimension() == 3) { vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[9]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[10]); vtkmatrix->SetElement(2, 3, -translation[2] + center[2] + transformParams[11]); } // set the transform matrix to init the transform vtktransform->SetMatrix(vtkmatrix); } return vtktransform; } int QmitkAffineTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) { m_Controls.m_ScalesAffineTransformScale7->hide(); m_Controls.m_ScalesAffineTransformScale8->hide(); m_Controls.m_ScalesAffineTransformScale9->hide(); m_Controls.m_ScalesAffineTransformScaleTranslationX->hide(); m_Controls.m_ScalesAffineTransformScaleTranslationY->hide(); m_Controls.m_ScalesAffineTransformScaleTranslationZ->hide(); m_Controls.textLabel2_7->setText("Translation Scale X:"); m_Controls.textLabel3_6->setText("Translation Scale Y:"); m_Controls.textLabel4_4->hide(); m_Controls.textLabel5_4->hide(); m_Controls.textLabel6_4->hide(); m_Controls.textLabel11_3->hide(); m_Controls.textLabel12_3->hide(); m_Controls.textLabel13_2->hide(); return 6; } else { m_Controls.m_ScalesAffineTransformScale7->show(); m_Controls.m_ScalesAffineTransformScale8->show(); m_Controls.m_ScalesAffineTransformScale9->show(); m_Controls.m_ScalesAffineTransformScaleTranslationX->show(); m_Controls.m_ScalesAffineTransformScaleTranslationY->show(); m_Controls.m_ScalesAffineTransformScaleTranslationZ->show(); m_Controls.textLabel2_7->setText("Scale 5:"); m_Controls.textLabel3_6->setText("Scale 6:"); m_Controls.textLabel4_4->show(); m_Controls.textLabel5_4->show(); m_Controls.textLabel6_4->show(); m_Controls.textLabel11_3->show(); m_Controls.textLabel12_3->show(); m_Controls.textLabel13_2->show(); return 12; } } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredRigid2DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredRigid2DTransformView.cpp index 97d6a1e2e0..df287b188f 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredRigid2DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredRigid2DTransformView.cpp @@ -1,178 +1,179 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkCenteredRigid2DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkCenteredRigid2DTransformView::QmitkCenteredRigid2DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkCenteredRigid2DTransformView::~QmitkCenteredRigid2DTransformView() { } mitk::TransformParameters::TransformType QmitkCenteredRigid2DTransformView::GetTransformType() { return mitk::TransformParameters::CENTEREDRIGID2DTRANSFORM; } itk::Object::Pointer QmitkCenteredRigid2DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkCenteredRigid2DTransformView::GetTransform2(itk::Image* /* itkImage1 */) { if (VImageDimension == 2) { typedef typename itk::Image< TPixelType, 2 > FixedImage2DType; typedef typename itk::Image< TPixelType, 2 > MovingImage2DType; typename FixedImage2DType::Pointer fixedImage2D; mitk::CastToItkImage(m_FixedImage, fixedImage2D); typename MovingImage2DType::Pointer movingImage2D; mitk::CastToItkImage(m_MovingImage, movingImage2D); typename itk::CenteredRigid2DTransform< double >::Pointer transformPointer = itk::CenteredRigid2DTransform< double >::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerCenteredRigid2D->isChecked()) { typedef typename itk::CenteredRigid2DTransform< double > CenteredRigid2DTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage2D ); transformInitializer->SetMovingImage( movingImage2D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsCenteredRigid2D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } transformPointer->SetAngle( m_Controls.m_AngleCenteredRigid2D->text().toFloat() ); m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkCenteredRigid2DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(9); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesCenteredRigid2D->isChecked(); transformValues[1] = m_Controls.m_RotationScaleCenteredRigid2D->text().toDouble(); transformValues[2] = m_Controls.m_CenterXScaleCenteredRigid2D->text().toDouble(); transformValues[3] = m_Controls.m_CenterYScaleCenteredRigid2D->text().toDouble(); transformValues[4] = m_Controls.m_TranslationXScaleCenteredRigid2D->text().toDouble(); transformValues[5] = m_Controls.m_TranslationYScaleCenteredRigid2D->text().toDouble(); transformValues[6] = m_Controls.m_AngleCenteredRigid2D->text().toFloat(); transformValues[7] = m_Controls.m_CenterForInitializerCenteredRigid2D->isChecked(); transformValues[8] = m_Controls.m_MomentsCenteredRigid2D->isChecked(); return transformValues; } void QmitkCenteredRigid2DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesCenteredRigid2D->setChecked(transformValues[0]); m_Controls.m_RotationScaleCenteredRigid2D->setText(QString::number(transformValues[1])); m_Controls.m_CenterXScaleCenteredRigid2D->setText(QString::number(transformValues[2])); m_Controls.m_CenterYScaleCenteredRigid2D->setText(QString::number(transformValues[3])); m_Controls.m_TranslationXScaleCenteredRigid2D->setText(QString::number(transformValues[4])); m_Controls.m_TranslationYScaleCenteredRigid2D->setText(QString::number(transformValues[5])); m_Controls.m_AngleCenteredRigid2D->setText(QString::number(transformValues[6])); m_Controls.m_CenterForInitializerCenteredRigid2D->setChecked(transformValues[7]); m_Controls.m_MomentsCenteredRigid2D->setChecked(transformValues[8]); m_Controls.m_GeometryCenteredRigid2D->setChecked(!transformValues[8]); } QString QmitkCenteredRigid2DTransformView::GetName() { return "CenteredRigid2D"; } void QmitkCenteredRigid2DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_AngleCenteredRigid2D->setValidator(validatorLineEditInputFloat); m_Controls.m_RotationScaleCenteredRigid2D->setValidator(validatorLineEditInputFloat); m_Controls.m_CenterXScaleCenteredRigid2D->setValidator(validatorLineEditInputFloat); m_Controls.m_CenterYScaleCenteredRigid2D->setValidator(validatorLineEditInputFloat); m_Controls.m_TranslationXScaleCenteredRigid2D->setValidator(validatorLineEditInputFloat); m_Controls.m_TranslationYScaleCenteredRigid2D->setValidator(validatorLineEditInputFloat); } itk::Array QmitkCenteredRigid2DTransformView::GetScales() { itk::Array scales; scales.SetSize(5); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesCenteredRigid2D->isChecked()) { scales[0] = m_Controls.m_RotationScaleCenteredRigid2D->text().toDouble(); scales[1] = m_Controls.m_CenterXScaleCenteredRigid2D->text().toDouble(); scales[2] = m_Controls.m_CenterYScaleCenteredRigid2D->text().toDouble(); scales[3] = m_Controls.m_TranslationXScaleCenteredRigid2D->text().toDouble(); scales[4] = m_Controls.m_TranslationYScaleCenteredRigid2D->text().toDouble(); } return scales; } vtkTransform* QmitkCenteredRigid2DTransformView::Transform(vtkMatrix4x4* /* vtkmatrix */, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { mitk::ScalarType angle = transformParams[0] * 45.0 / atan(1.0);; vtktransform->PostMultiply(); vtktransform->Translate(-transformParams[1], -transformParams[2], 0); vtktransform->RotateZ(angle); vtktransform->Translate(transformParams[1], transformParams[2], 0); vtktransform->Translate(transformParams[3], transformParams[4], 0); vtktransform->PreMultiply(); } return vtktransform; } int QmitkCenteredRigid2DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 5; else return 0; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredSimilarity2DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredSimilarity2DTransformView.cpp index a4e979504e..04a5726d18 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredSimilarity2DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkCenteredSimilarity2DTransformView.cpp @@ -1,186 +1,187 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkCenteredSimilarity2DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkCenteredSimilarity2DTransformView::QmitkCenteredSimilarity2DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkCenteredSimilarity2DTransformView::~QmitkCenteredSimilarity2DTransformView() { } mitk::TransformParameters::TransformType QmitkCenteredSimilarity2DTransformView::GetTransformType() { return mitk::TransformParameters::CENTEREDSIMILARITY2DTRANSFORM; } itk::Object::Pointer QmitkCenteredSimilarity2DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkCenteredSimilarity2DTransformView::GetTransform2(itk::Image* /* itkImage1 */) { if (VImageDimension == 2) { typedef typename itk::Image< TPixelType, 2 > FixedImage2DType; typedef typename itk::Image< TPixelType, 2 > MovingImage2DType; typename FixedImage2DType::Pointer fixedImage2D; mitk::CastToItkImage(m_FixedImage, fixedImage2D); typename MovingImage2DType::Pointer movingImage2D; mitk::CastToItkImage(m_MovingImage, movingImage2D); typename itk::CenteredSimilarity2DTransform< double >::Pointer transformPointer = itk::CenteredSimilarity2DTransform< double >::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerCenteredSimilarity2D->isChecked()) { typedef typename itk::CenteredSimilarity2DTransform< double > CenteredSimilarity2DTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage2D ); transformInitializer->SetMovingImage( movingImage2D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsCenteredSimilarity2D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } transformPointer->SetScale( m_Controls.m_InitialScaleCenteredSimilarity2D->text().toFloat() ); transformPointer->SetAngle( m_Controls.m_AngleCenteredSimilarity2D->text().toFloat() ); m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkCenteredSimilarity2DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(11); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesCenteredSimilarity2D->isChecked(); transformValues[1] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale4->text().toDouble(); transformValues[5] = m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationX->text().toDouble(); transformValues[6] = m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationY->text().toDouble(); transformValues[7] = m_Controls.m_InitialScaleCenteredSimilarity2D->text().toFloat(); transformValues[8] = m_Controls.m_AngleCenteredSimilarity2D->text().toFloat(); transformValues[9] = m_Controls.m_CenterForInitializerCenteredSimilarity2D->isChecked(); transformValues[10] = m_Controls.m_MomentsCenteredSimilarity2D->isChecked(); return transformValues; } void QmitkCenteredSimilarity2DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesCenteredSimilarity2D->setChecked(transformValues[0]); m_Controls.m_ScalesCenteredSimilarity2DTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesCenteredSimilarity2DTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesCenteredSimilarity2DTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_ScalesCenteredSimilarity2DTransformScale4->setText(QString::number(transformValues[4])); m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationX->setText(QString::number(transformValues[5])); m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationY->setText(QString::number(transformValues[6])); m_Controls.m_InitialScaleCenteredSimilarity2D->setText(QString::number(transformValues[7])); m_Controls.m_AngleCenteredSimilarity2D->setText(QString::number(transformValues[8])); m_Controls.m_CenterForInitializerCenteredSimilarity2D->setChecked(transformValues[9]); m_Controls.m_MomentsCenteredSimilarity2D->setChecked(transformValues[10]); m_Controls.m_GeometryCenteredSimilarity2D->setChecked(!transformValues[10]); } QString QmitkCenteredSimilarity2DTransformView::GetName() { return "CenteredSimilarity2D"; } void QmitkCenteredSimilarity2DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesCenteredSimilarity2DTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesCenteredSimilarity2DTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesCenteredSimilarity2DTransformScale3->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesCenteredSimilarity2DTransformScale4->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); } itk::Array QmitkCenteredSimilarity2DTransformView::GetScales() { itk::Array scales; scales.SetSize(6); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesCenteredSimilarity2D->isChecked()) { scales[0] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale3->text().toDouble(); scales[3] = m_Controls.m_ScalesCenteredSimilarity2DTransformScale4->text().toDouble(); scales[4] = m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationX->text().toDouble(); scales[5] = m_Controls.m_ScalesCenteredSimilarity2DTransformScaleTranslationY->text().toDouble(); } return scales; } vtkTransform* QmitkCenteredSimilarity2DTransformView::Transform(vtkMatrix4x4* /*vtkmatrix*/, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { mitk::ScalarType angle = transformParams[1] * 45.0 / atan(1.0); vtktransform->PostMultiply(); vtktransform->Translate(-transformParams[2], -transformParams[3], 0); vtktransform->Scale(transformParams[0], transformParams[0], 1); vtktransform->RotateZ(angle); vtktransform->Translate(transformParams[2], transformParams[3], 0); vtktransform->Translate(transformParams[4], transformParams[5], 0); vtktransform->PreMultiply(); } return vtktransform; } int QmitkCenteredSimilarity2DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 6; else return 0; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkEuler2DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkEuler2DTransformView.cpp index 9a5a820e13..2567d428f0 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkEuler2DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkEuler2DTransformView.cpp @@ -1,162 +1,163 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkEuler2DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkEuler2DTransformView::QmitkEuler2DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkEuler2DTransformView::~QmitkEuler2DTransformView() { } mitk::TransformParameters::TransformType QmitkEuler2DTransformView::GetTransformType() { return mitk::TransformParameters::EULER2DTRANSFORM; } itk::Object::Pointer QmitkEuler2DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkEuler2DTransformView::GetTransform2(itk::Image* /* itkImage1 */) { if (VImageDimension == 2) { typedef typename itk::Image< TPixelType, 2 > FixedImage2DType; typedef typename itk::Image< TPixelType, 2 > MovingImage2DType; typename FixedImage2DType::Pointer fixedImage2D; mitk::CastToItkImage(m_FixedImage, fixedImage2D); typename MovingImage2DType::Pointer movingImage2D; mitk::CastToItkImage(m_MovingImage, movingImage2D); typename itk::Euler2DTransform< double >::Pointer transformPointer = itk::Euler2DTransform< double >::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerEuler2D->isChecked()) { typedef typename itk::Euler2DTransform< double > Euler2DTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage2D ); transformInitializer->SetMovingImage( movingImage2D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsEuler2D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkEuler2DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(6); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesEuler2D->isChecked(); transformValues[1] = m_Controls.m_RotationScaleEuler2D->text().toDouble(); transformValues[2] = m_Controls.m_TranslationXScaleEuler2D->text().toDouble(); transformValues[3] = m_Controls.m_TranslationYScaleEuler2D->text().toDouble(); transformValues[4] = m_Controls.m_CenterForInitializerEuler2D->isChecked(); transformValues[5] = m_Controls.m_MomentsEuler2D->isChecked(); return transformValues; } void QmitkEuler2DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesEuler2D->setChecked(transformValues[0]); m_Controls.m_RotationScaleEuler2D->setText(QString::number(transformValues[1])); m_Controls.m_TranslationXScaleEuler2D->setText(QString::number(transformValues[2])); m_Controls.m_TranslationYScaleEuler2D->setText(QString::number(transformValues[3])); m_Controls.m_CenterForInitializerEuler2D->setChecked(transformValues[4]); m_Controls.m_MomentsEuler2D->setChecked(transformValues[5]); m_Controls.m_GeometryEuler2D->setChecked(!transformValues[5]); } QString QmitkEuler2DTransformView::GetName() { return "Euler2D"; } void QmitkEuler2DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_RotationScaleEuler2D->setValidator(validatorLineEditInputFloat); m_Controls.m_TranslationXScaleEuler2D->setValidator(validatorLineEditInputFloat); m_Controls.m_TranslationYScaleEuler2D->setValidator(validatorLineEditInputFloat); } itk::Array QmitkEuler2DTransformView::GetScales() { itk::Array scales; scales.SetSize(3); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesEuler2D->isChecked()) { scales[0] = m_Controls.m_RotationScaleEuler2D->text().toDouble(); scales[1] = m_Controls.m_TranslationXScaleEuler2D->text().toDouble(); scales[2] = m_Controls.m_TranslationYScaleEuler2D->text().toDouble(); } return scales; } vtkTransform* QmitkEuler2DTransformView::Transform(vtkMatrix4x4* /*vtkmatrix*/, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { mitk::ScalarType angle = transformParams[0] * 45.0 / atan(1.0); vtktransform->PostMultiply(); vtktransform->RotateZ(angle); vtktransform->Translate(transformParams[1], transformParams[2], 0); vtktransform->PreMultiply(); } return vtktransform; } int QmitkEuler2DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 3; else return 0; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkFixedCenterOfRotationAffineTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkFixedCenterOfRotationAffineTransformView.cpp index 2104c292e4..4fb3812c22 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkFixedCenterOfRotationAffineTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkFixedCenterOfRotationAffineTransformView.cpp @@ -1,253 +1,254 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkFixedCenterOfRotationAffineTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkFixedCenterOfRotationAffineTransformView::QmitkFixedCenterOfRotationAffineTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkFixedCenterOfRotationAffineTransformView::~QmitkFixedCenterOfRotationAffineTransformView() { } mitk::TransformParameters::TransformType QmitkFixedCenterOfRotationAffineTransformView::GetTransformType() { return mitk::TransformParameters::FIXEDCENTEROFROTATIONAFFINETRANSFORM; } itk::Object::Pointer QmitkFixedCenterOfRotationAffineTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkFixedCenterOfRotationAffineTransformView::GetTransform2(itk::Image* /*itkImage1*/) { typedef typename itk::Image< TPixelType, VImageDimension > FixedImageType; typedef typename itk::Image< TPixelType, VImageDimension > MovingImageType; typename FixedImageType::Pointer fixedImage; mitk::CastToItkImage(m_FixedImage, fixedImage); typename MovingImageType::Pointer movingImage; mitk::CastToItkImage(m_MovingImage, movingImage); typedef typename itk::FixedCenterOfRotationAffineTransform< double, VImageDimension > CenteredAffineTransformType; typename itk::FixedCenterOfRotationAffineTransform< double, VImageDimension>::Pointer transformPointer = itk::FixedCenterOfRotationAffineTransform< double, VImageDimension>::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerFixedCenterOfRotationAffine->isChecked()) { typedef typename itk::FixedCenterOfRotationAffineTransform< double, VImageDimension > FixedCenterOfRotationAffineTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage ); transformInitializer->SetMovingImage( movingImage ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsFixedCenterOfRotationAffine->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_CenterZ = transformPointer->GetCenter()[2]; transformInitializer->InitializeTransform(); } m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } itk::Array QmitkFixedCenterOfRotationAffineTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(15); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesFixedCenterOfRotationAffine->isChecked(); transformValues[1] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale4->text().toDouble(); transformValues[5] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale5->text().toDouble(); transformValues[6] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale6->text().toDouble(); transformValues[7] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale7->text().toDouble(); transformValues[8] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale8->text().toDouble(); transformValues[9] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale9->text().toDouble(); transformValues[10] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationX->text().toDouble(); transformValues[11] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationY->text().toDouble(); transformValues[12] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationZ->text().toDouble(); transformValues[13] = m_Controls.m_CenterForInitializerFixedCenterOfRotationAffine->isChecked(); transformValues[14] = m_Controls.m_MomentsFixedCenterOfRotationAffine->isChecked(); return transformValues; } void QmitkFixedCenterOfRotationAffineTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesFixedCenterOfRotationAffine->setChecked(transformValues[0]); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale4->setText(QString::number(transformValues[4])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale5->setText(QString::number(transformValues[5])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale6->setText(QString::number(transformValues[6])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale7->setText(QString::number(transformValues[7])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale8->setText(QString::number(transformValues[8])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale9->setText(QString::number(transformValues[9])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationX->setText(QString::number(transformValues[10])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationY->setText(QString::number(transformValues[11])); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationZ->setText(QString::number(transformValues[12])); m_Controls.m_CenterForInitializerFixedCenterOfRotationAffine->setChecked(transformValues[13]); m_Controls.m_MomentsFixedCenterOfRotationAffine->setChecked(transformValues[14]); m_Controls.m_GeometryFixedCenterOfRotationAffine->setChecked(!transformValues[14]); } QString QmitkFixedCenterOfRotationAffineTransformView::GetName() { return "FixedCenterOfRotationAffine"; } void QmitkFixedCenterOfRotationAffineTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale3->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale4->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale5->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale6->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale7->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale8->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale9->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationZ->setValidator(validatorLineEditInputFloat); } itk::Array QmitkFixedCenterOfRotationAffineTransformView::GetScales() { itk::Array scales; scales.SetSize(12); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesFixedCenterOfRotationAffine->isChecked()) { scales[0] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale3->text().toDouble(); scales[3] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale4->text().toDouble(); scales[4] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale5->text().toDouble(); scales[5] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale6->text().toDouble(); scales[6] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale7->text().toDouble(); scales[7] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale8->text().toDouble(); scales[8] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale9->text().toDouble(); scales[9] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationX->text().toDouble(); scales[10] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationY->text().toDouble(); scales[11] = m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationZ->text().toDouble(); } return scales; } vtkTransform* QmitkFixedCenterOfRotationAffineTransformView::Transform(vtkMatrix4x4* vtkmatrix, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { int m = 0; for (unsigned int i = 0; i < m_FixedImage->GetDimension(); i++) { for (unsigned int j = 0; j < m_FixedImage->GetDimension(); j++) { vtkmatrix->SetElement(i, j, transformParams[m]); m++; } } float center[4]; float translation[4]; center[0] = m_CenterX; center[1] = m_CenterY; center[2] = m_CenterZ; center[3] = 1; vtkmatrix->MultiplyPoint(center, translation); if (m_FixedImage->GetDimension() == 2) { vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[4]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[5]); } else if (m_FixedImage->GetDimension() == 3) { vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[9]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[10]); vtkmatrix->SetElement(2, 3, -translation[2] + center[2] + transformParams[11]); } vtktransform->SetMatrix(vtkmatrix); } return vtktransform; } int QmitkFixedCenterOfRotationAffineTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) { m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale7->hide(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale8->hide(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale9->hide(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationX->hide(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationY->hide(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationZ->hide(); m_Controls.textLabel2_7_2_2->setText("Translation Scale X:"); m_Controls.textLabel3_6_2_2->setText("Translation Scale Y:"); m_Controls.textLabel4_4_3_2->hide(); m_Controls.textLabel5_4_2_2->hide(); m_Controls.textLabel6_4_2_2->hide(); m_Controls.textLabel11_3_2_2->hide(); m_Controls.textLabel12_3_2_2->hide(); m_Controls.textLabel13_2_2_2->hide(); return 6; } else { m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale7->show(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale8->show(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScale9->show(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationX->show(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationY->show(); m_Controls.m_ScalesFixedCenterOfRotationAffineTransformScaleTranslationZ->show(); m_Controls.textLabel2_7_2_2->setText("Scale 5:"); m_Controls.textLabel3_6_2_2->setText("Scale 6:"); m_Controls.textLabel4_4_3_2->show(); m_Controls.textLabel5_4_2_2->show(); m_Controls.textLabel6_4_2_2->show(); m_Controls.textLabel11_3_2_2->show(); m_Controls.textLabel12_3_2_2->show(); m_Controls.textLabel13_2_2_2->show(); return 12; } } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkQuaternionRigidTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkQuaternionRigidTransformView.cpp index 39568c1b6d..9fbc045293 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkQuaternionRigidTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkQuaternionRigidTransformView.cpp @@ -1,197 +1,198 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkQuaternionRigidTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkQuaternionRigidTransformView::QmitkQuaternionRigidTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkQuaternionRigidTransformView::~QmitkQuaternionRigidTransformView() { } mitk::TransformParameters::TransformType QmitkQuaternionRigidTransformView::GetTransformType() { return mitk::TransformParameters::QUATERNIONRIGIDTRANSFORM; } itk::Object::Pointer QmitkQuaternionRigidTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkQuaternionRigidTransformView::GetTransform2(itk::Image* /*itkImage1*/) { if (VImageDimension == 3) { typedef typename itk::Image< TPixelType, 3 > FixedImage3DType; typedef typename itk::Image< TPixelType, 3 > MovingImage3DType; typename FixedImage3DType::Pointer fixedImage3D; mitk::CastToItkImage(m_FixedImage, fixedImage3D); typename MovingImage3DType::Pointer movingImage3D; mitk::CastToItkImage(m_MovingImage, movingImage3D); typename itk::QuaternionRigidTransform< double >::Pointer transformPointer = itk::QuaternionRigidTransform< double >::New(); transformPointer->SetIdentity(); typedef typename itk::QuaternionRigidTransform< double > QuaternionRigidTransformType; if (m_Controls.m_CenterForInitializerQuaternionRigid->isChecked()) { typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage3D ); transformInitializer->SetMovingImage( movingImage3D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsQuaternionRigid->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_CenterZ = transformPointer->GetCenter()[2]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkQuaternionRigidTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(10); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesQuaternionRigid->isChecked(); transformValues[1] = m_Controls.m_ScalesQuaternionRigidTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesQuaternionRigidTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesQuaternionRigidTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_ScalesQuaternionRigidTransformScale4->text().toDouble(); transformValues[5] = m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationX->text().toDouble(); transformValues[6] = m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationY->text().toDouble(); transformValues[7] = m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationZ->text().toDouble(); transformValues[8] = m_Controls.m_CenterForInitializerQuaternionRigid->isChecked(); transformValues[9] = m_Controls.m_MomentsQuaternionRigid->isChecked(); return transformValues; } void QmitkQuaternionRigidTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesQuaternionRigid->setChecked(transformValues[0]); m_Controls.m_ScalesQuaternionRigidTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesQuaternionRigidTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesQuaternionRigidTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_ScalesQuaternionRigidTransformScale4->setText(QString::number(transformValues[4])); m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationX->setText(QString::number(transformValues[5])); m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationY->setText(QString::number(transformValues[6])); m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationZ->setText(QString::number(transformValues[7])); m_Controls.m_CenterForInitializerQuaternionRigid->setChecked(transformValues[8]); m_Controls.m_MomentsQuaternionRigid->setChecked(transformValues[9]); m_Controls.m_GeometryQuaternionRigid->setChecked(!transformValues[9]); } QString QmitkQuaternionRigidTransformView::GetName() { return "QuaternionRigid"; } void QmitkQuaternionRigidTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesQuaternionRigidTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesQuaternionRigidTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesQuaternionRigidTransformScale3->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesQuaternionRigidTransformScale4->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationZ->setValidator(validatorLineEditInputFloat); } itk::Array QmitkQuaternionRigidTransformView::GetScales() { itk::Array scales; scales.SetSize(7); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesQuaternionRigid->isChecked()) { scales[0] = m_Controls.m_ScalesQuaternionRigidTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesQuaternionRigidTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesQuaternionRigidTransformScale3->text().toDouble(); scales[3] = m_Controls.m_ScalesQuaternionRigidTransformScale4->text().toDouble(); scales[4] = m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationX->text().toDouble(); scales[5] = m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationY->text().toDouble(); scales[6] = m_Controls.m_ScalesQuaternionRigidTransformScaleTranslationZ->text().toDouble(); } return scales; } vtkTransform* QmitkQuaternionRigidTransformView::Transform(vtkMatrix4x4* vtkmatrix, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { itk::QuaternionRigidTransform::Pointer quaternionTransform = itk::QuaternionRigidTransform::New(); quaternionTransform->SetParameters(transformParams); itk::Matrix Matrix = quaternionTransform->GetMatrix(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { vtkmatrix->SetElement(i, j, Matrix[i][j]); } } float center[4]; float translation[4]; center[0] = m_CenterX; center[1] = m_CenterY; center[2] = m_CenterZ; center[3] = 1; vtkmatrix->MultiplyPoint(center, translation); vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[4]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[5]); vtkmatrix->SetElement(2, 3, -translation[2] + center[2] + transformParams[6]); vtktransform->SetMatrix(vtkmatrix); } return vtktransform; } int QmitkQuaternionRigidTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 0; else return 7; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkRigid2DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkRigid2DTransformView.cpp index ff79248055..5b9c4f9c4e 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkRigid2DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkRigid2DTransformView.cpp @@ -1,162 +1,163 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkRigid2DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkRigid2DTransformView::QmitkRigid2DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkRigid2DTransformView::~QmitkRigid2DTransformView() { } mitk::TransformParameters::TransformType QmitkRigid2DTransformView::GetTransformType() { return mitk::TransformParameters::RIGID2DTRANSFORM; } itk::Object::Pointer QmitkRigid2DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkRigid2DTransformView::GetTransform2(itk::Image* /*itkImage1*/) { if (VImageDimension == 2) { typedef typename itk::Image< TPixelType, 2 > FixedImage2DType; typedef typename itk::Image< TPixelType, 2 > MovingImage2DType; typename FixedImage2DType::Pointer fixedImage2D; mitk::CastToItkImage(m_FixedImage, fixedImage2D); typename MovingImage2DType::Pointer movingImage2D; mitk::CastToItkImage(m_MovingImage, movingImage2D); typename itk::Rigid2DTransform< double >::Pointer transformPointer = itk::Rigid2DTransform< double >::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerRigid2D->isChecked()) { typedef typename itk::Rigid2DTransform< double > Rigid2DTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage2D ); transformInitializer->SetMovingImage( movingImage2D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsRigid2D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkRigid2DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(6); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesRigid2D->isChecked(); transformValues[1] = m_Controls.m_ScalesRigid2DTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesRigid2DTransformScaleTranslationX->text().toDouble(); transformValues[3] = m_Controls.m_ScalesRigid2DTransformScaleTranslationY->text().toDouble(); transformValues[4] = m_Controls.m_CenterForInitializerRigid2D->isChecked(); transformValues[5] = m_Controls.m_MomentsRigid2D->isChecked(); return transformValues; } void QmitkRigid2DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesRigid2D->setChecked(transformValues[0]); m_Controls.m_ScalesRigid2DTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesRigid2DTransformScaleTranslationX->setText(QString::number(transformValues[2])); m_Controls.m_ScalesRigid2DTransformScaleTranslationY->setText(QString::number(transformValues[3])); m_Controls.m_CenterForInitializerRigid2D->setChecked(transformValues[4]); m_Controls.m_MomentsRigid2D->setChecked(transformValues[5]); m_Controls.m_GeometryRigid2D->setChecked(!transformValues[5]); } QString QmitkRigid2DTransformView::GetName() { return "Rigid2D"; } void QmitkRigid2DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesRigid2DTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesRigid2DTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesRigid2DTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); } itk::Array QmitkRigid2DTransformView::GetScales() { itk::Array scales; scales.SetSize(3); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesRigid2D->isChecked()) { scales[0] = m_Controls.m_ScalesRigid2DTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesRigid2DTransformScaleTranslationX->text().toDouble(); scales[2] = m_Controls.m_ScalesRigid2DTransformScaleTranslationY->text().toDouble(); } return scales; } vtkTransform* QmitkRigid2DTransformView::Transform(vtkMatrix4x4* /*vtkmatrix*/, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { mitk::ScalarType angle = transformParams[0] * 45.0 / atan(1.0); vtktransform->PostMultiply(); vtktransform->RotateZ(angle); vtktransform->Translate(transformParams[1], transformParams[2], 0); vtktransform->PreMultiply(); } return vtktransform; } int QmitkRigid2DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 3; else return 0; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkScaleSkewVersor3DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkScaleSkewVersor3DTransformView.cpp index 1aeb9c7a7f..16d16f913c 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkScaleSkewVersor3DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkScaleSkewVersor3DTransformView.cpp @@ -1,228 +1,229 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkScaleSkewVersor3DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkScaleSkewVersor3DTransformView::QmitkScaleSkewVersor3DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkScaleSkewVersor3DTransformView::~QmitkScaleSkewVersor3DTransformView() { } mitk::TransformParameters::TransformType QmitkScaleSkewVersor3DTransformView::GetTransformType() { return mitk::TransformParameters::SCALESKEWVERSOR3DTRANSFORM; } itk::Object::Pointer QmitkScaleSkewVersor3DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkScaleSkewVersor3DTransformView::GetTransform2(itk::Image* /*itkImage1*/) { if (VImageDimension == 3) { typedef typename itk::Image< TPixelType, 3 > FixedImage3DType; typedef typename itk::Image< TPixelType, 3 > MovingImage3DType; typename FixedImage3DType::Pointer fixedImage3D; mitk::CastToItkImage(m_FixedImage, fixedImage3D); typename MovingImage3DType::Pointer movingImage3D; mitk::CastToItkImage(m_MovingImage, movingImage3D); typename itk::ScaleSkewVersor3DTransform< double >::Pointer transformPointer = itk::ScaleSkewVersor3DTransform< double >::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerScaleSkewVersorRigid3D->isChecked()) { typedef typename itk::ScaleSkewVersor3DTransform< double > ScaleSkewVersor3DTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage3D ); transformInitializer->SetMovingImage( movingImage3D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsScaleSkewVersorRigid3D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_CenterZ = transformPointer->GetCenter()[2]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkScaleSkewVersor3DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(18); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesScaleSkewVersorRigid3DTransform->isChecked(); transformValues[1] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationX->text().toDouble(); transformValues[5] = m_Controls.m_ScaleScaleSkewVersorRigid3DTransformScaleTranslationY->text().toDouble(); transformValues[6] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationZ->text().toDouble(); transformValues[7] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale7->text().toDouble(); transformValues[8] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale8->text().toDouble(); transformValues[9] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale9->text().toDouble(); transformValues[10] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale10->text().toDouble(); transformValues[11] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale11->text().toDouble(); transformValues[12] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale12->text().toDouble(); transformValues[13] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale13->text().toDouble(); transformValues[14] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale14->text().toDouble(); transformValues[15] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale15->text().toDouble(); transformValues[16] = m_Controls.m_CenterForInitializerScaleSkewVersorRigid3D->isChecked(); transformValues[17] = m_Controls.m_MomentsScaleSkewVersorRigid3D->isChecked(); return transformValues; } void QmitkScaleSkewVersor3DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesScaleSkewVersorRigid3DTransform->setChecked(transformValues[0]); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationX->setText(QString::number(transformValues[4])); m_Controls.m_ScaleScaleSkewVersorRigid3DTransformScaleTranslationY->setText(QString::number(transformValues[5])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationZ->setText(QString::number(transformValues[6])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale7->setText(QString::number(transformValues[7])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale8->setText(QString::number(transformValues[8])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale9->setText(QString::number(transformValues[9])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale10->setText(QString::number(transformValues[10])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale11->setText(QString::number(transformValues[11])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale12->setText(QString::number(transformValues[12])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale13->setText(QString::number(transformValues[13])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale14->setText(QString::number(transformValues[14])); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale15->setText(QString::number(transformValues[15])); m_Controls.m_CenterForInitializerScaleSkewVersorRigid3D->setChecked(transformValues[16]); m_Controls.m_MomentsScaleSkewVersorRigid3D->setChecked(transformValues[17]); m_Controls.m_GeometryScaleSkewVersorRigid3D->setChecked(!transformValues[17]); } QString QmitkScaleSkewVersor3DTransformView::GetName() { return "ScaleSkewVersor3D"; } void QmitkScaleSkewVersor3DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale3->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScaleScaleSkewVersorRigid3DTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationZ->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale7->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale8->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale9->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale10->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale11->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale12->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale13->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale14->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale15->setValidator(validatorLineEditInputFloat); } itk::Array QmitkScaleSkewVersor3DTransformView::GetScales() { itk::Array scales; scales.SetSize(15); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesScaleSkewVersorRigid3DTransform->isChecked()) { scales[0] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale3->text().toDouble(); scales[3] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationX->text().toDouble(); scales[4] = m_Controls.m_ScaleScaleSkewVersorRigid3DTransformScaleTranslationY->text().toDouble(); scales[5] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScaleTranslationZ->text().toDouble(); scales[6] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale7->text().toDouble(); scales[7] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale8->text().toDouble(); scales[8] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale9->text().toDouble(); scales[9] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale10->text().toDouble(); scales[10] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale11->text().toDouble(); scales[11] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale12->text().toDouble(); scales[12] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale13->text().toDouble(); scales[13] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale14->text().toDouble(); scales[14] = m_Controls.m_ScalesScaleSkewVersorRigid3DTransformScale15->text().toDouble(); } return scales; } vtkTransform* QmitkScaleSkewVersor3DTransformView::Transform(vtkMatrix4x4* vtkmatrix, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { itk::ScaleSkewVersor3DTransform::Pointer versorTransform = itk::ScaleSkewVersor3DTransform::New(); versorTransform->SetParameters(transformParams); itk::Matrix Matrix = versorTransform->GetMatrix(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { vtkmatrix->SetElement(i, j, Matrix[i][j]); } } float center[4]; float translation[4]; center[0] = m_CenterX; center[1] = m_CenterY; center[2] = m_CenterZ; center[3] = 1; vtkmatrix->MultiplyPoint(center, translation); vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[3]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[4]); vtkmatrix->SetElement(2, 3, -translation[2] + center[2] + transformParams[5]); vtktransform->SetMatrix(vtkmatrix); } return vtktransform; } int QmitkScaleSkewVersor3DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 0; else return 15; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity2DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity2DTransformView.cpp index 52f3b3b69a..16fa157492 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity2DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity2DTransformView.cpp @@ -1,173 +1,174 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkSimilarity2DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkSimilarity2DTransformView::QmitkSimilarity2DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkSimilarity2DTransformView::~QmitkSimilarity2DTransformView() { } mitk::TransformParameters::TransformType QmitkSimilarity2DTransformView::GetTransformType() { return mitk::TransformParameters::SIMILARITY2DTRANSFORM; } itk::Object::Pointer QmitkSimilarity2DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkSimilarity2DTransformView::GetTransform2(itk::Image* /* itkImage1 */) { if (VImageDimension == 2) { typedef typename itk::Image< TPixelType, 2 > FixedImage2DType; typedef typename itk::Image< TPixelType, 2 > MovingImage2DType; typename FixedImage2DType::Pointer fixedImage2D; mitk::CastToItkImage(m_FixedImage, fixedImage2D); typename MovingImage2DType::Pointer movingImage2D; mitk::CastToItkImage(m_MovingImage, movingImage2D); typename itk::Similarity2DTransform< double >::Pointer transformPointer = itk::Similarity2DTransform< double >::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerSimilarity2D->isChecked()) { typedef typename itk::Similarity2DTransform< double > Similarity2DTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage2D ); transformInitializer->SetMovingImage( movingImage2D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsSimilarity2D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } transformPointer->SetScale( m_Controls.m_InitialScaleSimilarity2D->text().toFloat() ); transformPointer->SetAngle( m_Controls.m_AngleSimilarity2D->text().toFloat() ); m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkSimilarity2DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(9); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesSimilarity2D->isChecked(); transformValues[1] = m_Controls.m_ScalingScaleSimilarity2D->text().toDouble(); transformValues[2] = m_Controls.m_RotationScaleSimilarity2D->text().toDouble(); transformValues[3] = m_Controls.m_TranslationXScaleSimilarity2D->text().toDouble(); transformValues[4] = m_Controls.m_TranslationYScaleSimilarity2D->text().toDouble(); transformValues[5] = m_Controls.m_InitialScaleSimilarity2D->text().toFloat(); transformValues[6] = m_Controls.m_AngleSimilarity2D->text().toFloat(); transformValues[7] = m_Controls.m_CenterForInitializerSimilarity2D->isChecked(); transformValues[8] = m_Controls.m_MomentsSimilarity2D->isChecked(); return transformValues; } void QmitkSimilarity2DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesSimilarity2D->setChecked(transformValues[0]); m_Controls.m_ScalingScaleSimilarity2D->setText(QString::number(transformValues[1])); m_Controls.m_RotationScaleSimilarity2D->setText(QString::number(transformValues[2])); m_Controls.m_TranslationXScaleSimilarity2D->setText(QString::number(transformValues[3])); m_Controls.m_TranslationYScaleSimilarity2D->setText(QString::number(transformValues[4])); m_Controls.m_InitialScaleSimilarity2D->setText(QString::number(transformValues[5])); m_Controls.m_AngleSimilarity2D->setText(QString::number(transformValues[6])); m_Controls.m_CenterForInitializerSimilarity2D->setChecked(transformValues[7]); m_Controls.m_MomentsSimilarity2D->setChecked(transformValues[8]); m_Controls.m_GeometrySimilarity2D->setChecked(!transformValues[8]); } QString QmitkSimilarity2DTransformView::GetName() { return "Similarity2D"; } void QmitkSimilarity2DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalingScaleSimilarity2D->setValidator(validatorLineEditInputFloat); m_Controls.m_RotationScaleSimilarity2D->setValidator(validatorLineEditInputFloat); m_Controls.m_TranslationXScaleSimilarity2D->setValidator(validatorLineEditInputFloat); m_Controls.m_TranslationYScaleSimilarity2D->setValidator(validatorLineEditInputFloat); } itk::Array QmitkSimilarity2DTransformView::GetScales() { itk::Array scales; scales.SetSize(4); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesSimilarity2D->isChecked()) { scales[0] = m_Controls.m_ScalingScaleSimilarity2D->text().toDouble(); scales[1] = m_Controls.m_RotationScaleSimilarity2D->text().toDouble(); scales[2] = m_Controls.m_TranslationXScaleSimilarity2D->text().toDouble(); scales[3] = m_Controls.m_TranslationYScaleSimilarity2D->text().toDouble(); } return scales; } vtkTransform* QmitkSimilarity2DTransformView::Transform(vtkMatrix4x4* /* vtkmatrix */, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { mitk::ScalarType angle = transformParams[1] * 45.0 / atan(1.0); vtktransform->PostMultiply(); vtktransform->Scale(transformParams[0], transformParams[0], 1); vtktransform->RotateZ(angle); vtktransform->Translate(transformParams[2], transformParams[3], 0); vtktransform->PreMultiply(); } return vtktransform; } int QmitkSimilarity2DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 4; else return 0; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity3DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity3DTransformView.cpp index 05f298bbf3..0bfc2b9cb4 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity3DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkSimilarity3DTransformView.cpp @@ -1,197 +1,198 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkSimilarity3DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkSimilarity3DTransformView::QmitkSimilarity3DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkSimilarity3DTransformView::~QmitkSimilarity3DTransformView() { } mitk::TransformParameters::TransformType QmitkSimilarity3DTransformView::GetTransformType() { return mitk::TransformParameters::SIMILARITY3DTRANSFORM; } itk::Object::Pointer QmitkSimilarity3DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkSimilarity3DTransformView::GetTransform2(itk::Image* /*itkImage1*/) { if (VImageDimension == 3) { typedef typename itk::Image< TPixelType, 3 > FixedImage3DType; typedef typename itk::Image< TPixelType, 3 > MovingImage3DType; typename FixedImage3DType::Pointer fixedImage3D; mitk::CastToItkImage(m_FixedImage, fixedImage3D); typename MovingImage3DType::Pointer movingImage3D; mitk::CastToItkImage(m_MovingImage, movingImage3D); typename itk::Similarity3DTransform< double >::Pointer transformPointer = itk::Similarity3DTransform< double >::New(); transformPointer->SetIdentity(); if (m_Controls.m_CenterForInitializerSimilarity3D->isChecked()) { typedef typename itk::Similarity3DTransform< double > Similarity3DTransformType; typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage3D ); transformInitializer->SetMovingImage( movingImage3D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsSimilarity3D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_CenterZ = transformPointer->GetCenter()[2]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkSimilarity3DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(10); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesSimilarity3D->isChecked(); transformValues[1] = m_Controls.m_ScalesSimilarity3DTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesSimilarity3DTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesSimilarity3DTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_ScalesSimilarity3DTransformScale4->text().toDouble(); transformValues[5] = m_Controls.m_ScalesSimilarity3DTransformScaleTranslationX->text().toDouble(); transformValues[6] = m_Controls.m_ScalesSimilarity3DTransformScaleTranslationY->text().toDouble(); transformValues[7] = m_Controls.m_ScalesSimilarity3DTransformScaleTranslationZ->text().toDouble(); transformValues[8] = m_Controls.m_CenterForInitializerSimilarity3D->isChecked(); transformValues[9] = m_Controls.m_MomentsSimilarity3D->isChecked(); return transformValues; } void QmitkSimilarity3DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesSimilarity3D->setChecked(transformValues[0]); m_Controls.m_ScalesSimilarity3DTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesSimilarity3DTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesSimilarity3DTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_ScalesSimilarity3DTransformScale4->setText(QString::number(transformValues[4])); m_Controls.m_ScalesSimilarity3DTransformScaleTranslationX->setText(QString::number(transformValues[5])); m_Controls.m_ScalesSimilarity3DTransformScaleTranslationY->setText(QString::number(transformValues[6])); m_Controls.m_ScalesSimilarity3DTransformScaleTranslationZ->setText(QString::number(transformValues[7])); m_Controls.m_CenterForInitializerSimilarity3D->setChecked(transformValues[8]); m_Controls.m_MomentsSimilarity3D->setChecked(transformValues[9]); m_Controls.m_GeometrySimilarity3D->setChecked(!transformValues[9]); } QString QmitkSimilarity3DTransformView::GetName() { return "Similarity3D"; } void QmitkSimilarity3DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesSimilarity3DTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesSimilarity3DTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesSimilarity3DTransformScale3->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesSimilarity3DTransformScale4->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesSimilarity3DTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesSimilarity3DTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesSimilarity3DTransformScaleTranslationZ->setValidator(validatorLineEditInputFloat); } itk::Array QmitkSimilarity3DTransformView::GetScales() { itk::Array scales; scales.SetSize(7); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesSimilarity3D->isChecked()) { scales[0] = m_Controls.m_ScalesSimilarity3DTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesSimilarity3DTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesSimilarity3DTransformScale3->text().toDouble(); scales[3] = m_Controls.m_ScalesSimilarity3DTransformScale4->text().toDouble(); scales[4] = m_Controls.m_ScalesSimilarity3DTransformScaleTranslationX->text().toDouble(); scales[5] = m_Controls.m_ScalesSimilarity3DTransformScaleTranslationY->text().toDouble(); scales[6] = m_Controls.m_ScalesSimilarity3DTransformScaleTranslationZ->text().toDouble(); } return scales; } vtkTransform* QmitkSimilarity3DTransformView::Transform(vtkMatrix4x4* vtkmatrix, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { itk::Similarity3DTransform::Pointer similarityTransform = itk::Similarity3DTransform::New(); similarityTransform->SetParameters(transformParams); itk::Matrix Matrix = similarityTransform->GetMatrix(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { vtkmatrix->SetElement(i, j, Matrix[i][j]); } } float center[4]; float translation[4]; center[0] = m_CenterX; center[1] = m_CenterY; center[2] = m_CenterZ; center[3] = 1; vtkmatrix->MultiplyPoint(center, translation); vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[4]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[5]); vtkmatrix->SetElement(2, 3, -translation[2] + center[2] + transformParams[6]); vtktransform->SetMatrix(vtkmatrix); } return vtktransform; } int QmitkSimilarity3DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 0; else return 7; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorRigid3DTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorRigid3DTransformView.cpp index e0c5b62e03..3ec9a4a320 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorRigid3DTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorRigid3DTransformView.cpp @@ -1,208 +1,209 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkVersorRigid3DTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkVersorRigid3DTransformView::QmitkVersorRigid3DTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkVersorRigid3DTransformView::~QmitkVersorRigid3DTransformView() { } mitk::TransformParameters::TransformType QmitkVersorRigid3DTransformView::GetTransformType() { return mitk::TransformParameters::VERSORRIGID3DTRANSFORM; } itk::Object::Pointer QmitkVersorRigid3DTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkVersorRigid3DTransformView::GetTransform2(itk::Image* /*itkImage1*/) { if (VImageDimension == 3) { typedef typename itk::Image< TPixelType, 3 > FixedImage3DType; typedef typename itk::Image< TPixelType, 3 > MovingImage3DType; typename FixedImage3DType::Pointer fixedImage3D; mitk::CastToItkImage(m_FixedImage, fixedImage3D); typename MovingImage3DType::Pointer movingImage3D; mitk::CastToItkImage(m_MovingImage, movingImage3D); typename itk::VersorRigid3DTransform< double >::Pointer transformPointer = itk::VersorRigid3DTransform< double >::New(); transformPointer->SetIdentity(); typedef typename itk::VersorRigid3DTransform< double > VersorRigid3DTransformType; if (m_Controls.m_CenterForInitializerVersorRigid3D->isChecked()) { typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage3D ); transformInitializer->SetMovingImage( movingImage3D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsVersorRigid3D->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } typedef VersorRigid3DTransformType::VersorType VersorType; typedef VersorType::VectorType VectorType; VersorType rotation; VectorType axis; axis[0] = 0.0; axis[1] = 0.0; axis[2] = 1.0; const double angle = 0; rotation.Set( axis, angle ); transformPointer->SetRotation( rotation ); m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_CenterZ = transformPointer->GetCenter()[2]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkVersorRigid3DTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(9); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesVersorRigid3D->isChecked(); transformValues[1] = m_Controls.m_ScalesVersorRigid3DTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesVersorRigid3DTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesVersorRigid3DTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationX->text().toDouble(); transformValues[5] = m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationY->text().toDouble(); transformValues[6] = m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationZ->text().toDouble(); transformValues[7] = m_Controls.m_CenterForInitializerVersorRigid3D->isChecked(); transformValues[8] = m_Controls.m_MomentsVersorRigid3D->isChecked(); return transformValues; } void QmitkVersorRigid3DTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesVersorRigid3D->setChecked(transformValues[0]); m_Controls.m_ScalesVersorRigid3DTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesVersorRigid3DTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesVersorRigid3DTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationX->setText(QString::number(transformValues[4])); m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationY->setText(QString::number(transformValues[5])); m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationZ->setText(QString::number(transformValues[6])); m_Controls.m_CenterForInitializerVersorRigid3D->setChecked(transformValues[7]); m_Controls.m_MomentsVersorRigid3D->setChecked(transformValues[8]); m_Controls.m_GeometryVersorRigid3D->setChecked(!transformValues[8]); } QString QmitkVersorRigid3DTransformView::GetName() { return "VersorRigid3D"; } void QmitkVersorRigid3DTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesVersorRigid3DTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesVersorRigid3DTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesVersorRigid3DTransformScale3->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationX->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationY->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationZ->setValidator(validatorLineEditInputFloat); } itk::Array QmitkVersorRigid3DTransformView::GetScales() { itk::Array scales; scales.SetSize(6); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesVersorRigid3D->isChecked()) { scales[0] = m_Controls.m_ScalesVersorRigid3DTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesVersorRigid3DTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesVersorRigid3DTransformScale3->text().toDouble(); scales[3] = m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationX->text().toDouble(); scales[4] = m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationY->text().toDouble(); scales[5] = m_Controls.m_ScalesVersorRigid3DTransformScaleTranslationZ->text().toDouble(); } return scales; } vtkTransform* QmitkVersorRigid3DTransformView::Transform(vtkMatrix4x4* vtkmatrix, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { itk::VersorRigid3DTransform::Pointer versorTransform = itk::VersorRigid3DTransform::New(); versorTransform->SetParameters(transformParams); itk::Matrix Matrix = versorTransform->GetMatrix(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { vtkmatrix->SetElement(i, j, Matrix[i][j]); } } float center[4]; float translation[4]; center[0] = m_CenterX; center[1] = m_CenterY; center[2] = m_CenterZ; center[3] = 1; vtkmatrix->MultiplyPoint(center, translation); vtkmatrix->SetElement(0, 3, -translation[0] + center[0] + transformParams[3]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1] + transformParams[4]); vtkmatrix->SetElement(2, 3, -translation[2] + center[2] + transformParams[5]); vtktransform->SetMatrix(vtkmatrix); } return vtktransform; } int QmitkVersorRigid3DTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 0; else return 6; } else return 0; } diff --git a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorTransformView.cpp b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorTransformView.cpp index 77d6d5e965..7eb2c4a033 100644 --- a/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorTransformView.cpp +++ b/Modules/RigidRegistrationUI/RigidRegistrationTransforms/QmitkVersorTransformView.cpp @@ -1,181 +1,182 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: -1 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkVersorTransformView.h" #include "mitkImageAccessByItk.h" +#include #include #include #include QmitkVersorTransformView::QmitkVersorTransformView(QWidget* parent, Qt::WindowFlags f ) : QmitkRigidRegistrationTransformsGUIBase(parent, f), m_CenterX(0), m_CenterY(0), m_CenterZ(0) { } QmitkVersorTransformView::~QmitkVersorTransformView() { } mitk::TransformParameters::TransformType QmitkVersorTransformView::GetTransformType() { return mitk::TransformParameters::VERSORTRANSFORM; } itk::Object::Pointer QmitkVersorTransformView::GetTransform() { if (m_FixedImage.IsNotNull()) { AccessByItk(m_FixedImage, GetTransform2); return m_TransformObject; } return NULL; } template < class TPixelType, unsigned int VImageDimension > itk::Object::Pointer QmitkVersorTransformView::GetTransform2(itk::Image* /*itkImage1*/) { if (VImageDimension == 3) { typedef typename itk::Image< TPixelType, 3 > FixedImage3DType; typedef typename itk::Image< TPixelType, 3 > MovingImage3DType; typename FixedImage3DType::Pointer fixedImage3D; mitk::CastToItkImage(m_FixedImage, fixedImage3D); typename MovingImage3DType::Pointer movingImage3D; mitk::CastToItkImage(m_MovingImage, movingImage3D); typename itk::VersorTransform< double >::Pointer transformPointer = itk::VersorTransform< double >::New(); transformPointer->SetIdentity(); typedef typename itk::VersorTransform< double > VersorTransformType; if (m_Controls.m_CenterForInitializerVersor->isChecked()) { typedef typename itk::CenteredTransformInitializer TransformInitializerType; typename TransformInitializerType::Pointer transformInitializer = TransformInitializerType::New(); transformInitializer->SetFixedImage( fixedImage3D ); transformInitializer->SetMovingImage( movingImage3D ); transformInitializer->SetTransform( transformPointer ); if (m_Controls.m_MomentsVersor->isChecked()) { transformInitializer->MomentsOn(); } else { transformInitializer->GeometryOn(); } transformInitializer->InitializeTransform(); } m_CenterX = transformPointer->GetCenter()[0]; m_CenterY = transformPointer->GetCenter()[1]; m_CenterZ = transformPointer->GetCenter()[2]; m_TransformObject = transformPointer.GetPointer(); return transformPointer.GetPointer(); } return NULL; } itk::Array QmitkVersorTransformView::GetTransformParameters() { itk::Array transformValues; transformValues.SetSize(6); transformValues.fill(0); transformValues[0] = m_Controls.m_UseOptimizerScalesVersor->isChecked(); transformValues[1] = m_Controls.m_ScalesVersorTransformScale1->text().toDouble(); transformValues[2] = m_Controls.m_ScalesVersorTransformScale2->text().toDouble(); transformValues[3] = m_Controls.m_ScalesVersorTransformScale3->text().toDouble(); transformValues[4] = m_Controls.m_CenterForInitializerVersor->isChecked(); transformValues[5] = m_Controls.m_MomentsVersor->isChecked(); return transformValues; } void QmitkVersorTransformView::SetTransformParameters(itk::Array transformValues) { m_Controls.m_UseOptimizerScalesVersor->setChecked(transformValues[0]); m_Controls.m_ScalesVersorTransformScale1->setText(QString::number(transformValues[1])); m_Controls.m_ScalesVersorTransformScale2->setText(QString::number(transformValues[2])); m_Controls.m_ScalesVersorTransformScale3->setText(QString::number(transformValues[3])); m_Controls.m_CenterForInitializerVersor->setChecked(transformValues[4]); m_Controls.m_MomentsVersor->setChecked(transformValues[5]); m_Controls.m_GeometryVersor->setChecked(!transformValues[5]); } QString QmitkVersorTransformView::GetName() { return "Versor"; } void QmitkVersorTransformView::SetupUI(QWidget* parent) { m_Controls.setupUi(parent); QValidator* validatorLineEditInputFloat = new QDoubleValidator(0, 20000000, 8, this); m_Controls.m_ScalesVersorTransformScale1->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesVersorTransformScale2->setValidator(validatorLineEditInputFloat); m_Controls.m_ScalesVersorTransformScale3->setValidator(validatorLineEditInputFloat); } itk::Array QmitkVersorTransformView::GetScales() { itk::Array scales; scales.SetSize(3); scales.Fill(1.0); if (m_Controls.m_UseOptimizerScalesVersor->isChecked()) { scales[0] = m_Controls.m_ScalesVersorTransformScale1->text().toDouble(); scales[1] = m_Controls.m_ScalesVersorTransformScale2->text().toDouble(); scales[2] = m_Controls.m_ScalesVersorTransformScale3->text().toDouble(); } return scales; } vtkTransform* QmitkVersorTransformView::Transform(vtkMatrix4x4* vtkmatrix, vtkTransform* vtktransform, itk::Array transformParams) { if (m_MovingImage.IsNotNull()) { itk::VersorTransform::Pointer versorTransform = itk::VersorTransform::New(); versorTransform->SetParameters(transformParams); itk::Matrix Matrix = versorTransform->GetMatrix(); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { vtkmatrix->SetElement(i, j, Matrix[i][j]); } } float center[4]; float translation[4]; center[0] = m_CenterX; center[1] = m_CenterY; center[2] = m_CenterZ; center[3] = 1; vtkmatrix->MultiplyPoint(center, translation); vtkmatrix->SetElement(0, 3, -translation[0] + center[0]); vtkmatrix->SetElement(1, 3, -translation[1] + center[1]); vtkmatrix->SetElement(2, 3, -translation[2] + center[2]); vtktransform->SetMatrix(vtkmatrix); } return vtktransform; } int QmitkVersorTransformView::GetNumberOfTransformParameters() { if (m_FixedImage.IsNotNull()) { if (m_FixedImage->GetDimension() == 2) return 0; else return 3; } else return 0; }