]> Creatis software - clitk.git/blob - itk/clitkResampleImageWithOptionsFilter.txx
aee15f5d397670e4f90a30c5b8ac497116bc2c20
[clitk.git] / itk / clitkResampleImageWithOptionsFilter.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://oncora1.lyon.fnclcc.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
19 // clitk
20 #include "clitkCommon.h"
21
22 // itk include
23 #include "itkImage.h"
24 #include "itkImageFileReader.h"
25 #include "itkImageSeriesReader.h"
26 #include "itkImageFileWriter.h"
27 #include "itkRecursiveGaussianImageFilter.h"
28 #include "itkResampleImageFilter.h"
29 #include "itkAffineTransform.h"
30 #include "itkNearestNeighborInterpolateImageFunction.h"
31 #include "itkLinearInterpolateImageFunction.h"
32 #include "itkBSplineInterpolateImageFunction.h"
33 #include "itkBSplineInterpolateImageFunctionWithLUT.h"
34 #include "itkCommand.h"
35
36 namespace clitk {
37
38   //--------------------------------------------------------------------
39   template <class TInputImage, class TOutputImage>
40   ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
41   ResampleImageWithOptionsFilter():itk::ImageToImageFilter<TInputImage, TOutputImage>() {
42     static const unsigned int dim = InputImageType::ImageDimension;
43     this->SetNumberOfRequiredInputs(1);
44     m_OutputIsoSpacing = -1;
45     m_InterpolationType = NearestNeighbor;
46     m_GaussianFilteringEnabled = true;
47     m_BSplineOrder = 3;
48     m_BLUTSamplingFactor = 20;
49     m_LastDimensionIsTime = false;
50     m_Transform =  TransformType::New();
51     if (dim == 4) m_LastDimensionIsTime = true; // by default 4D is 3D+t
52     for(unsigned int i=0; i<dim; i++) {
53       m_OutputSize[i] = 0;
54       m_OutputSpacing[i] = -1;
55       m_GaussianSigma[i] = -1;
56     }
57     m_VerboseOptions = false;
58   }
59   //--------------------------------------------------------------------
60
61
62   //--------------------------------------------------------------------
63   template <class TInputImage, class TOutputImage>
64   void 
65   ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
66   SetInput(const InputImageType * image) {
67     // Process object is not const-correct so the const casting is required.
68     this->SetNthInput(0, const_cast<InputImageType *>(image));
69   }
70   //--------------------------------------------------------------------
71   
72
73   //--------------------------------------------------------------------
74   template <class TInputImage, class TOutputImage>
75   void 
76   ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
77   GenerateInputRequestedRegion() {
78     // call the superclass's implementation of this method
79     Superclass::GenerateInputRequestedRegion();
80     
81     // get pointers to the input and output
82     InputImagePointer  inputPtr  = 
83       const_cast< TInputImage *>( this->GetInput() );
84     
85     // Request the entire input image
86     InputImageRegionType inputRegion;
87     inputRegion = inputPtr->GetLargestPossibleRegion();
88     inputPtr->SetRequestedRegion(inputRegion);
89    }
90   //--------------------------------------------------------------------
91
92
93   //--------------------------------------------------------------------
94   template <class TInputImage, class TOutputImage>
95   void 
96   ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
97   GenerateOutputInformation() { 
98     static const unsigned int dim = InputImageType::ImageDimension;
99
100     // Warning
101     if (!std::numeric_limits<InputImagePixelType>::is_signed) {
102       if ((m_InterpolationType == BSpline) || 
103           (m_InterpolationType == B_LUT)) {
104         std::cerr << "Warning : input pixel type is not signed, use bspline interpolation at your own risk ..." << std::endl;
105       }
106     }
107
108     // Get input pointer
109     InputImagePointer input = dynamic_cast<InputImageType*>(itk::ProcessObject::GetInput(0));
110      
111     // Perform default implementation
112     Superclass::GenerateOutputInformation();
113
114     // Compute sizes 
115     InputImageSpacingType inputSpacing = input->GetSpacing();
116     InputImageSizeType inputSize = input->GetLargestPossibleRegion().GetSize();
117
118     if (m_OutputIsoSpacing != -1) { // apply isoSpacing
119       for(unsigned int i=0; i<dim; i++) {
120         m_OutputSpacing[i] = m_OutputIsoSpacing;
121         m_OutputSize[i] = (int)lrint(inputSize[i]*inputSpacing[i]/m_OutputSpacing[i]);
122       }
123     }
124     else {
125       if (m_OutputSpacing[0] != -1) { // apply spacing, compute size
126         for(unsigned int i=0; i<dim; i++) {
127           m_OutputSize[i] = (int)lrint(inputSize[i]*inputSpacing[i]/m_OutputSpacing[i]);
128         }
129       }
130       else {
131         if (m_OutputSize[0] != 0) { // apply size, compute spacing
132           for(unsigned int i=0; i<dim; i++) {
133             m_OutputSpacing[i] = (double)inputSize[i]*inputSpacing[i]/(double)m_OutputSize[i];
134           }
135         }
136         else { // copy input size/spacing ... (no resampling)
137           m_OutputSize = inputSize;
138           m_OutputSpacing = inputSpacing;
139         }
140       }
141     }
142
143     // Special case for temporal image 2D+t or 3D+t
144     if (m_LastDimensionIsTime) {
145       int l = dim-1;
146       m_OutputSize[l] = inputSize[l];
147       m_OutputSpacing[l] = inputSpacing[l];
148     }
149     
150     // Set Size/Spacing
151     OutputImagePointer outputImage = this->GetOutput(0);
152     OutputImageRegionType region;
153     region.SetSize(m_OutputSize);
154     region.SetIndex(input->GetLargestPossibleRegion().GetIndex());
155     DD(input->GetLargestPossibleRegion().GetIndex());
156     outputImage->SetLargestPossibleRegion(region);
157     outputImage->SetSpacing(m_OutputSpacing);
158
159     // Init Gaussian sigma
160     if (m_GaussianSigma[0] != -1) { // Gaussian filter set by user
161       m_GaussianFilteringEnabled = true;
162     }
163     else {
164       if (m_GaussianFilteringEnabled) { // Automated sigma when downsample
165         for(unsigned int i=0; i<dim; i++) {
166           if (m_OutputSpacing[i] > inputSpacing[i]) { // downsample
167             m_GaussianSigma[i] = 0.5*m_OutputSpacing[i];// / inputSpacing[i]);
168           }
169           else m_GaussianSigma[i] = 0; // will be ignore after
170         }
171       }
172     }
173     if (m_GaussianFilteringEnabled && m_LastDimensionIsTime) {
174       m_GaussianSigma[dim-1] = 0;
175     }
176   }
177   //--------------------------------------------------------------------
178
179
180   //--------------------------------------------------------------------
181    template <class TInputImage, class TOutputImage>
182   void 
183   ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
184   GenerateData() {
185    
186     // Get input pointer
187     InputImagePointer input = dynamic_cast<InputImageType*>(itk::ProcessObject::GetInput(0));
188     static const unsigned int dim = InputImageType::ImageDimension;
189
190      // Create main Resample Image Filter
191     typedef itk::ResampleImageFilter<InputImageType,OutputImageType> FilterType;
192     typename FilterType::Pointer filter = FilterType::New();
193     filter->GraftOutput(this->GetOutput());
194 //     this->GetOutput()->Print(std::cout);
195 //     this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetLargestPossibleRegion());
196 //     this->GetOutput()->Print(std::cout);
197
198     // Print options if needed
199     if (m_VerboseOptions) {
200       std::cout << "Output Spacing = " << m_OutputSpacing << std::endl
201                 << "Output Size    = " << m_OutputSize << std::endl
202                 << "Gaussian       = " << m_GaussianFilteringEnabled << std::endl;
203       if (m_GaussianFilteringEnabled) 
204         std::cout << "Sigma          = " << m_GaussianSigma << std::endl;
205       std::cout << "Interpol       = ";
206       switch (m_InterpolationType) {
207       case NearestNeighbor: std::cout << "NearestNeighbor" << std::endl; break;
208       case Linear:          std::cout << "Linear" << std::endl; break;
209       case BSpline:         std::cout << "BSpline " << m_BSplineOrder << std::endl; break;
210       case B_LUT:           std::cout << "B-LUT " << m_BSplineOrder << " " << m_BLUTSamplingFactor << std::endl; break;
211       }
212       std::cout << "Threads        = " << this->GetNumberOfThreads() << std::endl;
213       std::cout << "LastDimIsTime  = " << m_LastDimensionIsTime << std::endl;
214     }
215
216     // Instance of the transform object to be passed to the resample
217     // filter. By default, identity transform is applied
218     filter->SetTransform(m_Transform);
219     filter->SetSize(m_OutputSize);
220     filter->SetOutputSpacing(m_OutputSpacing);
221     filter->SetOutputOrigin(input->GetOrigin());
222     filter->SetDefaultPixelValue(m_DefaultPixelValue);
223     filter->SetNumberOfThreads(this->GetNumberOfThreads()); 
224
225     // Select interpolator
226     switch (m_InterpolationType) {
227     case NearestNeighbor: 
228       {
229         typedef itk::NearestNeighborInterpolateImageFunction<InputImageType, double> InterpolatorType;     
230         typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
231         filter->SetInterpolator(interpolator);
232         break;
233       }
234     case Linear: 
235       {
236         typedef itk::LinearInterpolateImageFunction<InputImageType, double> InterpolatorType;     
237         typename InterpolatorType::Pointer interpolator =  InterpolatorType::New();
238         filter->SetInterpolator(interpolator);
239         break;
240       }
241     case BSpline: 
242       {
243         typedef itk::BSplineInterpolateImageFunction<InputImageType, double> InterpolatorType; 
244         typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
245         interpolator->SetSplineOrder(m_BSplineOrder);
246         filter->SetInterpolator(interpolator);
247       break;
248       }
249     case B_LUT: 
250       {
251         typedef itk::BSplineInterpolateImageFunctionWithLUT<InputImageType, double> InterpolatorType; 
252         typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
253         interpolator->SetSplineOrder(m_BSplineOrder);
254         interpolator->SetLUTSamplingFactor(m_BLUTSamplingFactor);
255         filter->SetInterpolator(interpolator);
256         break;
257       }
258     }
259     
260     // Initial Gaussian blurring if needed
261     typedef itk::RecursiveGaussianImageFilter<InputImageType, InputImageType> GaussianFilterType;
262     std::vector<typename GaussianFilterType::Pointer> gaussianFilters;
263     if (m_GaussianFilteringEnabled) {
264       for(unsigned int i=0; i<dim; i++) {
265         if (m_GaussianSigma[i] != 0) {
266           gaussianFilters.push_back(GaussianFilterType::New());
267           gaussianFilters[i]->SetDirection(i);
268           gaussianFilters[i]->SetOrder(GaussianFilterType::ZeroOrder);
269           gaussianFilters[i]->SetNormalizeAcrossScale(false);
270           gaussianFilters[i]->SetSigma(m_GaussianSigma[i]); // in millimeter !
271           if (gaussianFilters.size() == 1) { // first
272             gaussianFilters[0]->SetInput(input);
273           }
274           else {
275             gaussianFilters[i]->SetInput(gaussianFilters[i-1]->GetOutput());
276           }
277         }
278       }
279       if (gaussianFilters.size() > 0) {
280         filter->SetInput(gaussianFilters[gaussianFilters.size()-1]->GetOutput());
281       }
282       else filter->SetInput(input);
283     }
284     else filter->SetInput(input);
285
286     // Go ! 
287     filter->Update();
288     
289     // Set output
290     // DD("before Graft");
291     this->GraftOutput(filter->GetOutput());
292     // DD("after Graft");
293   }
294   //--------------------------------------------------------------------
295   
296 }//end clitk
297