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(); }
// 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()); }
typename TImage::Pointer modelBasedImageToImageRegistration(std::string referenceFilename, std::string targetFilename, typename TStatisticalModelType::Pointer model, std::string outputDfFilename, unsigned numberOfIterations){ typedef itk::ImageFileReader<TImage> ImageReaderType; typedef itk::InterpolatingStatisticalDeformationModelTransform<TRepresenter, double, VImageDimension> TransformType; typedef itk::LBFGSOptimizer OptimizerType; typedef itk::ImageRegistrationMethod<TImage, TImage> RegistrationFilterType; typedef itk::WarpImageFilter< TImage, TImage, TVectorImage > WarperType; typedef itk::LinearInterpolateImageFunction< TImage, double > InterpolatorType; typename ImageReaderType::Pointer referenceReader = ImageReaderType::New(); referenceReader->SetFileName(referenceFilename.c_str()); referenceReader->Update(); typename TImage::Pointer referenceImage = referenceReader->GetOutput(); referenceImage->Update(); typename ImageReaderType::Pointer targetReader = ImageReaderType::New(); targetReader->SetFileName(targetFilename.c_str()); targetReader->Update(); typename TImage::Pointer targetImage = targetReader->GetOutput(); targetImage->Update(); // do the fitting typename TransformType::Pointer transform = TransformType::New(); transform->SetStatisticalModel(model); transform->SetIdentity(); // Setting up the fitting OptimizerType::Pointer optimizer = OptimizerType::New(); optimizer->MinimizeOn(); optimizer->SetMaximumNumberOfFunctionEvaluations(numberOfIterations); typedef IterationStatusObserver ObserverType; ObserverType::Pointer observer = ObserverType::New(); optimizer->AddObserver( itk::IterationEvent(), observer ); typename TMetricType::Pointer metric = TMetricType::New(); typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); typename RegistrationFilterType::Pointer registration = RegistrationFilterType::New(); registration->SetInitialTransformParameters(transform->GetParameters()); registration->SetMetric(metric); registration->SetOptimizer( optimizer ); registration->SetTransform( transform ); registration->SetInterpolator( interpolator ); registration->SetFixedImage( targetImage ); registration->SetFixedImageRegion(targetImage->GetBufferedRegion() ); registration->SetMovingImage( referenceImage ); try { std::cout << "Performing registration... " << std::flush; registration->Update(); std::cout << "[done]" << std::endl; } catch ( itk::ExceptionObject& o ) { std::cout << "caught exception " << o << std::endl; } typename TVectorImage::Pointer df = model->DrawSample(transform->GetCoefficients()); // write deformation field if(outputDfFilename.size()>0){ typename itk::ImageFileWriter<TVectorImage>::Pointer df_writer = itk::ImageFileWriter<TVectorImage>::New(); df_writer->SetFileName(outputDfFilename); df_writer->SetInput(df); df_writer->Update(); } // warp reference std::cout << "Warping reference... " << std::flush; typename WarperType::Pointer warper = WarperType::New(); warper->SetInput(referenceImage ); warper->SetInterpolator( interpolator ); warper->SetOutputSpacing( targetImage->GetSpacing() ); warper->SetOutputOrigin( targetImage->GetOrigin() ); warper->SetOutputDirection( targetImage->GetDirection() ); warper->SetDisplacementField( df ); warper->Update(); std::cout << "[done]" << std::endl; return warper->GetOutput(); }