1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #ifndef clitkAffineTransformGenericFilter_txx
19 #define clitkAffineTransformGenericFilter_txx
24 #include <itkCenteredEuler3DTransform.h>
25 #include "clitkElastix.h"
30 //-----------------------------------------------------------
32 //-----------------------------------------------------------
33 template<class args_info_type>
34 AffineTransformGenericFilter<args_info_type>::AffineTransformGenericFilter()
39 //-------------------------------------------------------------------
42 //-----------------------------------------------------------
44 //-----------------------------------------------------------
45 template<class args_info_type>
46 void AffineTransformGenericFilter<args_info_type>::Update()
48 // Read the Dimension and PixelType
49 int Dimension, Components;
50 std::string PixelType;
51 ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
54 if(Dimension==2) UpdateWithDim<2>(PixelType, Components);
56 if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
57 else if (Dimension==4)UpdateWithDim<4>(PixelType, Components);
59 std::cout<<"Error, Only for 2, 3 or 4 Dimensions!!!"<<std::endl ;
63 //-------------------------------------------------------------------
66 //-------------------------------------------------------------------
67 // Update with the number of dimensions
68 //-------------------------------------------------------------------
69 template<class args_info_type>
70 template<unsigned int Dimension>
72 AffineTransformGenericFilter<args_info_type>::UpdateWithDim(std::string PixelType, int Components)
74 if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<<Components<<" component(s) of "<< PixelType<<"..."<<std::endl;
77 if(PixelType == "short") {
78 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
79 UpdateWithDimAndPixelType<Dimension, signed short>();
81 else if(PixelType == "unsigned_short"){
82 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
83 UpdateWithDimAndPixelType<Dimension, unsigned short>();
86 else if (PixelType == "unsigned_char") {
87 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
88 UpdateWithDimAndPixelType<Dimension, unsigned char>();
91 // else if (PixelType == "char"){
92 // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
93 // UpdateWithDimAndPixelType<Dimension, signed char>();
96 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
97 UpdateWithDimAndPixelType<Dimension, float>();
101 else if (Components==3) {
102 if (m_Verbose) std::cout << "Launching transform in "<< Dimension <<"D and 3D float (DVF)" << std::endl;
103 UpdateWithDimAndVectorType<Dimension, itk::Vector<float, Dimension> >();
106 else std::cerr<<"Number of components is "<<Components<<", not supported!"<<std::endl;
109 //-------------------------------------------------------------------
112 //-------------------------------------------------------------------
113 // Update with the number of dimensions and the pixeltype
114 //-------------------------------------------------------------------
115 template<class args_info_type>
116 template <unsigned int Dimension, class PixelType>
118 AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndPixelType()
122 typedef itk::Image<PixelType, Dimension> InputImageType;
123 typedef itk::Image<PixelType, Dimension> OutputImageType;
126 typedef itk::ImageFileReader<InputImageType> InputReaderType;
127 typename InputReaderType::Pointer reader = InputReaderType::New();
128 reader->SetFileName( m_InputFileName);
130 typename InputImageType::Pointer input= reader->GetOutput();
133 typedef itk::ResampleImageFilter< InputImageType,OutputImageType > ResampleFilterType;
134 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
137 typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
138 if (m_ArgsInfo.rotate_given || m_ArgsInfo.translate_given)
140 if (m_ArgsInfo.matrix_given)
142 std::cerr << "You must use either rotate/translate or matrix options" << std::endl;
145 itk::Array<double> transformParameters(2 * Dimension);
146 transformParameters.Fill(0.0);
147 if (m_ArgsInfo.rotate_given)
150 transformParameters[0] = m_ArgsInfo.rotate_arg[0];
152 for (unsigned int i = 0; i < 3; i++)
153 transformParameters[i] = m_ArgsInfo.rotate_arg[i];
155 if (m_ArgsInfo.translate_given)
160 for (unsigned int i = 0; i < Dimension && i < 3; i++)
161 transformParameters[pos++] = m_ArgsInfo.translate_arg[i];
165 matrix.SetIdentity();
166 itk::Matrix<double, 4, 4> tmp = GetForwardAffineMatrix3D(transformParameters);
167 for (unsigned int i = 0; i < 3; ++i)
168 for (unsigned int j = 0; j < 3; ++j)
169 matrix[i][j] = tmp[i][j];
170 for (unsigned int i = 0; i < 3; ++i)
171 matrix[i][4] = tmp[i][3];
174 matrix = GetForwardAffineMatrix<Dimension>(transformParameters);
178 if (m_ArgsInfo.matrix_given)
180 matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
181 if (m_Verbose) std::cout << "Reading the matrix..." << std::endl;
184 if (m_ArgsInfo.elastix_given) {
185 std::string filename(m_ArgsInfo.elastix_arg);
186 matrix = createMatrixFromElastixFile<Dimension>(filename, m_Verbose);
189 matrix.SetIdentity();
193 std::cout << "Using the following matrix:" << std::endl
194 << matrix << std::endl;
195 typename itk::Matrix<double, Dimension, Dimension> rotationMatrix = clitk::GetRotationalPartMatrix(matrix);
196 typename itk::Vector<double, Dimension> translationPart = clitk::GetTranslationPartMatrix(matrix);
199 typedef itk::AffineTransform<double, Dimension> AffineTransformType;
200 typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
201 affineTransform->SetMatrix(rotationMatrix);
202 affineTransform->SetTranslation(translationPart);
205 typedef clitk::GenericInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
206 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
207 genericInterpolator->SetArgsInfo(m_ArgsInfo);
210 if (m_ArgsInfo.like_given) {
211 typename InputReaderType::Pointer likeReader=InputReaderType::New();
212 likeReader->SetFileName(m_ArgsInfo.like_arg);
213 likeReader->Update();
214 resampler->SetOutputParametersFromImage(likeReader->GetOutput());
215 resampler->SetOutputDirection(likeReader->GetOutput()->GetDirection());
216 } else if(m_ArgsInfo.transform_grid_flag) {
217 typename itk::Matrix<double, Dimension+1, Dimension+1> invMatrix( matrix.GetInverse() );
218 typename itk::Matrix<double, Dimension, Dimension> invRotMatrix( clitk::GetRotationalPartMatrix(invMatrix) );
219 typename itk::Vector<double,Dimension> invTrans = clitk::GetTranslationPartMatrix(invMatrix);
222 if (m_ArgsInfo.spacing_given)
223 std::cout << "Warning --spacing ignored (because --transform_grid_flag)" << std::endl;
224 if (m_ArgsInfo.origin_given)
225 std::cout << "Warning --origin ignored (because --transform_grid_flag)" << std::endl;
227 // Spacing is influenced by affine transform matrix and input direction
228 typename InputImageType::SpacingType outputSpacing;
229 outputSpacing = invRotMatrix *
230 input->GetDirection() *
233 // Origin is influenced by translation but not by input direction
234 typename InputImageType::PointType outputOrigin;
235 outputOrigin = invRotMatrix *
239 // Size is influenced by affine transform matrix and input direction
240 // Size is converted to double, transformed and converted back to size type.
241 vnl_vector<double> vnlOutputSize(Dimension);
242 for(unsigned int i=0; i< Dimension; i++) {
243 vnlOutputSize[i] = input->GetLargestPossibleRegion().GetSize()[i];
245 vnlOutputSize = invRotMatrix *
246 input->GetDirection().GetVnlMatrix() *
248 typename OutputImageType::SizeType outputSize;
249 for(unsigned int i=0; i< Dimension; i++) {
250 // If the size is negative, we have a flip and we must modify
251 // the origin and the spacing accordingly.
252 if(vnlOutputSize[i]<0.) {
253 vnlOutputSize[i] *= -1.;
254 outputOrigin[i] = outputOrigin[i] + outputSpacing[i] * (vnlOutputSize[i]-1);
255 outputSpacing[i] *= -1.;
257 outputSize[i] = lrint(vnlOutputSize[i]);
259 resampler->SetSize( outputSize );
260 resampler->SetOutputSpacing( outputSpacing );
261 resampler->SetOutputOrigin( outputOrigin );
264 typename OutputImageType::SizeType outputSize;
265 if (m_ArgsInfo.size_given) {
266 for(unsigned int i=0; i< Dimension; i++)
267 outputSize[i]=m_ArgsInfo.size_arg[i];
268 } else outputSize=input->GetLargestPossibleRegion().GetSize();
271 typename OutputImageType::SpacingType outputSpacing;
272 if (m_ArgsInfo.spacing_given) {
273 for(unsigned int i=0; i< Dimension; i++)
274 outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
275 } else outputSpacing=input->GetSpacing();
278 typename OutputImageType::PointType outputOrigin;
279 if (m_ArgsInfo.origin_given) {
280 for(unsigned int i=0; i< Dimension; i++)
281 outputOrigin[i]=m_ArgsInfo.origin_arg[i];
282 } else outputOrigin=input->GetOrigin();
285 typename OutputImageType::DirectionType outputDirection;
286 if (m_ArgsInfo.direction_given) {
287 for(unsigned int j=0; j< Dimension; j++)
288 for(unsigned int i=0; i< Dimension; i++)
289 outputDirection[j][i]=m_ArgsInfo.direction_arg[i+Dimension*j];
290 } else outputDirection=input->GetDirection();
293 resampler->SetSize( outputSize );
294 resampler->SetOutputSpacing( outputSpacing );
295 resampler->SetOutputOrigin( outputOrigin );
296 resampler->SetOutputDirection( outputDirection );
300 if (m_ArgsInfo.spacinglike_given) {
301 typename InputReaderType::Pointer likeReader=InputReaderType::New();
302 likeReader->SetFileName(m_ArgsInfo.spacinglike_arg);
303 likeReader->Update();
305 // set the support like the image
306 if (m_ArgsInfo.like_given) {
307 typename OutputImageType::SizeType outputSize;
308 outputSize[0] = ceil(resampler->GetSize()[0]*resampler->GetOutputSpacing()[0]
309 /likeReader->GetOutput()->GetSpacing()[0]);
310 outputSize[1] = ceil(resampler->GetSize()[1]*resampler->GetOutputSpacing()[1]
311 /likeReader->GetOutput()->GetSpacing()[1]);
312 outputSize[2] = ceil(resampler->GetSize()[2]*resampler->GetOutputSpacing()[2]
313 /likeReader->GetOutput()->GetSpacing()[2]);
314 if (m_ArgsInfo.verbose_flag) {
315 std::cout << "Compute the number of pixels such as the support is like " << m_ArgsInfo.like_arg << std::endl;
317 resampler->SetSize( outputSize );
320 resampler->SetOutputSpacing( likeReader->GetOutput()->GetSpacing() );
323 if (m_ArgsInfo.verbose_flag) {
324 std::cout << "Setting the output size to " << resampler->GetSize() << "..." << std::endl;
325 std::cout << "Setting the output spacing to " << resampler->GetOutputSpacing() << "..." << std::endl;
326 std::cout << "Setting the output origin to " << resampler->GetOutputOrigin() << "..." << std::endl;
327 std::cout << "Setting the output direction to " << resampler->GetOutputDirection() << "..." << std::endl;
330 resampler->SetInput( input );
331 resampler->SetTransform( affineTransform );
332 resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
333 resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
337 } catch(itk::ExceptionObject) {
338 std::cerr<<"Error resampling the image"<<std::endl;
341 typename OutputImageType::Pointer output = resampler->GetOutput();
344 typedef itk::ImageFileWriter<OutputImageType> WriterType;
345 typename WriterType::Pointer writer = WriterType::New();
346 writer->SetFileName(m_ArgsInfo.output_arg);
347 writer->SetInput(output);
351 //-------------------------------------------------------------------
354 //-------------------------------------------------------------------
355 // Update with the number of dimensions and the pixeltype (components)
356 //-------------------------------------------------------------------
357 template<class args_info_type>
358 template<unsigned int Dimension, class PixelType>
359 void AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndVectorType()
362 typedef itk::Image<PixelType, Dimension> InputImageType;
363 typedef itk::Image<PixelType, Dimension> OutputImageType;
366 typedef itk::ImageFileReader<InputImageType> InputReaderType;
367 typename InputReaderType::Pointer reader = InputReaderType::New();
368 reader->SetFileName( m_InputFileName);
370 typename InputImageType::Pointer input= reader->GetOutput();
373 typedef itk::VectorResampleImageFilter< InputImageType,OutputImageType, double > ResampleFilterType;
374 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
377 typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
378 if (m_ArgsInfo.rotate_given || m_ArgsInfo.translate_given)
380 if (m_ArgsInfo.matrix_given)
382 std::cerr << "You must use either rotate/translate or matrix options" << std::endl;
385 itk::Array<double> transformParameters(2 * Dimension);
386 transformParameters.Fill(0.0);
387 if (m_ArgsInfo.rotate_given)
390 transformParameters[0] = m_ArgsInfo.rotate_arg[0];
392 for (unsigned int i = 0; i < 3; i++)
393 transformParameters[i] = m_ArgsInfo.rotate_arg[i];
395 if (m_ArgsInfo.translate_given)
400 for (unsigned int i = 0; i < Dimension && i < 3; i++)
401 transformParameters[pos++] = m_ArgsInfo.translate_arg[i];
405 matrix.SetIdentity();
406 itk::Matrix<double, 4, 4> tmp = GetForwardAffineMatrix3D(transformParameters);
407 for (unsigned int i = 0; i < 3; ++i)
408 for (unsigned int j = 0; j < 3; ++j)
409 matrix[i][j] = tmp[i][j];
410 for (unsigned int i = 0; i < 3; ++i)
411 matrix[i][4] = tmp[i][3];
414 matrix = GetForwardAffineMatrix<Dimension>(transformParameters);
418 if (m_ArgsInfo.matrix_given)
420 matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
421 if (m_Verbose) std::cout << "Reading the matrix..." << std::endl;
424 matrix.SetIdentity();
427 std::cout << "Using the following matrix:" << std::endl
428 << matrix << std::endl;
429 typename itk::Matrix<double, Dimension, Dimension> rotationMatrix = clitk::GetRotationalPartMatrix(matrix);
430 typename itk::Vector<double, Dimension> translationPart = clitk::GetTranslationPartMatrix(matrix);
433 typedef itk::AffineTransform<double, Dimension> AffineTransformType;
434 typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
435 affineTransform->SetMatrix(rotationMatrix);
436 affineTransform->SetTranslation(translationPart);
439 typedef clitk::GenericVectorInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
440 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
441 genericInterpolator->SetArgsInfo(m_ArgsInfo);
444 if (m_ArgsInfo.like_given) {
445 typename InputReaderType::Pointer likeReader=InputReaderType::New();
446 likeReader->SetFileName(m_ArgsInfo.like_arg);
447 likeReader->Update();
448 resampler->SetSize( likeReader->GetOutput()->GetLargestPossibleRegion().GetSize() );
449 resampler->SetOutputSpacing( likeReader->GetOutput()->GetSpacing() );
450 resampler->SetOutputOrigin( likeReader->GetOutput()->GetOrigin() );
451 resampler->SetOutputDirection( likeReader->GetOutput()->GetDirection() );
454 typename OutputImageType::SizeType outputSize;
455 if (m_ArgsInfo.size_given) {
456 for(unsigned int i=0; i< Dimension; i++)
457 outputSize[i]=m_ArgsInfo.size_arg[i];
458 } else outputSize=input->GetLargestPossibleRegion().GetSize();
459 std::cout<<"Setting the size to "<<outputSize<<"..."<<std::endl;
462 typename OutputImageType::SpacingType outputSpacing;
463 if (m_ArgsInfo.spacing_given) {
464 for(unsigned int i=0; i< Dimension; i++)
465 outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
466 } else outputSpacing=input->GetSpacing();
467 std::cout<<"Setting the spacing to "<<outputSpacing<<"..."<<std::endl;
470 typename OutputImageType::PointType outputOrigin;
471 if (m_ArgsInfo.origin_given) {
472 for(unsigned int i=0; i< Dimension; i++)
473 outputOrigin[i]=m_ArgsInfo.origin_arg[i];
474 } else outputOrigin=input->GetOrigin();
475 std::cout<<"Setting the origin to "<<outputOrigin<<"..."<<std::endl;
478 typename OutputImageType::DirectionType outputDirection;
479 if (m_ArgsInfo.direction_given) {
480 for(unsigned int j=0; j< Dimension; j++)
481 for(unsigned int i=0; i< Dimension; i++)
482 outputDirection[j][i]=m_ArgsInfo.direction_arg[i+Dimension*j];
483 } else outputDirection=input->GetDirection();
484 std::cout<<"Setting the direction to "<<outputDirection<<"..."<<std::endl;
487 resampler->SetSize( outputSize );
488 resampler->SetOutputSpacing( outputSpacing );
489 resampler->SetOutputOrigin( outputOrigin );
490 resampler->SetOutputDirection( outputDirection );
494 resampler->SetInput( input );
495 resampler->SetTransform( affineTransform );
496 resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
497 resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
501 } catch(itk::ExceptionObject) {
502 std::cerr<<"Error resampling the image"<<std::endl;
505 typename OutputImageType::Pointer output = resampler->GetOutput();
508 typedef itk::ImageFileWriter<OutputImageType> WriterType;
509 typename WriterType::Pointer writer = WriterType::New();
510 writer->SetFileName(m_ArgsInfo.output_arg);
511 writer->SetInput(output);
515 //-------------------------------------------------------------------
519 #endif //#define clitkAffineTransformGenericFilter_txx