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 common task of extracting a 2D slice from a
22 //  3D volume. Perform some processing on that slice and then paste it on an
23 //  output volume of the same size as the volume from the input.
24 //
25 //  In this example we start by including the appropriate header files.
26 //
27 //  Software Guide : EndLatex
28 // Software Guide : BeginCodeSnippet
29 #include "itkImageFileReader.h"
30 #include "itkImageFileWriter.h"
31 // Software Guide : EndCodeSnippet
32 
33 //  Software Guide : BeginLatex
34 //
35 //  The filter used to extract a region from an image is the
36 //  \doxygen{ExtractImageFilter}. Its header is included below.  This filter
37 //  is capable of extracting a slice from the input image.
38 //
39 //  \index{itk::ExtractImageFilter!header}
40 //
41 //  Software Guide : EndLatex
42 // Software Guide : BeginCodeSnippet
43 #include "itkExtractImageFilter.h"
44 // Software Guide : EndCodeSnippet
45 
46 //  Software Guide : BeginLatex
47 //
48 //  The filter used to place the processed image in a region of the output
49 //  image is the \doxygen{PasteImageFilter}. Its header is included below.
50 //  This filter is capable of inserting the processed image into the
51 //  destination image.
52 //
53 //  \index{itk::PasteImageFilter!header}
54 //
55 //  Software Guide : EndLatex
56 // Software Guide : BeginCodeSnippet
57 #include "itkPasteImageFilter.h"
58 // Software Guide : EndCodeSnippet
59 // Software Guide : BeginCodeSnippet
60 #include "itkMedianImageFilter.h"
61 // Software Guide : EndCodeSnippet
main(int argc,char ** argv)62 int main( int argc, char ** argv )
63 {
64   // Verify the number of parameters in the command line
65   if( argc <= 3 )
66     {
67     std::cerr << "Usage: " << std::endl;
68     std::cerr << argv[0] << " input3DImageFile  output3DImageFile " << std::endl;
69     std::cerr << " sliceNumber " << std::endl;
70     return EXIT_FAILURE;
71     }
72 
73   //  Software Guide : BeginLatex
74   //
75   //  Image types are defined below. Note that the input image type is $3D$ and
76   //  the output image type is a $3D$ image as well.
77   //
78   //  Software Guide : EndLatex
79   // Software Guide : BeginCodeSnippet
80   using InputPixelType = unsigned char;
81   using MiddlePixelType = unsigned char;
82   using OutputPixelType = unsigned char;
83   using InputImageType = itk::Image< InputPixelType,  3 >;
84   using MiddleImageType = itk::Image< MiddlePixelType, 3 >;
85   using OutputImageType = itk::Image< OutputPixelType, 3 >;
86   // Software Guide : EndCodeSnippet
87 
88   //  Software Guide : BeginLatex
89   //
90   //  The types for the \doxygen{ImageFileReader} and \doxygen{ImageFileWriter}
91   //  are instantiated using the image types.
92   //
93   //  Software Guide : EndLatex
94   // Software Guide : BeginCodeSnippet
95   using ReaderType = itk::ImageFileReader< InputImageType  >;
96   using WriterType = itk::ImageFileWriter< OutputImageType >;
97   // Software Guide : EndCodeSnippet
98 
99   // Here we recover the file names from the command line arguments
100   //
101   const char * inputFilename  = argv[1];
102   const char * outputFilename = argv[2];
103 
104   //  Software Guide : BeginLatex
105   //
106   //  Below, we create the reader and writer  using the New() method and
107   //  assigning the result to a \doxygen{SmartPointer}.
108   //
109   //  \index{itk::ImageFileReader!New()}
110   //  \index{itk::ImageFileWriter!New()}
111   //  \index{itk::ImageFileReader!SmartPointer}
112   //  \index{itk::ImageFileWriter!SmartPointer}
113   //
114   //  Software Guide : EndLatex
115   // Software Guide : BeginCodeSnippet
116   ReaderType::Pointer reader = ReaderType::New();
117   WriterType::Pointer writer = WriterType::New();
118   // Software Guide : EndCodeSnippet
119 
120   //  Software Guide : BeginLatex
121   //
122   //  The name of the file to be read or written is passed with the
123   //  SetFileName() method.
124   //
125   //  \index{itk::ImageFileReader!SetFileName()}
126   //  \index{itk::ImageFileWriter!SetFileName()}
127   //  \index{SetFileName()!itk::ImageFileReader}
128   //  \index{SetFileName()!itk::ImageFileWriter}
129   //
130   //  Software Guide : EndLatex
131   // Software Guide : BeginCodeSnippet
132   reader->SetFileName( inputFilename  );
133   writer->SetFileName( outputFilename );
134   // Software Guide : EndCodeSnippet
135 
136   //  Software Guide : BeginLatex
137   //
138   //  The ExtractImageFilter type is instantiated using the input and
139   //  output image types. A filter object is created with the New()
140   //  method and assigned to a SmartPointer.
141   //
142   //  Software Guide : EndLatex
143   // Software Guide : BeginCodeSnippet
144   using ExtractFilterType =
145       itk::ExtractImageFilter< InputImageType, MiddleImageType >;
146   ExtractFilterType::Pointer extractFilter = ExtractFilterType::New();
147   extractFilter->SetDirectionCollapseToSubmatrix();
148   // Software Guide : EndCodeSnippet
149 
150   //  Software Guide : BeginLatex
151   //
152   //  The ExtractImageFilter requires a region to be defined by the user. The
153   //  region is specified by an \doxygen{Index} indicating the pixel where the
154   //  region starts and an \doxygen{Size} indication how many pixels the region
155   //  has along each dimension. In order to extract a $2D$ image from a $3D$
156   //  data set, it is enough to set the size of the region to $1$ in one
157   //  dimension. Note that, strictly speaking, we are extracting here a $3D$
158   //  image of a single slice. Here we take the region from the buffered region
159   //  of the input image. Note that Update() is being called first on the
160   //  reader, since otherwise the output would have invalid data.
161   //
162   //  Software Guide : EndLatex
163 
164   // Software Guide : BeginCodeSnippet
165   reader->Update();
166   const InputImageType * inputImage = reader->GetOutput();
167   InputImageType::RegionType inputRegion = inputImage->GetBufferedRegion();
168   // Software Guide : EndCodeSnippet
169 
170   //  Software Guide : BeginLatex
171   //
172   //  We take the size from the region and collapse the size in the $Z$
173   //  component by setting its value to $1$.
174   //
175   //  Software Guide : EndLatex
176   // Software Guide : BeginCodeSnippet
177   InputImageType::SizeType size = inputRegion.GetSize();
178   size[2] = 1;
179   // Software Guide : EndCodeSnippet
180   //  Software Guide : BeginLatex
181   //
182   //  Note that in this case we are extracting a $Z$ slice, and for that
183   //  reason, the dimension to be collapsed in the one with index $2$. You
184   //  may keep in mind the association of index components
185   //  $\{X=0,Y=1,Z=2\}$. If we were interested in extracting a slice
186   //  perpendicular to the $Y$ axis we would have set \code{size[1]=1;}.
187   //
188   //  Software Guide : EndLatex
189 
190   //  Software Guide : BeginLatex
191   //
192   //  Then, we take the index from the region and set its $Z$ value to the
193   //  slice number we want to extract. In this example we obtain the slice
194   //  number from the command line arguments.
195   //
196   //  Software Guide : EndLatex
197   // Software Guide : BeginCodeSnippet
198   InputImageType::IndexType start = inputRegion.GetIndex();
199   const unsigned int sliceNumber = std::stoi( argv[3] );
200   start[2] = sliceNumber;
201   // Software Guide : EndCodeSnippet
202 
203   //  Software Guide : BeginLatex
204   //
205   //  Finally, an \doxygen{ImageRegion} object is created and initialized with
206   //  the start and size we just prepared using the slice information.
207   //
208   //  Software Guide : EndLatex
209   // Software Guide : BeginCodeSnippet
210   InputImageType::RegionType desiredRegion;
211   desiredRegion.SetSize(  size  );
212   desiredRegion.SetIndex( start );
213   // Software Guide : EndCodeSnippet
214 
215   //  Software Guide : BeginLatex
216   //
217   //  Then the region is passed to the filter using the
218   //  SetExtractionRegion() method.
219   //
220   //  \index{itk::ExtractImageFilter!SetExtractionRegion()}
221   //
222   //  Software Guide : EndLatex
223 
224   // Software Guide : BeginCodeSnippet
225   extractFilter->SetExtractionRegion( desiredRegion );
226   // Software Guide : EndCodeSnippet
227   // Software Guide : BeginCodeSnippet
228   using PasteFilterType = itk::PasteImageFilter< MiddleImageType,
229                                  OutputImageType >;
230   PasteFilterType::Pointer pasteFilter = PasteFilterType::New();
231   // Software Guide : EndCodeSnippet
232   // Software Guide : BeginCodeSnippet
233   using MedianFilterType = itk::MedianImageFilter< MiddleImageType,
234                                   MiddleImageType >;
235   MedianFilterType::Pointer medianFilter = MedianFilterType::New();
236   // Software Guide : EndCodeSnippet
237   //  Software Guide : BeginLatex
238   //
239   //  Below we connect the reader, filter and writer to form the data
240   //  processing pipeline.
241   //
242   //  Software Guide : EndLatex
243   // Software Guide : BeginCodeSnippet
244   extractFilter->SetInput( inputImage );
245   medianFilter->SetInput( extractFilter->GetOutput() );
246   pasteFilter->SetSourceImage( medianFilter->GetOutput() );
247   pasteFilter->SetDestinationImage( inputImage );
248   pasteFilter->SetDestinationIndex( start );
249   MiddleImageType::SizeType indexRadius;
250   indexRadius[0] = 1; // radius along x
251   indexRadius[1] = 1; // radius along y
252   indexRadius[2] = 0; // radius along z
253   medianFilter->SetRadius( indexRadius );
254   medianFilter->UpdateLargestPossibleRegion();
255   const MiddleImageType * medianImage = medianFilter->GetOutput();
256   pasteFilter->SetSourceRegion( medianImage->GetBufferedRegion() );
257   writer->SetInput( pasteFilter->GetOutput() );
258   // Software Guide : EndCodeSnippet
259 
260   //  Software Guide : BeginLatex
261   //
262   //  Finally we execute the pipeline by invoking Update() on the writer. The
263   //  call is placed in a \code{try/catch} block in case exceptions are
264   //  thrown.
265   //
266   //  Software Guide : EndLatex
267   // Software Guide : BeginCodeSnippet
268   try
269     {
270     writer->Update();
271     }
272   catch( itk::ExceptionObject & err )
273     {
274     std::cerr << "ExceptionObject caught !" << std::endl;
275     std::cerr << err << std::endl;
276     return EXIT_FAILURE;
277     }
278   // Software Guide : EndCodeSnippet
279 
280   return EXIT_SUCCESS;
281 }
282