#include #include #include #include #include #include "rpiTRex.hxx" /** * TRex (Toy Registration EXample) executable. * This method is a fully ITK registration method implemented into the RPI framework. * The method is simple and gives a clear example of how a registration method of RPI should be implemented. * @author Vincent Garcia * @date 2011/03/15 */ /** * Structure containing the parameters. */ struct Param{ std::string fixedImagePath; std::string movingImagePath; std::string outputImagePath; std::string outputTransformPath; unsigned int iterations; }; /** * Parses the command line arguments and deduces the corresponding Param structure. * @param argc number of arguments * @param argv array containing the arguments * @param param structure of parameters */ void parseParameters(int argc, char** argv, struct Param & param) { // Program description std::string description = "\b\b\bDESCRIPTION\n"; description += "TRex registration method: Toy Registration EXample. The transformation "; description += "computed is a rigid transformation."; description += "\nAuthor : Vincent Garcia"; try { // Define the command line parser TCLAP::CmdLine cmd( description, ' ', "1.0", true); TCLAP::ValueArg arg_iterations( "a", "iterations", "Number of iterations (default 5000)", false, 5000, "uint", cmd ); TCLAP::ValueArg arg_outputImage( "i", "output-image", "Path to the output image (default output_image.nii).", false, "output_image.nii", "string", cmd ); TCLAP::ValueArg arg_outputTransform( "t", "output-transform", "Path of the output transformation (default output_transform.txt).", false, "output_transform.txt", "string", cmd ); TCLAP::ValueArg arg_movingImage( "m", "moving-image", "Path to the moving image.", true, "", "string", cmd ); TCLAP::ValueArg arg_fixedImage( "f", "fixed-image", "Path to the fixed image.", true, "", "string", cmd ); // Parse the command line cmd.parse( argc, argv ); // Set the parameters param.fixedImagePath = arg_fixedImage.getValue(); param.movingImagePath = arg_movingImage.getValue(); param.outputTransformPath = arg_outputTransform.getValue(); param.outputImagePath = arg_outputImage.getValue(); param.iterations = arg_iterations.getValue(); } catch (TCLAP::ArgException &e) { std::cerr << "Error: " << e.error() << " for argument " << e.argId() << std::endl; throw std::runtime_error("Unable to parse the command line arguments."); } } /** * Prints parameters. * @param fixedImagePath path to the fixed image * @param movingImagePath path to the moving image * @param outputImagePath path to the output file containing the resampled image * @param outputTransformPath path to the output file containing the transformation * @param initialTransformPath path to the initial transformation * @param registration registration object */ template< class TFixedImage, class TMovingImage, class TTransformScalarType > void PrintParameters( std::string fixedImagePath, std::string movingImagePath, std::string outputImagePath, std::string outputTransformPath, rpi::TRex * registration ) { // Print I/O parameters std::cout << std::endl; std::cout << "I/O PARAMETERS" << std::endl; std::cout << " Fixed image path : " << fixedImagePath << std::endl; std::cout << " Moving image path : " << movingImagePath << std::endl; std::cout << " Output image path : " << outputImagePath << std::endl; std::cout << " Output transformation path : " << outputTransformPath << std::endl; std::cout << std::endl; // Print method parameters std::cout << "METHOD PARAMETER" << std::endl; std::cout << " Number of iterations : " << registration->GetNumberOfIterations() << std::endl << std::endl; } /** * Starts the main program. * @param param parameters needed for the image registration process * @return EXIT_SUCCESS if the registration succeded, EXIT_FAILURE otherwise */ template< class TFixedImage, class TMovingImage > int StartMainProgram(struct Param param) { // Type definition typedef double TransformScalarType; typedef rpi::TRex< TFixedImage, TMovingImage, TransformScalarType > RegistrationMethod; // Create registration object RegistrationMethod * registration = new RegistrationMethod(); try { // Read input images typename TFixedImage::Pointer fixedImage = rpi::readImage< TFixedImage >( param.fixedImagePath ); typename TMovingImage::Pointer movingImage = rpi::readImage< TMovingImage >( param.movingImagePath ); // Set parameters registration->SetFixedImage( fixedImage ); registration->SetMovingImage( movingImage ); registration->SetNumberOfIterations( param.iterations ); // Print parameters PrintParameters( param.fixedImagePath, param.movingImagePath, param.outputImagePath, param.outputTransformPath, registration ); // Display std::cout << "STARTING MAIN PROGRAM" << std::endl; // Start registration process std::cout << " Registering images : " << std::flush; registration->StartRegistration(); std::cout << "OK" << std::endl; // Write output transformation std::cout << " Writing transformation : " << std::flush; rpi::writeLinearTransformation( registration->GetTransformation(), param.outputTransformPath ); std::cout << "OK" << std::endl; // Write output image std::cout << " Writing image : " << std::flush; rpi::resampleAndWriteImage( fixedImage, movingImage, registration->GetTransformation(), param.outputImagePath ); std::cout << "OK" << std::endl << std::endl; } catch( std::exception& e ) { std::cerr << e.what() << std::endl; delete registration; return EXIT_FAILURE; }; // Free memory and exit delete registration; return EXIT_SUCCESS; } /** * Main function. */ int main(int argc, char** argv) { // Parse parameters struct Param param; parseParameters( argc, argv, param); // Read image information itk::ImageIOBase::Pointer fixed_imageIO; itk::ImageIOBase::Pointer moving_imageIO; try { fixed_imageIO = rpi::readImageInformation( param.fixedImagePath ); moving_imageIO = rpi::readImageInformation( param.movingImagePath ); } catch( std::exception& e ) { std::cerr << "Error: " << e.what() << std::endl; return EXIT_FAILURE; } // Only 3D images are supported yet if ( fixed_imageIO->GetNumberOfDimensions()!=3 && moving_imageIO->GetNumberOfDimensions()!=3 ) { std::cerr << "Error: Only images of dimension 3 are supported yet." << std::endl; return EXIT_FAILURE; } // Only scalar images are supported yet if ( fixed_imageIO->GetPixelType() != itk::ImageIOBase::SCALAR || moving_imageIO->GetPixelType() != itk::ImageIOBase::SCALAR ) { std::cerr << "Error: Only scalar images are supported yet." << std::endl; return EXIT_FAILURE; } // Component type typedef itk::ImageIOBase::IOComponentType ComponentType; ComponentType fixed_type = fixed_imageIO->GetComponentType(); ComponentType moving_type = moving_imageIO->GetComponentType(); std::string fixed_type_str = fixed_imageIO->GetComponentTypeAsString( fixed_type ); std::string moving_type_str = moving_imageIO->GetComponentTypeAsString( moving_type ); // Switch on component type switch ( fixed_type ) { case itk::ImageIOBase::UCHAR : switch ( moving_type ) { case itk::ImageIOBase::UCHAR : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::USHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::SHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::FLOAT : return StartMainProgram< itk::Image , itk::Image >(param); break; default : std::cerr << "Error: Pixel type " << moving_type_str << " is not supported yet." << std::endl; return EXIT_FAILURE; } break; case itk::ImageIOBase::USHORT : switch ( moving_type ) { case itk::ImageIOBase::UCHAR : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::USHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::SHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::FLOAT : return StartMainProgram< itk::Image , itk::Image >(param); break; default : std::cerr << "Error: Pixel type " << moving_type_str << " is not supported yet." << std::endl; return EXIT_FAILURE; } break; case itk::ImageIOBase::SHORT : switch ( moving_type ) { case itk::ImageIOBase::UCHAR : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::USHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::SHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::FLOAT : return StartMainProgram< itk::Image , itk::Image >(param); break; default : std::cerr << "Error: Pixel type " << moving_type_str << " is not supported yet." << std::endl; return EXIT_FAILURE; } break; case itk::ImageIOBase::FLOAT : switch ( moving_type ) { case itk::ImageIOBase::UCHAR : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::USHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::SHORT : return StartMainProgram< itk::Image , itk::Image >(param); break; case itk::ImageIOBase::FLOAT : return StartMainProgram< itk::Image , itk::Image >(param); break; default : std::cerr << "Error: Pixel type " << moving_type_str << " is not supported yet." << std::endl; return EXIT_FAILURE; } break; default : std::cerr << "Error: Pixel type " << fixed_type_str << " is not supported yet." << std::endl; return EXIT_FAILURE; } // End of the program return EXIT_FAILURE; }