]> Creatis software - clitk.git/blob - tools/clitkAffineTransformGenericFilter.txx
Merge commit '488f24aa984ae24adc9458bf5fbf3b2351415742'
[clitk.git] / tools / clitkAffineTransformGenericFilter.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
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
8
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.
12
13   It is distributed under dual licence
14
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
20
21 /* =================================================
22  * @file   clitkAffineTransformGenericFilter.txx
23  * @author
24  * @date
25  *
26  * @brief
27  *
28  ===================================================*/
29
30
31 namespace clitk
32 {
33
34 //-----------------------------------------------------------
35 // Constructor
36 //-----------------------------------------------------------
37 template<class args_info_type>
38 AffineTransformGenericFilter<args_info_type>::AffineTransformGenericFilter()
39 {
40   m_Verbose=false;
41   m_InputFileName="";
42 }
43
44
45 //-----------------------------------------------------------
46 // Update
47 //-----------------------------------------------------------
48 template<class args_info_type>
49 void AffineTransformGenericFilter<args_info_type>::Update()
50 {
51   // Read the Dimension and PixelType
52   int Dimension, Components;
53   std::string PixelType;
54   ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
55
56
57   // Call UpdateWithDim
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);
61   else {
62     std::cout<<"Error, Only for 2, 3 or 4  Dimensions!!!"<<std::endl ;
63     return;
64   }
65 }
66
67 //-------------------------------------------------------------------
68 // Update with the number of dimensions
69 //-------------------------------------------------------------------
70 template<class args_info_type>
71 template<unsigned int Dimension>
72 void
73 AffineTransformGenericFilter<args_info_type>::UpdateWithDim(std::string PixelType, int Components)
74 {
75   if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<<Components<<" component(s) of "<<  PixelType<<"..."<<std::endl;
76
77   if (Components==1) {
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>();
81     }
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>();
85     //     }
86
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>();
90     }
91
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>();
95     //     }
96     else {
97       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
98       UpdateWithDimAndPixelType<Dimension, float>();
99     }
100   }
101
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> >();
105   }
106
107   else std::cerr<<"Number of components is "<<Components<<", not supported!"<<std::endl;
108
109 }
110
111
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>
117 void
118 AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndPixelType()
119 {
120
121   // ImageTypes
122   typedef itk::Image<PixelType, Dimension> InputImageType;
123   typedef itk::Image<PixelType, Dimension> OutputImageType;
124
125   // Read the input
126   typedef itk::ImageFileReader<InputImageType> InputReaderType;
127   typename InputReaderType::Pointer reader = InputReaderType::New();
128   reader->SetFileName( m_InputFileName);
129   reader->Update();
130   typename InputImageType::Pointer input= reader->GetOutput();
131
132   //Filter
133   typedef  itk::ResampleImageFilter< InputImageType,OutputImageType >  ResampleFilterType;
134   typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
135
136   // Matrix
137   typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
138   if (m_ArgsInfo.matrix_given) {
139     matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
140     if (m_Verbose) std::cout<<"Reading the matrix..."<<std::endl;
141   } else {
142     matrix.SetIdentity();
143   }
144   if (m_Verbose) std::cout<<"Using the following matrix:"<<std::endl;
145   if (m_Verbose) std::cout<<matrix<<std::endl;
146   typename itk::Matrix<double, Dimension, Dimension> rotationMatrix=clitk::GetRotationalPartMatrix(matrix);
147   typename itk::Vector<double,Dimension> translationPart= clitk::GetTranslationPartMatrix(matrix);
148
149   // Transform
150   typedef itk::AffineTransform<double, Dimension> AffineTransformType;
151   typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
152   affineTransform->SetMatrix(rotationMatrix);
153   affineTransform->SetTranslation(translationPart);
154
155   // Interp
156   typedef clitk::GenericInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
157   typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
158   genericInterpolator->SetArgsInfo(m_ArgsInfo);
159
160   // Properties
161   if (m_ArgsInfo.like_given) {
162     typename InputReaderType::Pointer likeReader=InputReaderType::New();
163     likeReader->SetFileName(m_ArgsInfo.like_arg);
164     likeReader->Update();
165     resampler->SetOutputParametersFromImage(likeReader->GetOutput());
166   } else if(m_ArgsInfo.transform_grid_flag) {
167     typename itk::Matrix<double, Dimension+1, Dimension+1> invMatrix( matrix.GetInverse() );
168     typename itk::Matrix<double, Dimension, Dimension> invRotMatrix( clitk::GetRotationalPartMatrix(invMatrix) );
169     typename itk::Vector<double,Dimension> invTrans =  clitk::GetTranslationPartMatrix(invMatrix);
170
171     // Spacing is influenced by affine transform matrix and input direction
172     typename InputImageType::SpacingType outputSpacing;
173     outputSpacing = invRotMatrix *
174                     input->GetDirection() *
175                     input->GetSpacing();
176
177     // Origin is influenced by translation but not by input direction
178     typename InputImageType::PointType outputOrigin;
179     outputOrigin = invRotMatrix *
180                    input->GetOrigin() +
181                    invTrans;
182
183     // Size is influenced by affine transform matrix and input direction
184     // Size is converted to double, transformed and converted back to size type.
185     vnl_vector<double> vnlOutputSize(Dimension);
186     for(unsigned int i=0; i< Dimension; i++) {
187       vnlOutputSize[i] = input->GetLargestPossibleRegion().GetSize()[i];
188     }
189     vnlOutputSize = invRotMatrix *
190                     input->GetDirection().GetVnlMatrix() *
191                     vnlOutputSize;
192     typename OutputImageType::SizeType outputSize;
193     for(unsigned int i=0; i< Dimension; i++) {
194       // If the size is negative, we have a flip and we must modify
195       // the origin and the spacing accordingly.
196       if(vnlOutputSize[i]<0.) {
197         vnlOutputSize[i] *= -1.;
198         outputOrigin[i] = outputOrigin[i] + outputSpacing[i] * (vnlOutputSize[i]-1);
199         outputSpacing[i] *= -1.;
200       }
201       outputSize[i] = lrint(vnlOutputSize[i]);
202     }
203     resampler->SetSize( outputSize );
204     resampler->SetOutputSpacing( outputSpacing );
205     resampler->SetOutputOrigin( outputOrigin );
206   } else {
207     //Size
208     typename OutputImageType::SizeType outputSize;
209     if (m_ArgsInfo.size_given) {
210       for(unsigned int i=0; i< Dimension; i++)
211         outputSize[i]=m_ArgsInfo.size_arg[i];
212     } else outputSize=input->GetLargestPossibleRegion().GetSize();
213
214     //Spacing
215     typename OutputImageType::SpacingType outputSpacing;
216     if (m_ArgsInfo.spacing_given) {
217       for(unsigned int i=0; i< Dimension; i++)
218         outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
219     } else outputSpacing=input->GetSpacing();
220
221     //Origin
222     typename OutputImageType::PointType outputOrigin;
223     if (m_ArgsInfo.origin_given) {
224       for(unsigned int i=0; i< Dimension; i++)
225         outputOrigin[i]=m_ArgsInfo.origin_arg[i];
226     } else outputOrigin=input->GetOrigin();
227
228     // Set
229     resampler->SetSize( outputSize );
230     resampler->SetOutputSpacing( outputSpacing );
231     resampler->SetOutputOrigin(  outputOrigin );
232
233   }
234
235   if (m_ArgsInfo.verbose_flag) {
236     std::cout << "Setting the output size to " << resampler->GetSize() << "..." << std::endl;
237     std::cout << "Setting the output spacing to " << resampler->GetOutputSpacing() << "..." << std::endl;
238     std::cout << "Setting the output origin to " << resampler->GetOutputOrigin() << "..." << std::endl;
239   }
240
241   resampler->SetInput( input );
242   resampler->SetTransform( affineTransform );
243   resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
244   resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
245
246   try {
247     resampler->Update();
248   } catch(itk::ExceptionObject) {
249     std::cerr<<"Error resampling the image"<<std::endl;
250   }
251
252   typename OutputImageType::Pointer output = resampler->GetOutput();
253
254   // Output
255   typedef itk::ImageFileWriter<OutputImageType> WriterType;
256   typename WriterType::Pointer writer = WriterType::New();
257   writer->SetFileName(m_ArgsInfo.output_arg);
258   writer->SetInput(output);
259   writer->Update();
260
261 }
262
263 //-------------------------------------------------------------------
264 // Update with the number of dimensions and the pixeltype (components)
265 //-------------------------------------------------------------------
266 template<class args_info_type>
267 template<unsigned int Dimension, class PixelType>
268 void AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndVectorType()
269 {
270   // ImageTypes
271   typedef itk::Image<PixelType, Dimension> InputImageType;
272   typedef itk::Image<PixelType, Dimension> OutputImageType;
273
274   // Read the input
275   typedef itk::ImageFileReader<InputImageType> InputReaderType;
276   typename InputReaderType::Pointer reader = InputReaderType::New();
277   reader->SetFileName( m_InputFileName);
278   reader->Update();
279   typename InputImageType::Pointer input= reader->GetOutput();
280
281   //Filter
282   typedef  itk::VectorResampleImageFilter< InputImageType,OutputImageType, double >  ResampleFilterType;
283   typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
284
285   // Matrix
286   typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
287   if (m_ArgsInfo.matrix_given)
288     matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
289   else
290     matrix.SetIdentity();
291   if (m_Verbose) std::cout<<"Using the following matrix:"<<std::endl;
292   if (m_Verbose) std::cout<<matrix<<std::endl;
293   typename itk::Matrix<double, Dimension, Dimension> rotationMatrix=clitk::GetRotationalPartMatrix(matrix);
294   typename itk::Vector<double, Dimension> translationPart= clitk::GetTranslationPartMatrix(matrix);
295
296   // Transform
297   typedef itk::AffineTransform<double, Dimension> AffineTransformType;
298   typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
299   affineTransform->SetMatrix(rotationMatrix);
300   affineTransform->SetTranslation(translationPart);
301
302   // Interp
303   typedef clitk::GenericVectorInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
304   typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
305   genericInterpolator->SetArgsInfo(m_ArgsInfo);
306
307   // Properties
308   if (m_ArgsInfo.like_given) {
309     typename InputReaderType::Pointer likeReader=InputReaderType::New();
310     likeReader->SetFileName(m_ArgsInfo.like_arg);
311     likeReader->Update();
312     resampler->SetSize( likeReader->GetOutput()->GetLargestPossibleRegion().GetSize() );
313     resampler->SetOutputSpacing( likeReader->GetOutput()->GetSpacing() );
314     resampler->SetOutputOrigin(  likeReader->GetOutput()->GetOrigin() );
315   } else {
316     //Size
317     typename OutputImageType::SizeType outputSize;
318     if (m_ArgsInfo.size_given) {
319       for(unsigned int i=0; i< Dimension; i++)
320         outputSize[i]=m_ArgsInfo.size_arg[i];
321     } else outputSize=input->GetLargestPossibleRegion().GetSize();
322     std::cout<<"Setting the size to "<<outputSize<<"..."<<std::endl;
323
324     //Spacing
325     typename OutputImageType::SpacingType outputSpacing;
326     if (m_ArgsInfo.spacing_given) {
327       for(unsigned int i=0; i< Dimension; i++)
328         outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
329     } else outputSpacing=input->GetSpacing();
330     std::cout<<"Setting the spacing to "<<outputSpacing<<"..."<<std::endl;
331
332     //Origin
333     typename OutputImageType::PointType outputOrigin;
334     if (m_ArgsInfo.origin_given) {
335       for(unsigned int i=0; i< Dimension; i++)
336         outputOrigin[i]=m_ArgsInfo.origin_arg[i];
337     } else outputOrigin=input->GetOrigin();
338     std::cout<<"Setting the origin to "<<outputOrigin<<"..."<<std::endl;
339
340     // Set
341     resampler->SetSize( outputSize );
342     resampler->SetOutputSpacing( outputSpacing );
343     resampler->SetOutputOrigin(  outputOrigin );
344
345   }
346
347   resampler->SetInput( input );
348   resampler->SetTransform( affineTransform );
349   resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
350   resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
351
352   try {
353     resampler->Update();
354   } catch(itk::ExceptionObject) {
355     std::cerr<<"Error resampling the image"<<std::endl;
356   }
357
358   typename OutputImageType::Pointer output = resampler->GetOutput();
359
360   // Output
361   typedef itk::ImageFileWriter<OutputImageType> WriterType;
362   typename WriterType::Pointer writer = WriterType::New();
363   writer->SetFileName(m_ArgsInfo.output_arg);
364   writer->SetInput(output);
365   writer->Update();
366
367 }
368
369
370 } //end clitk
371
372 #endif //#define clitkAffineTransformGenericFilter_txx