static mitk::Image::Pointer ResampleDWIbySpacing(mitk::Image::Pointer input, float* spacing) { itk::Vector<double, 3> spacingVector; spacingVector[0] = spacing[0]; spacingVector[1] = spacing[1]; spacingVector[2] = spacing[2]; typedef itk::ResampleDwiImageFilter<short> ResampleFilterType; mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(input, itkVectorImagePointer); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput( itkVectorImagePointer ); resampler->SetInterpolation(ResampleFilterType::Interpolate_Linear); resampler->SetNewSpacing(spacingVector); resampler->Update(); mitk::Image::Pointer output = mitk::GrabItkImageMemory( resampler->GetOutput() ); output->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer(input) ) ); output->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ) ); mitk::DiffusionPropertyHelper propertyHelper( output ); propertyHelper.InitializeImage(); return output; }
static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol = false) { // Convert to itk Images InputImageType::Pointer itkReference = InputImageType::New(); InputImageType::Pointer itkMoving = InputImageType::New(); mitk::CastToItkImage(reference,itkReference); mitk::CastToItkImage(moving,itkMoving); // Identify Transform typedef itk::IdentityTransform<double, 3> T_Transform; T_Transform::Pointer _pTransform = T_Transform::New(); _pTransform->SetIdentity(); typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 3> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::ResampleImageFilter<InputImageType, InputImageType> ResampleFilterType; ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkMoving); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); resampler->SetTransform(_pTransform); resampler->SetInterpolator(sinc_interpolator); resampler->Update(); // Convert back to mitk mitk::Image::Pointer result = mitk::Image::New(); result->InitializeByItk(resampler->GetOutput()); GrabItkImageMemory( resampler->GetOutput() , result ); return result; }
// perform B-spline registration for 2D image void runBspline2D(StringVector& args) { typedef itk::BSplineTransform<double, 2, 3> TransformType; typedef itk::LBFGSOptimizer OptimizerType; typedef itk::MeanSquaresImageToImageMetric<RealImage2, RealImage2> MetricType; typedef itk:: LinearInterpolateImageFunction<RealImage2, double> InterpolatorType; typedef itk::ImageRegistrationMethod<RealImage2, RealImage2> RegistrationType; MetricType::Pointer metric = MetricType::New(); OptimizerType::Pointer optimizer = OptimizerType::New(); InterpolatorType::Pointer interpolator = InterpolatorType::New(); RegistrationType::Pointer registration = RegistrationType::New(); // The old registration framework has problems with multi-threading // For now, we set the number of threads to 1 registration->SetNumberOfThreads(1); registration->SetMetric( metric ); registration->SetOptimizer( optimizer ); registration->SetInterpolator( interpolator ); TransformType::Pointer transform = TransformType::New(); registration->SetTransform( transform ); ImageIO<RealImage2> io; // Create the synthetic images RealImage2::Pointer fixedImage = io.ReadImage(args[0]); RealImage2::Pointer movingImage = io.ReadImage(args[1]); // Setup the registration registration->SetFixedImage( fixedImage ); registration->SetMovingImage( movingImage); RealImage2::RegionType fixedRegion = fixedImage->GetBufferedRegion(); registration->SetFixedImageRegion( fixedRegion ); TransformType::PhysicalDimensionsType fixedPhysicalDimensions; TransformType::MeshSizeType meshSize; for( unsigned int i=0; i < 2; i++ ) { fixedPhysicalDimensions[i] = fixedImage->GetSpacing()[i] * static_cast<double>( fixedImage->GetLargestPossibleRegion().GetSize()[i] - 1 ); } unsigned int numberOfGridNodesInOneDimension = 18; meshSize.Fill( numberOfGridNodesInOneDimension - 3 ); transform->SetTransformDomainOrigin( fixedImage->GetOrigin() ); transform->SetTransformDomainPhysicalDimensions( fixedPhysicalDimensions ); transform->SetTransformDomainMeshSize( meshSize ); transform->SetTransformDomainDirection( fixedImage->GetDirection() ); typedef TransformType::ParametersType ParametersType; const unsigned int numberOfParameters = transform->GetNumberOfParameters(); ParametersType parameters( 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; // Next we set the parameters of the LBFGS Optimizer. optimizer->SetGradientConvergenceTolerance( 0.005 ); optimizer->SetLineSearchAccuracy( 0.9 ); optimizer->SetDefaultStepLength( .1 ); optimizer->TraceOn(); optimizer->SetMaximumNumberOfFunctionEvaluations( 1000 ); std::cout << std::endl << "Starting Registration" << std::endl; try { registration->Update(); std::cout << "Optimizer stop condition = " << registration->GetOptimizer()->GetStopConditionDescription() << std::endl; } catch( itk::ExceptionObject & err ) { std::cerr << "ExceptionObject caught !" << std::endl; std::cerr << err << std::endl; return; } OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters(); std::cout << "Last Transform Parameters" << std::endl; std::cout << finalParameters << std::endl; transform->SetParameters( finalParameters ); typedef itk::ResampleImageFilter<RealImage2, RealImage2> ResampleFilterType; ResampleFilterType::Pointer resample = ResampleFilterType::New(); resample->SetTransform( transform ); resample->SetInput( movingImage ); resample->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() ); resample->SetOutputOrigin( fixedImage->GetOrigin() ); resample->SetOutputSpacing( fixedImage->GetSpacing() ); resample->SetOutputDirection( fixedImage->GetDirection() ); resample->SetDefaultPixelValue( 100 ); resample->Update(); io.WriteImage(args[2], resample->GetOutput()); }
FilterImageType::Pointer gaussTransform(const FilterImageType::Pointer sourceImage, FilterImageType::SizeType destSize, float gaussSigma, const BaseTransformType *transform) { std::cerr << "Filter, Transformation and Output start" << std::endl; itk::TimeProbesCollectorBase collector; collector.Start( "Filter, Transformation and Output" ); collector.Start( "Filter" ); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; FilterImageType::SizeType sourceSize = sourceImage->GetBufferedRegion().GetSize(); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; FilterImageType::ConstPointer temp; #ifdef useFastMemoryHungryGaussian { GaussFilterType::Pointer filter = GaussFilterType::New(); filter->SetDirection( 0 ); // 0 --> X direction filter->SetOrder( GaussFilterType::ZeroOrder ); filter->SetSigma( gaussSigma ); filter->SetInput( sourceImage ); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; try { filter->Update(); } catch( itk::ExceptionObject & excep ) { std::cerr << "Exception caught !" << std::endl << excep << std::endl; } temp = filter->GetOutput(); } { GaussFilterType::Pointer filter = GaussFilterType::New(); filter->SetDirection( 1 ); // 1 --> Y direction filter->SetOrder( GaussFilterType::ZeroOrder ); filter->SetSigma( gaussSigma ); filter->SetInput( temp ); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; try { filter->Update(); } catch( itk::ExceptionObject & excep ) { std::cerr << "Exception caught !" << std::endl << excep << std::endl; } temp = filter->GetOutput(); } { GaussFilterType::Pointer filter = GaussFilterType::New(); filter->SetDirection( 2 ); // 2 --> Z direction filter->SetOrder( GaussFilterType::ZeroOrder ); filter->SetSigma( gaussSigma ); filter->SetInput( temp ); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; try { filter->Update(); } catch( itk::ExceptionObject & excep ) { std::cerr << "Exception caught !" << std::endl << excep << std::endl; } temp = filter->GetOutput(); } #else { GaussFilterType::Pointer filter = GaussFilterType::New(); filter->SetUseImageSpacingOn(); filter->SetVariance( std::sqrt(gaussSigma) ); filter->SetInput( sourceImage ); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; try { filter->Update(); } catch( itk::ExceptionObject & excep ) { std::cerr << "Exception caught !" << std::endl << excep << std::endl; } temp = filter->GetOutput(); } #endif collector.Stop( "Filter" ); InterpolatorType::Pointer interpolator = InterpolatorType::New(); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInterpolator( interpolator ); IdentityTransformType::Pointer identPointer; if (transform == NULL) { identPointer = IdentityTransformType::New(); transform = identPointer; } resampler->SetTransform( transform ); FilterImageType::SpacingType destSpacing; for(unsigned int i = 0; i < Dimension; ++i) { destSpacing[i] = sourceImage->GetSpacing()[i] * float(sourceSize[i]) / float(destSize[i]); } resampler->SetInput( temp ); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; resampler->SetSize( destSize ); resampler->SetOutputSpacing( destSpacing ); resampler->SetOutputOrigin( sourceImage->GetOrigin() ); resampler->SetDefaultPixelValue( 0 ); std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; FilterImageType::Pointer result; try { resampler->Update(); result = resampler->GetOutput(); } catch( itk::ExceptionObject & excep ) { std::cerr << "Exception caught !" << std::endl << excep << std::endl; } std::cerr << "dbg:" << __FILE__ << " line:" << __LINE__ << std::endl; collector.Stop( "Filter, Transformation and Output" ); collector.Report(); std::cerr << "Filter, Transformation and Output end" << std::endl; return result; }
int main(int argc, char** argv ) { /** * /home/morgan/invaginatingleg/invagination/invagination_T0.ome.tif * /home/morgan/invaginatingleg/invagination/invagination_T1.ome.tif * /home/morgan/invaginatingleg/invagination/invagination_T2.ome.tif * /home/morgan/invaginatingleg/invagination/invagination_T3.ome.tif * /home/morgan/invaginationmasked/invaginated_T4.ome.tif * /home/morgan/invaginationmasked/invaginated_T5.ome.tif * /home/morgan/invaginationmasked/invaginated_T6.ome.tif * /home/morgan/invaginationmasked/invaginated_T7.ome.tif * /home/morgan/invaginationmasked/invaginated_T8.ome.tif * /home/morgan/invaginationmasked/invaginated_T9.ome.tif * /home/morgan/invaginationmasked/invaginated_T10.ome.tif * /home/morgan/invaginationmasked/invaginated_T11.ome.tif * /home/morgan/invaginationmasked/invaginated_T12.ome.tif * /home/morgan/invaginationmasked/invaginated_T13.ome.tif * /home/morgan/invaginationmasked/invaginated_T14.ome.tif * /home/morgan/invaginationmasked/invaginated_T15.ome.tif * /home/morgan/invaginationmasked/invaginated_T16.ome.tif * /home/morgan/invaginationmasked/invaginated_T17.ome.tif * /home/morgan/invaginationmasked/invaginated_T18.ome.tif * /home/morgan/invaginationmasked/invaginated_T19.ome.tif * /home/morgan/invaginationmasked/invaginated_T20.ome.tif * /home/morgan/invaginationmasked/invaginated_T21.ome.tif * /home/morgan/invaginationmasked/invaginated_T22.ome.tif * output */ std::vector<std::string> inputFiles; typedef float PixelType; // Fixed Image Type typedef itk::Image<PixelType,3> FixedImageType; // Moving Image Type typedef itk::Image<PixelType,3> MovingImageType; typedef FixedImageType::SpacingType SpacingType; SpacingType spacing; //spacing[0]=0.3107403; //spacing[1]=0.3107403; //spacing[2]=0.739833; spacing[0]=0.1569476; spacing[1]=0.1569476; spacing[2]=0.6209697; // Transform Type typedef itk::VersorRigid3DTransform< double > TransformType; #if 0 inputFiles.push_back("/home/morgan/invaginatingleg/invagination/invagination_T0.ome.tif"); inputFiles.push_back("/home/morgan/invaginatingleg/invagination/invagination_T1.ome.tif"); typedef float VectorComponentType; typedef itk::Vector< VectorComponentType, 3 > VectorType; typedef itk::Image< VectorType, 3 > DeformationFieldType; typedef itk::ImageFileReader<FixedImageType> FixedImageReaderType; typedef itk::ImageFileReader<MovingImageType> MovingImageReaderType; FixedImageReaderType::Pointer fixedImageReader=FixedImageReaderType::New(); MovingImageReaderType::Pointer movingImageReader=MovingImageReaderType::New(); fixedImageReader->SetFileName(inputFiles[0]); movingImageReader->SetFileName(inputFiles[1]); fixedImageReader->Update(); movingImageReader->Update(); FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput(); MovingImageType::Pointer movingImage = movingImageReader->GetOutput(); fixedImage->SetSpacing(spacing); movingImage->SetSpacing(spacing); typedef itk::VersorRigid3DTransform< double > Rigid3DTransformType; typedef itk::LandmarkBasedTransformInitializer< Rigid3DTransformType, FixedImageType, MovingImageType > LandmarkBasedTransformInitializerType; LandmarkBasedTransformInitializerType::Pointer landmarkBasedTransformInitializer = LandmarkBasedTransformInitializerType::New(); // Create source and target landmarks. typedef LandmarkBasedTransformInitializerType::LandmarkPointContainer LandmarkContainerType; typedef LandmarkBasedTransformInitializerType::LandmarkPointType LandmarkPointType; LandmarkContainerType fixedLandmarks; LandmarkContainerType movingLandmarks; LandmarkPointType fixedPoint; LandmarkPointType movingPoint; fixedPoint[0] = 37.510; fixedPoint[1] = 34.685; fixedPoint[2] = 52*spacing[2]; movingPoint[0] = 31.468; movingPoint[1] = 27.593; movingPoint[2] = 50*spacing[2]; fixedLandmarks.push_back( fixedPoint ); movingLandmarks.push_back( movingPoint ); fixedPoint[0] = 32.645; fixedPoint[1] = 33.901; fixedPoint[2] = 52*spacing[2]; movingPoint[0] = 25.888; movingPoint[1] = 26.353; movingPoint[2] = 50*spacing[2]; fixedLandmarks.push_back( fixedPoint ); movingLandmarks.push_back( movingPoint ); fixedPoint[0] = 35.784; fixedPoint[1] = 37.354; fixedPoint[2] = 52*spacing[2]; movingPoint[0] = 29.918; movingPoint[1] = 29.918; movingPoint[2] = 50*spacing[2]; fixedLandmarks.push_back( fixedPoint ); movingLandmarks.push_back( movingPoint ); fixedPoint[0] = 33.116; fixedPoint[1] = 37.040; fixedPoint[2] = 52*spacing[2]; movingPoint[0] = 26.818; movingPoint[1] = 29.608; movingPoint[2] = 50*spacing[2]; fixedLandmarks.push_back( fixedPoint ); movingLandmarks.push_back( movingPoint ); landmarkBasedTransformInitializer->SetFixedLandmarks( fixedLandmarks ); landmarkBasedTransformInitializer->SetMovingLandmarks( movingLandmarks ); Rigid3DTransformType::Pointer transform = Rigid3DTransformType::New(); transform->SetIdentity(); landmarkBasedTransformInitializer->SetTransform(transform); landmarkBasedTransformInitializer->InitializeTransform(); typedef itk::ResampleImageFilter<FixedImageType, MovingImageType, double > ResampleFilterType; ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New(); resampleFilter->SetInput( movingImage ); resampleFilter->SetTransform( transform ); resampleFilter->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() ); resampleFilter->SetOutputOrigin( fixedImage->GetOrigin() ); resampleFilter->SetOutputSpacing( fixedImage->GetSpacing() ); resampleFilter->SetOutputDirection( fixedImage->GetDirection() ); resampleFilter->SetDefaultPixelValue(0); resampleFilter->GetOutput(); // Write the output typedef itk::ImageFileWriter< MovingImageType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetInput ( resampleFilter->GetOutput() ); writer->SetFileName( "output.ome.tif" ); writer->Update(); #endif for(int i=1;i<argc-1;i++){ inputFiles.push_back(argv[i]); } std::string outputPrefix=argv[argc-1]; int nImages = inputFiles.size(); std::vector<TransformType::Pointer >transforms(nImages); for(int i=0;i<nImages;i++){ transforms[i]=TransformType::New(); } transforms[0]->SetIdentity(); for(int i=1;i<nImages;i++){ /* * Read files */ std::cout << "Registering " << inputFiles[i] <<" to " <<inputFiles[i-1] << std::endl; typedef itk::ImageFileReader<FixedImageType> FixedImageReaderType; typedef itk::ImageFileReader<MovingImageType> MovingImageReaderType; FixedImageReaderType::Pointer fixedImageReader=FixedImageReaderType::New(); MovingImageReaderType::Pointer movingImageReader=MovingImageReaderType::New(); fixedImageReader->SetFileName(inputFiles[i-1]); movingImageReader->SetFileName(inputFiles[i]); fixedImageReader->Update(); movingImageReader->Update(); FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput(); MovingImageType::Pointer movingImage = movingImageReader->GetOutput(); fixedImage->SetSpacing(spacing); movingImage->SetSpacing(spacing); FixedImageType::SizeType size= fixedImage->GetLargestPossibleRegion().GetSize(); FixedImageType::PointType origin; origin[0]=size[0]*spacing[0]/2; origin[1]=size[1]*spacing[1]/2; origin[2]=size[2]*spacing[2]/2; fixedImage->SetOrigin(origin); movingImage->SetOrigin(origin); RegisterPair<FixedImageType,MovingImageType,TransformType>(fixedImage,movingImage,transforms[i]); } typedef itk::ResampleImageFilter<MovingImageType,MovingImageType> ResamplerType; ResamplerType::Pointer resampler = ResamplerType::New(); //transform->SetIdentity(); #if 0 TransformType::ParametersType initialParameters( transform->GetNumberOfParameters() ); initialParameters.Fill( 0 ); initialParameters[3] = 1.0; initialParameters[4]=10; initialParameters[5]=10; initialParameters[6]=0; transform->SetParameters(initialParameters); #endif for(int i=0;i<nImages;i++){ typedef itk::ImageFileReader<MovingImageType> MovingImageReaderType; MovingImageReaderType::Pointer movingImageReader=MovingImageReaderType::New(); movingImageReader->SetFileName(inputFiles[i]); movingImageReader->Update(); MovingImageType::Pointer movingImage = movingImageReader->GetOutput(); movingImage->SetSpacing(spacing); MovingImageType::SizeType size = movingImage->GetLargestPossibleRegion().GetSize(); MovingImageType::SizeType resampledSize; resampledSize[0]=1280; resampledSize[1]=1280; resampledSize[2]=150; resampler->SetSize(resampledSize ); typedef itk::TranslationTransform<double,3> TranslationTransformType; TranslationTransformType::Pointer translationTransform = TranslationTransformType::New(); TranslationTransformType::OutputVectorType translation; translation[0] = -20;//-(resampledSize[0]-size[0])/2*spacing[0]; translation[1] = -20;// -(resampledSize[1]-size[1])/2*spacing[1]; translation[2] = -20; //-(resampledSize[2]-size[2])/2*spacing[2]; translationTransform->Translate(translation); typedef itk::CompositeTransform<double,3> CompositeType; CompositeType::Pointer composite = CompositeType::New(); composite->AddTransform(translationTransform); for(int k=1;k<=i;k++){ composite->AddTransform(transforms[k]); } std::cout << "Origin: " << movingImage->GetOrigin() << std::endl; resampler->SetInput(movingImage); resampler->SetTransform(composite); resampler->SetOutputOrigin(movingImage->GetOrigin()); resampler->SetOutputSpacing( movingImage->GetSpacing() ); resampler->SetOutputDirection( movingImage->GetDirection() ); resampler->SetDefaultPixelValue( 0 ); resampler->Update(); std::stringstream ss; ss << outputPrefix << "-T" << i << ".ome.tif"; std::string filename; ss >> filename; typedef itk::ImageFileWriter<MovingImageType> MovingImageWriterType; MovingImageWriterType::Pointer movingImageWriter=MovingImageWriterType::New(); movingImageWriter->SetFileName(filename); movingImageWriter->SetInput(resampler->GetOutput()); movingImageWriter->Update(); std::cout << transforms[i] << std::endl; } }
int main( int argc, char *argv[] ) { if( argc < 4 ) { std::cerr << "Missing Parameters " << std::endl; std::cerr << "Usage: " << argv[0]; std::cerr << " fixedImageFile movingImageFile "; std::cerr << " outputImagefile [differenceBeforeRegistration] "; std::cerr << " [differenceAfterRegistration] "; std::cerr << " [sliceBeforeRegistration] "; std::cerr << " [sliceDifferenceBeforeRegistration] "; std::cerr << " [sliceDifferenceAfterRegistration] "; std::cerr << " [sliceAfterRegistration] " << std::endl; return EXIT_FAILURE; } const unsigned int Dimension = 3; typedef float PixelType; typedef itk::Image< PixelType, Dimension > FixedImageType; typedef itk::Image< PixelType, Dimension > MovingImageType; // Software Guide : BeginLatex // // The Transform class is instantiated using the code below. The only // template parameter to this class is the representation type of the // space coordinates. // // \index{itk::Versor\-Rigid3D\-Transform!Instantiation} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet // Software Guide : EndCodeSnippet typedef itk:: LinearInterpolateImageFunction< MovingImageType, double > InterpolatorType; typedef itk::ImageRegistrationMethod< FixedImageType, MovingImageType > RegistrationType; MetricType::Pointer metric = MetricType::New(); OptimizerType::Pointer optimizer = OptimizerType::New(); InterpolatorType::Pointer interpolator = InterpolatorType::New(); RegistrationType::Pointer registration = RegistrationType::New(); registration->SetMetric( metric ); registration->SetOptimizer( optimizer ); registration->SetInterpolator( interpolator ); // Software Guide : BeginLatex // // The transform object is constructed below and passed to the registration // method. // // \index{itk::Versor\-Rigid3D\-Transform!New()} // \index{itk::Versor\-Rigid3D\-Transform!Pointer} // \index{itk::Registration\-Method!SetTransform()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet TransformType::Pointer transform = TransformType::New(); registration->SetTransform( transform ); // Software Guide : EndCodeSnippet typedef itk::ImageFileReader< FixedImageType > FixedImageReaderType; typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType; FixedImageReaderType::Pointer fixedImageReader = FixedImageReaderType::New(); MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New(); fixedImageReader->SetFileName( argv[1] ); movingImageReader->SetFileName( argv[2] ); registration->SetFixedImage( fixedImageReader->GetOutput() ); registration->SetMovingImage( movingImageReader->GetOutput() ); fixedImageReader->Update(); registration->SetFixedImageRegion( fixedImageReader->GetOutput()->GetBufferedRegion() ); // Software Guide : BeginLatex // // The input images are taken from readers. It is not necessary here to // explicitly call \code{Update()} on the readers since the // \doxygen{CenteredTransformInitializer} will do it as part of its // computations. The following code instantiates the type of the // initializer. This class is templated over the fixed and moving image type // as well as the transform type. An initializer is then constructed by // calling the \code{New()} method and assigning the result to a smart // pointer. // // \index{itk::Centered\-Transform\-Initializer!Instantiation} // \index{itk::Centered\-Transform\-Initializer!New()} // \index{itk::Centered\-Transform\-Initializer!SmartPointer} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet // Software Guide : BeginLatex // // Let's execute this example over some of the images available in the ftp // site // // \url{ftp://public.kitware.com/pub/itk/Data/BrainWeb} // // Note that the images in the ftp site are compressed in \code{.tgz} files. // You should download these files an uncompress them in your local system. // After decompressing and extracting the files you could take a pair of // volumes, for example the pair: // // \begin{itemize} // \item \code{brainweb1e1a10f20.mha} // \item \code{brainweb1e1a10f20Rot10Tx15.mha} // \end{itemize} // // The second image is the result of intentionally rotating the first image // by $10$ degrees around the origin and shifting it $15mm$ in $X$. The // registration takes $24$ iterations and produces: // // \begin{center} // \begin{verbatim} // [-6.03744e-05, 5.91487e-06, -0.0871932, 2.64659, -17.4637, -0.00232496] // \end{verbatim} // \end{center} // // That are interpreted as // // \begin{itemize} // \item Versor = $(-6.03744e-05, 5.91487e-06, -0.0871932)$ // \item Translation = $(2.64659, -17.4637, -0.00232496)$ millimeters // \end{itemize} // // This Versor is equivalent to a rotation of $9.98$ degrees around the $Z$ // axis. // // Note that the reported translation is not the translation of $(15.0,0.0,0.0)$ // that we may be naively expecting. The reason is that the // \code{VersorRigid3DTransform} is applying the rotation around the center // found by the \code{CenteredTransformInitializer} and then adding the // translation vector shown above. // // It is more illustrative in this case to take a look at the actual // rotation matrix and offset resulting form the $6$ parameters. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet transform->SetParameters( finalParameters ); TransformType::MatrixType matrix = transform->GetMatrix(); TransformType::OffsetType offset = transform->GetOffset(); std::cout << "Matrix = " << std::endl << matrix << std::endl; std::cout << "Offset = " << std::endl << offset << std::endl; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The output of this print statements is // // \begin{center} // \begin{verbatim} // Matrix = // 0.984795 0.173722 2.23132e-05 // -0.173722 0.984795 0.000119257 // -1.25621e-06 -0.00012132 1 // // Offset = // [-15.0105, -0.00672343, 0.0110854] // \end{verbatim} // \end{center} // // From the rotation matrix it is possible to deduce that the rotation is // happening in the X,Y plane and that the angle is on the order of // $\arcsin{(0.173722)}$ which is very close to 10 degrees, as we expected. // // Software Guide : EndLatex // Software Guide : BeginLatex // // \begin{figure} // \center // \includegraphics[width=0.44\textwidth]{BrainProtonDensitySliceBorder20} // \includegraphics[width=0.44\textwidth]{BrainProtonDensitySliceR10X13Y17} // \itkcaption[CenteredTransformInitializer input images]{Fixed and moving image // provided as input to the registration method using // CenteredTransformInitializer.} // \label{fig:FixedMovingImageRegistration8} // \end{figure} // // // \begin{figure} // \center // \includegraphics[width=0.32\textwidth]{ImageRegistration8Output} // \includegraphics[width=0.32\textwidth]{ImageRegistration8DifferenceBefore} // \includegraphics[width=0.32\textwidth]{ImageRegistration8DifferenceAfter} // \itkcaption[CenteredTransformInitializer output images]{Resampled moving // image (left). Differences between fixed and moving images, before (center) // and after (right) registration with the // CenteredTransformInitializer.} // \label{fig:ImageRegistration8Outputs} // \end{figure} // // Figure \ref{fig:ImageRegistration8Outputs} shows the output of the // registration. The center image in this figure shows the differences // between the fixed image and the resampled moving image before the // registration. The image on the right side presents the difference between // the fixed image and the resampled moving image after the registration has // been performed. Note that these images are individual slices extracted // from the actual volumes. For details, look at the source code of this // example, where the ExtractImageFilter is used to extract a slice from the // the center of each one of the volumes. One of the main purposes of this // example is to illustrate that the toolkit can perform registration on // images of any dimension. The only limitations are, as usual, the amount of // memory available for the images and the amount of computation time that it // will take to complete the optimization process. // // \begin{figure} // \center // \includegraphics[height=0.32\textwidth]{ImageRegistration8TraceMetric} // \includegraphics[height=0.32\textwidth]{ImageRegistration8TraceAngle} // \includegraphics[height=0.32\textwidth]{ImageRegistration8TraceTranslations} // \itkcaption[CenteredTransformInitializer output plots]{Plots of the metric, // rotation angle, center of rotation and translations during the // registration using CenteredTransformInitializer.} // \label{fig:ImageRegistration8Plots} // \end{figure} // // Figure \ref{fig:ImageRegistration8Plots} shows the plots of the main // output parameters of the registration process. The metric values at every // iteration. The Z component of the versor is plotted as an indication of // how the rotation progress. The X,Y translation components of the // registration are plotted at every iteration too. // // Shell and Gnuplot scripts for generating the diagrams in // Figure~\ref{fig:ImageRegistration8Plots} are available in the directory // // \code{InsightDocuments/SoftwareGuide/Art} // // You are strongly encouraged to run the example code, since only in this // way you can gain a first hand experience with the behavior of the // registration process. Once again, this is a simple reflection of the // philosophy that we put forward in this book: // // \emph{If you can not replicate it, then it does not exist!}. // // We have seen enough published papers with pretty pictures, presenting // results that in practice are impossible to replicate. That is vanity, not // science. // // Software Guide : EndLatex typedef itk::ResampleImageFilter< MovingImageType, FixedImageType > ResampleFilterType; TransformType::Pointer finalTransform = TransformType::New(); finalTransform->SetCenter( transform->GetCenter() ); finalTransform->SetParameters( finalParameters ); finalTransform->SetFixedParameters( transform->GetFixedParameters() ); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetTransform( finalTransform ); resampler->SetInput( movingImageReader->GetOutput() ); FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput(); resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() ); resampler->SetOutputOrigin( fixedImage->GetOrigin() ); resampler->SetOutputSpacing( fixedImage->GetSpacing() ); resampler->SetOutputDirection( fixedImage->GetDirection() ); resampler->SetDefaultPixelValue( 100 ); typedef unsigned char OutputPixelType; typedef itk::Image< OutputPixelType, Dimension > OutputImageType; typedef itk::CastImageFilter< FixedImageType, OutputImageType > CastFilterType; typedef itk::ImageFileWriter< OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); CastFilterType::Pointer caster = CastFilterType::New(); writer->SetFileName( argv[3] ); caster->SetInput( resampler->GetOutput() ); writer->SetInput( caster->GetOutput() ); writer->Update(); typedef itk::SubtractImageFilter< FixedImageType, FixedImageType, FixedImageType > DifferenceFilterType; DifferenceFilterType::Pointer difference = DifferenceFilterType::New(); typedef itk::RescaleIntensityImageFilter< FixedImageType, OutputImageType > RescalerType; RescalerType::Pointer intensityRescaler = RescalerType::New(); intensityRescaler->SetInput( difference->GetOutput() ); intensityRescaler->SetOutputMinimum( 0 ); intensityRescaler->SetOutputMaximum( 255 ); difference->SetInput1( fixedImageReader->GetOutput() ); difference->SetInput2( resampler->GetOutput() ); resampler->SetDefaultPixelValue( 1 ); WriterType::Pointer writer2 = WriterType::New(); writer2->SetInput( intensityRescaler->GetOutput() ); // Compute the difference image between the // fixed and resampled moving image. if( argc > 5 ) { writer2->SetFileName( argv[5] ); writer2->Update(); } typedef itk::IdentityTransform< double, Dimension > IdentityTransformType; IdentityTransformType::Pointer identity = IdentityTransformType::New(); // Compute the difference image between the // fixed and moving image before registration. if( argc > 4 ) { resampler->SetTransform( identity ); writer2->SetFileName( argv[4] ); writer2->Update(); } // // Here we extract slices from the input volume, and the difference volumes // produced before and after the registration. These slices are presented as // figures in the Software Guide. // // typedef itk::Image< OutputPixelType, 2 > OutputSliceType; typedef itk::ExtractImageFilter< OutputImageType, OutputSliceType > ExtractFilterType; ExtractFilterType::Pointer extractor = ExtractFilterType::New(); extractor->SetDirectionCollapseToSubmatrix(); extractor->InPlaceOn(); FixedImageType::RegionType inputRegion = fixedImage->GetLargestPossibleRegion(); FixedImageType::SizeType size = inputRegion.GetSize(); FixedImageType::IndexType start = inputRegion.GetIndex(); // Select one slice as output size[2] = 0; start[2] = 90; FixedImageType::RegionType desiredRegion; desiredRegion.SetSize( size ); desiredRegion.SetIndex( start ); extractor->SetExtractionRegion( desiredRegion ); typedef itk::ImageFileWriter< OutputSliceType > SliceWriterType; SliceWriterType::Pointer sliceWriter = SliceWriterType::New(); sliceWriter->SetInput( extractor->GetOutput() ); if( argc > 6 ) { extractor->SetInput( caster->GetOutput() ); resampler->SetTransform( identity ); sliceWriter->SetFileName( argv[6] ); sliceWriter->Update(); } if( argc > 7 ) { extractor->SetInput( intensityRescaler->GetOutput() ); resampler->SetTransform( identity ); sliceWriter->SetFileName( argv[7] ); sliceWriter->Update(); } if( argc > 8 ) { resampler->SetTransform( finalTransform ); sliceWriter->SetFileName( argv[8] ); sliceWriter->Update(); } if( argc > 9 ) { extractor->SetInput( caster->GetOutput() ); resampler->SetTransform( finalTransform ); sliceWriter->SetFileName( argv[9] ); sliceWriter->Update(); } return EXIT_SUCCESS; }
void mitk::RegistrationWrapper::ApplyTransformationToImage(mitk::Image::Pointer img, const mitk::RegistrationWrapper::RidgidTransformType &transformation,double* offset, mitk::Image* resampleReference, bool binary) { typedef mitk::DiffusionImage<short> DiffusionImageType; if (dynamic_cast<DiffusionImageType*> (img.GetPointer()) == NULL) { ItkImageType::Pointer itkImage = ItkImageType::New(); MITK_ERROR << "imgCopy 0 " << "/" << img->GetReferenceCount(); MITK_ERROR << "pixel type " << img->GetPixelType().GetComponentTypeAsString(); CastToItkImage(img, itkImage); typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType parameters(RigidTransformType::ParametersDimension); for (int i = 0; i<6;++i) parameters[i] = transformation[i]; rtransform->SetParameters( parameters ); mitk::Point3D origin = itkImage->GetOrigin(); origin[0]-=offset[0]; origin[1]-=offset[1]; origin[2]-=offset[2]; mitk::Point3D newOrigin = rtransform->GetInverseTransform()->TransformPoint(origin); itk::Matrix<double,3,3> dir = itkImage->GetDirection(); itk::Matrix<double,3,3> transM ( vnl_inverse(rtransform->GetMatrix().GetVnlMatrix())); itk::Matrix<double,3,3> newDirection = transM * dir; itkImage->SetOrigin(newOrigin); itkImage->SetDirection(newDirection); // Perform Resampling if reference image is provided if (resampleReference != NULL) { typedef itk::ResampleImageFilter<ItkImageType, ItkImageType> ResampleFilterType; ItkImageType::Pointer itkReference = ItkImageType::New(); CastToItkImage(resampleReference,itkReference); typedef itk::WindowedSincInterpolateImageFunction< ItkImageType, 3> WindowedSincInterpolatorType; WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New(); typedef itk::NearestNeighborInterpolateImageFunction< ItkImageType, double > NearestNeighborInterpolatorType; NearestNeighborInterpolatorType::Pointer nn_interpolator = NearestNeighborInterpolatorType::New(); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkImage); resampler->SetReferenceImage( itkReference ); resampler->UseReferenceImageOn(); if (binary) resampler->SetInterpolator(nn_interpolator); else resampler->SetInterpolator(sinc_interpolator); resampler->Update(); GrabItkImageMemory(resampler->GetOutput(), img); } else { // !! CastToItk behaves very differently depending on the original data type // if the target type is the same as the original, only a pointer to the data is set // and an additional GrabItkImageMemory will cause a segfault when the image is destroyed // GrabItkImageMemory - is not necessary in this case since we worked on the original data // See Bug 17538. if (img->GetPixelType().GetComponentTypeAsString() != "double") img = GrabItkImageMemory(itkImage); } } else { DiffusionImageType::Pointer diffImages = dynamic_cast<DiffusionImageType*>(img.GetPointer()); typedef itk::Euler3DTransform< double > RigidTransformType; RigidTransformType::Pointer rtransform = RigidTransformType::New(); RigidTransformType::ParametersType parameters(RigidTransformType::ParametersDimension); for (int i = 0; i<6;++i) { parameters[i] = transformation[i]; } rtransform->SetParameters( parameters ); mitk::Point3D b0origin = diffImages->GetVectorImage()->GetOrigin(); b0origin[0]-=offset[0]; b0origin[1]-=offset[1]; b0origin[2]-=offset[2]; mitk::Point3D newOrigin = rtransform->GetInverseTransform()->TransformPoint(b0origin); itk::Matrix<double,3,3> dir = diffImages->GetVectorImage()->GetDirection(); itk::Matrix<double,3,3> transM ( vnl_inverse(rtransform->GetMatrix().GetVnlMatrix())); itk::Matrix<double,3,3> newDirection = transM * dir; diffImages->GetVectorImage()->SetOrigin(newOrigin); diffImages->GetVectorImage()->SetDirection(newDirection); diffImages->Modified(); mitk::DiffusionImageCorrectionFilter<short>::Pointer correctionFilter = mitk::DiffusionImageCorrectionFilter<short>::New(); // For Diff. Images: Need to rotate the gradients (works in-place) correctionFilter->SetImage(diffImages); correctionFilter->CorrectDirections(transM.GetVnlMatrix()); img = diffImages; } }
RealImage::Pointer bsplineRegistration(RealImage::Pointer srcImg, RealImage::Pointer dstImg) { const unsigned int SpaceDimension = ImageDimension; const unsigned int SplineOrder = 3; typedef double CoordinateRepType; typedef itk::BSplineTransform<CoordinateRepType, SpaceDimension, SplineOrder> TransformType; typedef itk::LBFGSOptimizer OptimizerType; typedef itk::MeanSquaresImageToImageMetric<ImageType, ImageType> MetricType; typedef itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType; typedef itk::ImageRegistrationMethod<ImageType, ImageType> RegistrationType; MetricType::Pointer metric = MetricType::New(); OptimizerType::Pointer optimizer = OptimizerType::New(); InterpolatorType::Pointer interpolator = InterpolatorType::New(); RegistrationType::Pointer registration = RegistrationType::New(); // The old registration framework has problems with multi-threading // For now, we set the number of threads to 1 // registration->SetNumberOfThreads(1); registration->SetMetric( metric ); registration->SetOptimizer( optimizer ); registration->SetInterpolator( interpolator ); TransformType::Pointer transform = TransformType::New(); registration->SetTransform( transform ); // Setup the registration registration->SetFixedImage( dstImg ); registration->SetMovingImage( srcImg); ImageType::RegionType fixedRegion = srcImg->GetBufferedRegion(); registration->SetFixedImageRegion( fixedRegion ); // Here we define the parameters of the BSplineDeformableTransform grid. We // arbitrarily decide to use a grid with $5 \times 5$ nodes within the image. // The reader should note that the BSpline computation requires a // finite support region ( 1 grid node at the lower borders and 2 // grid nodes at upper borders). Therefore in this example, we set // the grid size to be $8 \times 8$ and place the grid origin such that // grid node (1,1) coincides with the first pixel in the fixed image. TransformType::PhysicalDimensionsType fixedPhysicalDimensions; TransformType::MeshSizeType meshSize; for (unsigned int i=0; i < ImageDimension; i++) { fixedPhysicalDimensions[i] = dstImg->GetSpacing()[i] * static_cast<double>(dstImg->GetLargestPossibleRegion().GetSize()[i] - 1 ); meshSize[i] = dstImg->GetLargestPossibleRegion().GetSize()[i] / 8 - SplineOrder; } // unsigned int numberOfGridNodesInOneDimension = 15; // meshSize.Fill( numberOfGridNodesInOneDimension - SplineOrder ); transform->SetTransformDomainOrigin( dstImg->GetOrigin() ); transform->SetTransformDomainPhysicalDimensions( fixedPhysicalDimensions ); transform->SetTransformDomainMeshSize( meshSize ); transform->SetTransformDomainDirection( dstImg->GetDirection() ); typedef TransformType::ParametersType ParametersType; const unsigned int numberOfParameters = transform->GetNumberOfParameters(); ParametersType parameters( 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; // Next we set the parameters of the LBFGS Optimizer. optimizer->SetGradientConvergenceTolerance(0.1); optimizer->SetLineSearchAccuracy(0.09); optimizer->SetDefaultStepLength(.1); optimizer->TraceOn(); optimizer->SetMaximumNumberOfFunctionEvaluations(1000); std::cout << std::endl << "Starting Registration" << std::endl; try { registration->Update(); std::cout << "Optimizer stop condition = " << registration->GetOptimizer()->GetStopConditionDescription() << std::endl; } catch (itk::ExceptionObject & err) { std::cerr << "ExceptionObject caught !" << std::endl; std::cerr << err << std::endl; return RealImage::Pointer(); } OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters(); std::cout << "Last Transform Parameters" << std::endl; std::cout << finalParameters << std::endl; transform->SetParameters( finalParameters ); typedef itk::ResampleImageFilter<ImageType, ImageType> ResampleFilterType; ResampleFilterType::Pointer resample = ResampleFilterType::New(); resample->SetTransform( transform ); resample->SetInput( srcImg ); resample->SetSize( dstImg->GetLargestPossibleRegion().GetSize() ); resample->SetOutputOrigin( dstImg->GetOrigin() ); resample->SetOutputSpacing( dstImg->GetSpacing() ); resample->SetOutputDirection( dstImg->GetDirection() ); resample->SetDefaultPixelValue( 100 ); resample->Update(); return resample->GetOutput(); }