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