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
21 /* =================================================
22 * @file clitkAffineTransformGenericFilter.txx
28 ===================================================*/
34 //-----------------------------------------------------------
36 //-----------------------------------------------------------
37 template<class args_info_type>
38 AffineTransformGenericFilter<args_info_type>::AffineTransformGenericFilter()
45 //-----------------------------------------------------------
47 //-----------------------------------------------------------
48 template<class args_info_type>
49 void AffineTransformGenericFilter<args_info_type>::Update()
51 // Read the Dimension and PixelType
52 int Dimension, Components;
53 std::string PixelType;
54 ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
58 if(Dimension==2) UpdateWithDim<2>(PixelType, Components);
59 else if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
60 else if (Dimension==4)UpdateWithDim<4>(PixelType, Components);
62 std::cout<<"Error, Only for 2, 3 or 4 Dimensions!!!"<<std::endl ;
67 //-------------------------------------------------------------------
68 // Update with the number of dimensions
69 //-------------------------------------------------------------------
70 template<class args_info_type>
71 template<unsigned int Dimension>
73 AffineTransformGenericFilter<args_info_type>::UpdateWithDim(std::string PixelType, int Components)
75 if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<<Components<<" component(s) of "<< PixelType<<"..."<<std::endl;
78 if(PixelType == "short") {
79 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
80 UpdateWithDimAndPixelType<Dimension, signed short>();
82 // else if(PixelType == "unsigned_short"){
83 // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
84 // UpdateWithDimAndPixelType<Dimension, unsigned short>();
87 else if (PixelType == "unsigned_char") {
88 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
89 UpdateWithDimAndPixelType<Dimension, unsigned char>();
92 // else if (PixelType == "char"){
93 // if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
94 // UpdateWithDimAndPixelType<Dimension, signed char>();
97 if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
98 UpdateWithDimAndPixelType<Dimension, float>();
102 else if (Components==3) {
103 if (m_Verbose) std::cout << "Launching transform in "<< Dimension <<"D and 3D float (DVF)" << std::endl;
104 UpdateWithDimAndVectorType<Dimension, itk::Vector<float, Dimension> >();
107 else std::cerr<<"Number of components is "<<Components<<", not supported!"<<std::endl;
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::cout;
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 matrix.SetIdentity();
187 std::cout << "Using the following matrix:" << std::endl
188 << matrix << std::endl;
189 typename itk::Matrix<double, Dimension, Dimension> rotationMatrix = clitk::GetRotationalPartMatrix(matrix);
190 typename itk::Vector<double, Dimension> translationPart = clitk::GetTranslationPartMatrix(matrix);
193 typedef itk::AffineTransform<double, Dimension> AffineTransformType;
194 typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
195 affineTransform->SetMatrix(rotationMatrix);
196 affineTransform->SetTranslation(translationPart);
199 typedef clitk::GenericInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
200 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
201 genericInterpolator->SetArgsInfo(m_ArgsInfo);
204 if (m_ArgsInfo.like_given) {
205 typename InputReaderType::Pointer likeReader=InputReaderType::New();
206 likeReader->SetFileName(m_ArgsInfo.like_arg);
207 likeReader->Update();
208 resampler->SetOutputParametersFromImage(likeReader->GetOutput());
209 } else if(m_ArgsInfo.transform_grid_flag) {
210 typename itk::Matrix<double, Dimension+1, Dimension+1> invMatrix( matrix.GetInverse() );
211 typename itk::Matrix<double, Dimension, Dimension> invRotMatrix( clitk::GetRotationalPartMatrix(invMatrix) );
212 typename itk::Vector<double,Dimension> invTrans = clitk::GetTranslationPartMatrix(invMatrix);
215 if (m_ArgsInfo.spacing_given)
216 std::cout << "Warning --spacing ignored (because --transform_grid_flag)" << std::endl;
217 if (m_ArgsInfo.origin_given)
218 std::cout << "Warning --origin ignored (because --transform_grid_flag)" << std::endl;
220 // Spacing is influenced by affine transform matrix and input direction
221 typename InputImageType::SpacingType outputSpacing;
222 outputSpacing = invRotMatrix *
223 input->GetDirection() *
226 // Origin is influenced by translation but not by input direction
227 typename InputImageType::PointType outputOrigin;
228 outputOrigin = invRotMatrix *
232 // Size is influenced by affine transform matrix and input direction
233 // Size is converted to double, transformed and converted back to size type.
234 vnl_vector<double> vnlOutputSize(Dimension);
235 for(unsigned int i=0; i< Dimension; i++) {
236 vnlOutputSize[i] = input->GetLargestPossibleRegion().GetSize()[i];
238 vnlOutputSize = invRotMatrix *
239 input->GetDirection().GetVnlMatrix() *
241 typename OutputImageType::SizeType outputSize;
242 for(unsigned int i=0; i< Dimension; i++) {
243 // If the size is negative, we have a flip and we must modify
244 // the origin and the spacing accordingly.
245 if(vnlOutputSize[i]<0.) {
246 vnlOutputSize[i] *= -1.;
247 outputOrigin[i] = outputOrigin[i] + outputSpacing[i] * (vnlOutputSize[i]-1);
248 outputSpacing[i] *= -1.;
250 outputSize[i] = lrint(vnlOutputSize[i]);
252 resampler->SetSize( outputSize );
253 resampler->SetOutputSpacing( outputSpacing );
254 resampler->SetOutputOrigin( outputOrigin );
257 typename OutputImageType::SizeType outputSize;
258 if (m_ArgsInfo.size_given) {
259 for(unsigned int i=0; i< Dimension; i++)
260 outputSize[i]=m_ArgsInfo.size_arg[i];
261 } else outputSize=input->GetLargestPossibleRegion().GetSize();
264 typename OutputImageType::SpacingType outputSpacing;
265 if (m_ArgsInfo.spacing_given) {
266 for(unsigned int i=0; i< Dimension; i++)
267 outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
268 } else outputSpacing=input->GetSpacing();
271 typename OutputImageType::PointType outputOrigin;
272 if (m_ArgsInfo.origin_given) {
273 for(unsigned int i=0; i< Dimension; i++)
274 outputOrigin[i]=m_ArgsInfo.origin_arg[i];
275 } else outputOrigin=input->GetOrigin();
278 resampler->SetSize( outputSize );
279 resampler->SetOutputSpacing( outputSpacing );
280 resampler->SetOutputOrigin( outputOrigin );
284 if (m_ArgsInfo.verbose_flag) {
285 std::cout << "Setting the output size to " << resampler->GetSize() << "..." << std::endl;
286 std::cout << "Setting the output spacing to " << resampler->GetOutputSpacing() << "..." << std::endl;
287 std::cout << "Setting the output origin to " << resampler->GetOutputOrigin() << "..." << std::endl;
290 resampler->SetInput( input );
291 resampler->SetTransform( affineTransform );
292 resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
293 resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
297 } catch(itk::ExceptionObject) {
298 std::cerr<<"Error resampling the image"<<std::endl;
301 typename OutputImageType::Pointer output = resampler->GetOutput();
304 typedef itk::ImageFileWriter<OutputImageType> WriterType;
305 typename WriterType::Pointer writer = WriterType::New();
306 writer->SetFileName(m_ArgsInfo.output_arg);
307 writer->SetInput(output);
312 //-------------------------------------------------------------------
313 // Update with the number of dimensions and the pixeltype (components)
314 //-------------------------------------------------------------------
315 template<class args_info_type>
316 template<unsigned int Dimension, class PixelType>
317 void AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndVectorType()
320 typedef itk::Image<PixelType, Dimension> InputImageType;
321 typedef itk::Image<PixelType, Dimension> OutputImageType;
324 typedef itk::ImageFileReader<InputImageType> InputReaderType;
325 typename InputReaderType::Pointer reader = InputReaderType::New();
326 reader->SetFileName( m_InputFileName);
328 typename InputImageType::Pointer input= reader->GetOutput();
331 typedef itk::VectorResampleImageFilter< InputImageType,OutputImageType, double > ResampleFilterType;
332 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
335 typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
336 if (m_ArgsInfo.rotate_given || m_ArgsInfo.translate_given)
338 if (m_ArgsInfo.matrix_given)
340 std::cerr << "You must use either rotate/translate or matrix options" << std::cout;
343 itk::Array<double> transformParameters(2 * Dimension);
344 transformParameters.Fill(0.0);
345 if (m_ArgsInfo.rotate_given)
348 transformParameters[0] = m_ArgsInfo.rotate_arg[0];
350 for (unsigned int i = 0; i < 3; i++)
351 transformParameters[i] = m_ArgsInfo.rotate_arg[i];
353 if (m_ArgsInfo.translate_given)
358 for (unsigned int i = 0; i < Dimension && i < 3; i++)
359 transformParameters[pos++] = m_ArgsInfo.translate_arg[i];
363 matrix.SetIdentity();
364 itk::Matrix<double, 4, 4> tmp = GetForwardAffineMatrix3D(transformParameters);
365 for (unsigned int i = 0; i < 3; ++i)
366 for (unsigned int j = 0; j < 3; ++j)
367 matrix[i][j] = tmp[i][j];
368 for (unsigned int i = 0; i < 3; ++i)
369 matrix[i][4] = tmp[i][3];
372 matrix = GetForwardAffineMatrix<Dimension>(transformParameters);
376 if (m_ArgsInfo.matrix_given)
378 matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
379 if (m_Verbose) std::cout << "Reading the matrix..." << std::endl;
382 matrix.SetIdentity();
385 std::cout << "Using the following matrix:" << std::endl
386 << matrix << std::endl;
387 typename itk::Matrix<double, Dimension, Dimension> rotationMatrix = clitk::GetRotationalPartMatrix(matrix);
388 typename itk::Vector<double, Dimension> translationPart = clitk::GetTranslationPartMatrix(matrix);
391 typedef itk::AffineTransform<double, Dimension> AffineTransformType;
392 typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
393 affineTransform->SetMatrix(rotationMatrix);
394 affineTransform->SetTranslation(translationPart);
397 typedef clitk::GenericVectorInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
398 typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
399 genericInterpolator->SetArgsInfo(m_ArgsInfo);
402 if (m_ArgsInfo.like_given) {
403 typename InputReaderType::Pointer likeReader=InputReaderType::New();
404 likeReader->SetFileName(m_ArgsInfo.like_arg);
405 likeReader->Update();
406 resampler->SetSize( likeReader->GetOutput()->GetLargestPossibleRegion().GetSize() );
407 resampler->SetOutputSpacing( likeReader->GetOutput()->GetSpacing() );
408 resampler->SetOutputOrigin( likeReader->GetOutput()->GetOrigin() );
411 typename OutputImageType::SizeType outputSize;
412 if (m_ArgsInfo.size_given) {
413 for(unsigned int i=0; i< Dimension; i++)
414 outputSize[i]=m_ArgsInfo.size_arg[i];
415 } else outputSize=input->GetLargestPossibleRegion().GetSize();
416 std::cout<<"Setting the size to "<<outputSize<<"..."<<std::endl;
419 typename OutputImageType::SpacingType outputSpacing;
420 if (m_ArgsInfo.spacing_given) {
421 for(unsigned int i=0; i< Dimension; i++)
422 outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
423 } else outputSpacing=input->GetSpacing();
424 std::cout<<"Setting the spacing to "<<outputSpacing<<"..."<<std::endl;
427 typename OutputImageType::PointType outputOrigin;
428 if (m_ArgsInfo.origin_given) {
429 for(unsigned int i=0; i< Dimension; i++)
430 outputOrigin[i]=m_ArgsInfo.origin_arg[i];
431 } else outputOrigin=input->GetOrigin();
432 std::cout<<"Setting the origin to "<<outputOrigin<<"..."<<std::endl;
435 resampler->SetSize( outputSize );
436 resampler->SetOutputSpacing( outputSpacing );
437 resampler->SetOutputOrigin( outputOrigin );
441 resampler->SetInput( input );
442 resampler->SetTransform( affineTransform );
443 resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
444 resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
448 } catch(itk::ExceptionObject) {
449 std::cerr<<"Error resampling the image"<<std::endl;
452 typename OutputImageType::Pointer output = resampler->GetOutput();
455 typedef itk::ImageFileWriter<OutputImageType> WriterType;
456 typename WriterType::Pointer writer = WriterType::New();
457 writer->SetFileName(m_ArgsInfo.output_arg);
458 writer->SetInput(output);
466 #endif //#define clitkAffineTransformGenericFilter_txx