]> Creatis software - clitk.git/blob - tools/clitkAffineTransformGenericFilter.txx
Added --transform_grid which uses input->GetDirection
[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     // Size is converted to double, transformed and converted back to size type
172     vnl_vector<double> vnlOutputSize(Dimension);
173     for(unsigned int i=0; i< Dimension; i++) {
174       vnlOutputSize[i] = input->GetLargestPossibleRegion().GetSize()[i];
175     }
176     vnlOutputSize = invRotMatrix *
177                     input->GetDirection().GetVnlMatrix() *
178                     vnlOutputSize;
179     typename OutputImageType::SizeType outputSize;
180     for(unsigned int i=0; i< Dimension; i++) {
181       outputSize[i] = lrint(vnlOutputSize[i]);
182     }
183     resampler->SetSize( outputSize );
184     
185     // Spacing can be dictly computed in the same way
186     resampler->SetOutputSpacing ( invRotMatrix *
187                                   input->GetDirection() *
188                                   input->GetSpacing() );
189     // Origin is influenced by translation but not by direction
190     resampler->SetOutputOrigin ( invRotMatrix *
191                                  input->GetOrigin() +
192                                  invTrans );
193   } else {
194     //Size
195     typename OutputImageType::SizeType outputSize;
196     if (m_ArgsInfo.size_given) {
197       for(unsigned int i=0; i< Dimension; i++)
198         outputSize[i]=m_ArgsInfo.size_arg[i];
199     } else outputSize=input->GetLargestPossibleRegion().GetSize();
200
201     //Spacing
202     typename OutputImageType::SpacingType outputSpacing;
203     if (m_ArgsInfo.spacing_given) {
204       for(unsigned int i=0; i< Dimension; i++)
205         outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
206     } else outputSpacing=input->GetSpacing();
207
208     //Origin
209     typename OutputImageType::PointType outputOrigin;
210     if (m_ArgsInfo.origin_given) {
211       for(unsigned int i=0; i< Dimension; i++)
212         outputOrigin[i]=m_ArgsInfo.origin_arg[i];
213     } else outputOrigin=input->GetOrigin();
214
215     // Set
216     resampler->SetSize( outputSize );
217     resampler->SetOutputSpacing( outputSpacing );
218     resampler->SetOutputOrigin(  outputOrigin );
219
220   }
221
222   if (m_ArgsInfo.verbose_flag) {
223     std::cout << "Setting the output size to " << resampler->GetSize() << "..." << std::endl;
224     std::cout << "Setting the output spacing to " << resampler->GetOutputSpacing() << "..." << std::endl;
225     std::cout << "Setting the output origin to " << resampler->GetOutputOrigin() << "..." << std::endl;
226   }
227
228   resampler->SetInput( input );
229   resampler->SetTransform( affineTransform );
230   resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
231   resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
232
233   try {
234     resampler->Update();
235   } catch(itk::ExceptionObject) {
236     std::cerr<<"Error resampling the image"<<std::endl;
237   }
238
239   typename OutputImageType::Pointer output = resampler->GetOutput();
240
241   // Output
242   typedef itk::ImageFileWriter<OutputImageType> WriterType;
243   typename WriterType::Pointer writer = WriterType::New();
244   writer->SetFileName(m_ArgsInfo.output_arg);
245   writer->SetInput(output);
246   writer->Update();
247
248 }
249
250 //-------------------------------------------------------------------
251 // Update with the number of dimensions and the pixeltype (components)
252 //-------------------------------------------------------------------
253 template<class args_info_type>
254 template<unsigned int Dimension, class PixelType>
255 void AffineTransformGenericFilter<args_info_type>::UpdateWithDimAndVectorType()
256 {
257   // ImageTypes
258   typedef itk::Image<PixelType, Dimension> InputImageType;
259   typedef itk::Image<PixelType, Dimension> OutputImageType;
260
261   // Read the input
262   typedef itk::ImageFileReader<InputImageType> InputReaderType;
263   typename InputReaderType::Pointer reader = InputReaderType::New();
264   reader->SetFileName( m_InputFileName);
265   reader->Update();
266   typename InputImageType::Pointer input= reader->GetOutput();
267
268   //Filter
269   typedef  itk::VectorResampleImageFilter< InputImageType,OutputImageType, double >  ResampleFilterType;
270   typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
271
272   // Matrix
273   typename itk::Matrix<double, Dimension+1, Dimension+1> matrix;
274   if (m_ArgsInfo.matrix_given)
275     matrix= clitk::ReadMatrix<Dimension>(m_ArgsInfo.matrix_arg);
276   else
277     matrix.SetIdentity();
278   if (m_Verbose) std::cout<<"Using the following matrix:"<<std::endl;
279   if (m_Verbose) std::cout<<matrix<<std::endl;
280   typename itk::Matrix<double, Dimension, Dimension> rotationMatrix=clitk::GetRotationalPartMatrix(matrix);
281   typename itk::Vector<double, Dimension> translationPart= clitk::GetTranslationPartMatrix(matrix);
282
283   // Transform
284   typedef itk::AffineTransform<double, Dimension> AffineTransformType;
285   typename AffineTransformType::Pointer affineTransform=AffineTransformType::New();
286   affineTransform->SetMatrix(rotationMatrix);
287   affineTransform->SetTranslation(translationPart);
288
289   // Interp
290   typedef clitk::GenericVectorInterpolator<args_info_type, InputImageType, double> GenericInterpolatorType;
291   typename GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
292   genericInterpolator->SetArgsInfo(m_ArgsInfo);
293
294   // Properties
295   if (m_ArgsInfo.like_given) {
296     typename InputReaderType::Pointer likeReader=InputReaderType::New();
297     likeReader->SetFileName(m_ArgsInfo.like_arg);
298     likeReader->Update();
299     resampler->SetSize( likeReader->GetOutput()->GetLargestPossibleRegion().GetSize() );
300     resampler->SetOutputSpacing( likeReader->GetOutput()->GetSpacing() );
301     resampler->SetOutputOrigin(  likeReader->GetOutput()->GetOrigin() );
302   } else {
303     //Size
304     typename OutputImageType::SizeType outputSize;
305     if (m_ArgsInfo.size_given) {
306       for(unsigned int i=0; i< Dimension; i++)
307         outputSize[i]=m_ArgsInfo.size_arg[i];
308     } else outputSize=input->GetLargestPossibleRegion().GetSize();
309     std::cout<<"Setting the size to "<<outputSize<<"..."<<std::endl;
310
311     //Spacing
312     typename OutputImageType::SpacingType outputSpacing;
313     if (m_ArgsInfo.spacing_given) {
314       for(unsigned int i=0; i< Dimension; i++)
315         outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
316     } else outputSpacing=input->GetSpacing();
317     std::cout<<"Setting the spacing to "<<outputSpacing<<"..."<<std::endl;
318
319     //Origin
320     typename OutputImageType::PointType outputOrigin;
321     if (m_ArgsInfo.origin_given) {
322       for(unsigned int i=0; i< Dimension; i++)
323         outputOrigin[i]=m_ArgsInfo.origin_arg[i];
324     } else outputOrigin=input->GetOrigin();
325     std::cout<<"Setting the origin to "<<outputOrigin<<"..."<<std::endl;
326
327     // Set
328     resampler->SetSize( outputSize );
329     resampler->SetOutputSpacing( outputSpacing );
330     resampler->SetOutputOrigin(  outputOrigin );
331
332   }
333
334   resampler->SetInput( input );
335   resampler->SetTransform( affineTransform );
336   resampler->SetInterpolator( genericInterpolator->GetInterpolatorPointer());
337   resampler->SetDefaultPixelValue( static_cast<PixelType>(m_ArgsInfo.pad_arg) );
338
339   try {
340     resampler->Update();
341   } catch(itk::ExceptionObject) {
342     std::cerr<<"Error resampling the image"<<std::endl;
343   }
344
345   typename OutputImageType::Pointer output = resampler->GetOutput();
346
347   // Output
348   typedef itk::ImageFileWriter<OutputImageType> WriterType;
349   typename WriterType::Pointer writer = WriterType::New();
350   writer->SetFileName(m_ArgsInfo.output_arg);
351   writer->SetInput(output);
352   writer->Update();
353
354 }
355
356
357 } //end clitk
358
359 #endif //#define clitkAffineTransformGenericFilter_txx