1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 //  Software Guide : BeginLatex
20 //
21 //  This example illustrates the use of the \doxygen{Similarity2DTransform}. A
22 //  similarity transform involves rotation, translation and scaling. Since the
23 //  parameterization of rotations is difficult to get in a generic $ND$ case, a
24 //  particular implementation is available for $2D$.
25 //
26 //
27 //  Software Guide : EndLatex
28 
29 
30 #include "itkImage.h"
31 #include "itkImageFileReader.h"
32 #include "itkImageFileWriter.h"
33 #include "itkResampleImageFilter.h"
34 
35 
36 //  Software Guide : BeginLatex
37 //
38 //  The header file of the transform is included below.
39 //
40 //  \index{itk::Similarity2DTransform!header}
41 //
42 //  Software Guide : EndLatex
43 
44 // Software Guide : BeginCodeSnippet
45 #include "itkSimilarity2DTransform.h"
46 // Software Guide : EndCodeSnippet
47 
48 
main(int argc,char * argv[])49 int main( int argc, char * argv[] )
50 {
51   if( argc < 5 )
52     {
53     std::cerr << "Usage: " << std::endl;
54     std::cerr << argv[0] << "  inputImageFile  outputImageFile  degrees  scale" << std::endl;
55     return EXIT_FAILURE;
56     }
57 
58   constexpr unsigned int Dimension = 2;
59   using InputPixelType = unsigned char;
60   using OutputPixelType = unsigned char;
61 
62   using InputImageType = itk::Image< InputPixelType,  Dimension >;
63   using OutputImageType = itk::Image< OutputPixelType, Dimension >;
64 
65   using ReaderType = itk::ImageFileReader< InputImageType  >;
66   using WriterType = itk::ImageFileWriter< OutputImageType >;
67 
68   ReaderType::Pointer reader = ReaderType::New();
69   WriterType::Pointer writer = WriterType::New();
70 
71   reader->SetFileName( argv[1] );
72   writer->SetFileName( argv[2] );
73 
74   const double angleInDegrees = std::stod( argv[3] );
75   const double scale          = std::stod( argv[4] );
76 
77   using FilterType = itk::ResampleImageFilter<
78                   InputImageType, OutputImageType >;
79 
80   FilterType::Pointer filter = FilterType::New();
81 
82 
83   //  Software Guide : BeginLatex
84   //
85   //  The transform type is instantiated using the coordinate representation
86   //  type as the single template parameter.
87   //
88   //  \index{itk::Similarity2DTransform!instantiation}
89   //
90   //  Software Guide : EndLatex
91 
92   // Software Guide : BeginCodeSnippet
93   using TransformType = itk::Similarity2DTransform< double >;
94   // Software Guide : EndCodeSnippet
95 
96 
97   //  Software Guide : BeginLatex
98   //
99   //  A transform object is constructed by calling \code{New()} and passing
100   //  the result to a \doxygen{SmartPointer}.
101   //
102   //  \index{itk::Similarity2DTransform!New()}
103   //  \index{itk::Similarity2DTransform!Pointer}
104   //
105   //  Software Guide : EndLatex
106 
107   // Software Guide : BeginCodeSnippet
108   TransformType::Pointer transform = TransformType::New();
109   // Software Guide : EndCodeSnippet
110 
111 
112   using InterpolatorType = itk::LinearInterpolateImageFunction<
113                        InputImageType, double >;
114   InterpolatorType::Pointer interpolator = InterpolatorType::New();
115 
116   filter->SetInterpolator( interpolator );
117 
118   filter->SetDefaultPixelValue( 100 );
119 
120 
121   //  Software Guide : BeginLatex
122   //
123   //  The parameters of the output image are taken from the input image.
124   //
125   //  Software Guide : EndLatex
126 
127   reader->Update();
128   const InputImageType::SpacingType&
129     spacing = reader->GetOutput()->GetSpacing();
130   const InputImageType::PointType&
131     origin  = reader->GetOutput()->GetOrigin();
132   const InputImageType::DirectionType&
133     direction  = reader->GetOutput()->GetDirection();
134   InputImageType::SizeType size =
135       reader->GetOutput()->GetLargestPossibleRegion().GetSize();
136 
137   filter->SetOutputOrigin( origin );
138   filter->SetOutputSpacing( spacing );
139   filter->SetOutputDirection( direction );
140   filter->SetSize( size );
141 
142 
143   filter->SetInput( reader->GetOutput() );
144   writer->SetInput( filter->GetOutput() );
145 
146 
147   //  Software Guide : BeginLatex
148   //
149   //  The Similarity2DTransform allows the user to select the
150   //  center of rotation.  This center is used for both rotation and scaling
151   //  operations.
152   //
153   //  \index{itk::Similarity2DTransform!SetRotationCenter()}
154   //
155   //  Software Guide : EndLatex
156 
157   // Software Guide : BeginCodeSnippet
158   TransformType::InputPointType rotationCenter;
159   rotationCenter[0] = origin[0] + spacing[0] * size[0] / 2.0;
160   rotationCenter[1] = origin[1] + spacing[1] * size[1] / 2.0;
161   transform->SetCenter( rotationCenter );
162   // Software Guide : EndCodeSnippet
163 
164 
165   //  Software Guide : BeginLatex
166   //
167   //  The rotation is specified with the method \code{SetAngle()}.
168   //
169   //  \index{itk::Similarity2DTransform!SetAngle()}
170   //
171   //  Software Guide : EndLatex
172 
173   // Software Guide : BeginCodeSnippet
174   const double degreesToRadians = std::atan(1.0) / 45.0;
175   const double angle = angleInDegrees * degreesToRadians;
176   transform->SetAngle( angle );
177   // Software Guide : EndCodeSnippet
178 
179 
180   //  Software Guide : BeginLatex
181   //
182   //  The scale change is defined using the method \code{SetScale()}.
183   //  \index{itk::Similarity2DTransform!SetScale()}
184   //
185   //  Software Guide : EndLatex
186 
187   // Software Guide : BeginCodeSnippet
188   transform->SetScale( scale );
189   // Software Guide : EndCodeSnippet
190 
191 
192   //  Software Guide : BeginLatex
193   //
194   //  A translation to be applied after the rotation and scaling can be
195   //  specified with the method \code{SetTranslation()}.
196   //
197   //  \index{itk::AffineTransform!Translate()}
198   //
199   //  Software Guide : EndLatex
200 
201   // Software Guide : BeginCodeSnippet
202   TransformType::OutputVectorType translation;
203 
204   translation[0] =   13.0;
205   translation[1] =   17.0;
206 
207   transform->SetTranslation( translation );
208 
209   filter->SetTransform( transform );
210   // Software Guide : EndCodeSnippet
211 
212 
213   //  Software Guide : BeginLatex
214   //
215   //  Note that the order in which rotation, scaling and translation are
216   //  defined is irrelevant in this transform. This is not the case in the
217   //  Affine transform which is very generic and allows different combinations
218   //  for initialization. In the Similarity2DTransform class the
219   //  rotation and scaling will always be applied before the translation.
220   //
221   //  \index{itk::Similarity2DTransform!SetScale()}
222   //
223   //  Software Guide : EndLatex
224 
225 
226   try
227     {
228     writer->Update();
229     }
230   catch( itk::ExceptionObject & excep )
231     {
232     std::cerr << "Exception catched !" << std::endl;
233     std::cerr << excep << std::endl;
234     }
235 
236 
237   //  Software Guide : BeginLatex
238   //
239   //  \begin{figure}
240   //  \center
241   //  \includegraphics[width=0.44\textwidth]{BrainProtonDensitySliceBorder20}
242   //  \includegraphics[width=0.44\textwidth]{ResampleImageFilterOutput11}
243   //  \itkcaption[Effect of the Resample filter rotating and scaling an
244   //  image]{Effect of the resample filter rotating and scaling an image.}
245   //  \label{fig:ResampleImageFilterOutput11}
246   //  \end{figure}
247   //
248   //  Figure \ref{fig:ResampleImageFilterOutput11} shows the effect of this
249   //  rotation, translation and scaling on a slice of a brain MRI. The scale
250   //  applied for producing this figure was $1.2$ and the rotation angle was
251   //  $10^{\circ}$.
252   //
253   //  Software Guide : EndLatex
254 
255 
256   return EXIT_SUCCESS;
257 }
258