]> Creatis software - clitk.git/blob - segmentation/clitkMorphoMathFilter.txx
add SetRadius with a single int (isotropic)
[clitk.git] / segmentation / clitkMorphoMathFilter.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
19 //--------------------------------------------------------------------
20 template<class ImageType>
21 clitk::MorphoMathFilter<ImageType>::MorphoMathFilter():
22   clitk::FilterBase(),
23   itk::ImageToImageFilter<ImageType, ImageType>()
24 {
25   this->SetNumberOfRequiredInputs(1);
26   SetBackgroundValue(0);
27   SetForegroundValue(1);
28   SetOperationType(0);
29   SizeType p;
30   p.Fill(1);
31   SetRadius(p);
32   SetBoundaryToForegroundFlag(false);
33 }
34 //--------------------------------------------------------------------
35
36
37 //--------------------------------------------------------------------
38 template<class ImageType>
39 clitk::MorphoMathFilter<ImageType>::~MorphoMathFilter()
40 {
41   // Nothing
42 }
43 //--------------------------------------------------------------------
44
45
46 //--------------------------------------------------------------------
47 template<class ImageType>
48 void clitk::MorphoMathFilter<ImageType>::
49 SetRadiusInMM(PointType & p)
50 {
51   m_RadiusInMM = p;
52   m_RadiusInMMIsSet = true;
53   m_RadiusIsSet = false;
54 }
55 //--------------------------------------------------------------------
56
57
58 //--------------------------------------------------------------------
59 template<class ImageType>
60 void clitk::MorphoMathFilter<ImageType>::
61 SetRadius(SizeType & p)
62 {
63   m_Radius = p;
64   m_RadiusIsSet = true;
65   m_RadiusInMMIsSet = false;
66 }
67 //--------------------------------------------------------------------
68
69
70 //--------------------------------------------------------------------
71 template<class ImageType>
72 void clitk::MorphoMathFilter<ImageType>::
73 SetRadius(int r)
74 {
75   for(uint i=0; i<ImageType::ImageDimension; i++)
76     m_Radius[i] = r;
77   SetRadius(m_Radius);
78 }
79 //--------------------------------------------------------------------
80
81
82 //--------------------------------------------------------------------
83 template<class ImageType>
84 void clitk::MorphoMathFilter<ImageType>::
85 SetOperationType(int type)
86 {
87   switch (type) {
88   case 0: m_OperationType = Erode; return;
89   case 1: m_OperationType = Dilate; return;
90   case 2: m_OperationType = Open; return;
91   case 3: m_OperationType = Close; return;
92   case 4: m_OperationType = CondErode; return;
93   case 5: m_OperationType = CondDilate; return;
94   default: clitkExceptionMacro("Operation type must be between 0-5 (0=Erode, 1=Dilate, 2=Close (erode(dilate(x))), 3=Open (dilate(erode(x))), 4=CondErode, 5=CondDilate)");
95   }    
96 }
97 //--------------------------------------------------------------------
98
99
100 //--------------------------------------------------------------------
101 template <class ImageType>
102 void 
103 clitk::MorphoMathFilter<ImageType>::
104 GenerateInputRequestedRegion() 
105 {
106   // Call default
107   itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
108   // Get input pointers and set requested region to common region
109   ImagePointer input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
110   input1->SetRequestedRegion(input1->GetLargestPossibleRegion());
111 }
112 //--------------------------------------------------------------------
113
114
115 //--------------------------------------------------------------------
116 template <class ImageType>
117 void 
118 clitk::MorphoMathFilter<ImageType>::
119 GenerateOutputInformation() 
120 {
121   //---------------------------------
122   // Define the images
123   //---------------------------------
124   ImagePointer m_input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
125
126   //---------------------------------
127   // Cast into internalimagetype
128   //---------------------------------
129   typedef itk::CastImageFilter<ImageType, InternalImageType> InputCastImageFilterType;
130   typename InputCastImageFilterType::Pointer caster = InputCastImageFilterType::New();
131   caster->SetInput(m_input);
132   caster->Update();
133   input =caster->GetOutput();
134   
135   //---------------------------------
136   // Compute the radius in pixel
137   //---------------------------------
138   if (m_RadiusInMMIsSet) {
139     for(uint i=0; i<ImageType::ImageDimension; i++) {
140       m_Radius[i] = (uint)lrint(m_RadiusInMM[i]/input->GetSpacing()[i]);
141     }
142   }
143
144   //---------------------------------
145   // Extend the image if needed
146   //---------------------------------
147   if (GetExtendSupportFlag()) {
148     typedef itk::ConstantPadImageFilter<InternalImageType, InternalImageType> PadFilterType;
149     typename PadFilterType::Pointer padFilter = PadFilterType::New();
150     padFilter->SetInput(input);
151     typename ImageType::SizeType lower;
152     typename ImageType::SizeType upper;
153     for(uint i=0; i<3; i++) {
154       lower[i] = upper[i] = 2*(m_Radius[i]+1);
155     }
156     padFilter->SetPadLowerBound(lower);
157     padFilter->SetPadUpperBound(upper);
158     padFilter->Update();
159     if (GetVerboseFlag()) std::cout << "Extend the image to 2x " << lower << std::endl;
160     input = padFilter->GetOutput();
161   }
162   
163   // Set output size
164   ImagePointer outputImage = this->GetOutput(0);
165   outputImage->SetRegions(input->GetLargestPossibleRegion());
166 }
167 //--------------------------------------------------------------------
168
169
170 //--------------------------------------------------------------------
171 template <class ImageType>
172 void 
173 clitk::MorphoMathFilter<ImageType>::
174 GenerateData() 
175 {
176   //---------------------------------
177   // Build kernel
178   //---------------------------------
179   typedef itk::BinaryBallStructuringElement<PixelType,ImageDimension> KernelType;
180   KernelType structuringElement;
181   if (GetVerboseFlag()) {
182     std::cout << "Radius in pixel : " << m_Radius << std::endl;
183   }
184   structuringElement.SetRadius(m_Radius);
185   structuringElement.CreateStructuringElement();
186
187   //---------------------------------
188   // Switch according to operation type
189   //---------------------------------
190   typedef itk::ImageToImageFilter<InternalImageType, InternalImageType> ImageFilterType;
191   typename ImageFilterType::Pointer filter; 
192   switch(m_OperationType)
193     {
194     case Erode: {
195       typedef itk::BinaryErodeImageFilter<InternalImageType, InternalImageType , KernelType> FilterType;
196       typename FilterType::Pointer m = FilterType::New();
197       m->SetBackgroundValue(this->GetBackgroundValue());
198       m->SetForegroundValue(this->GetForegroundValue());
199       m->SetBoundaryToForeground(GetBoundaryToForegroundFlag());
200       m->SetKernel(structuringElement);
201       
202       filter=m;
203       if (GetVerboseFlag()) std::cout<<"Using the erode filter..."<<std::endl;
204       break;
205     }
206
207     case Dilate:
208       {
209         typedef itk::BinaryDilateImageFilter<InternalImageType, InternalImageType , KernelType> FilterType;
210         typename FilterType::Pointer m = FilterType::New();
211         m->SetBackgroundValue(this->GetBackgroundValue());
212         m->SetForegroundValue(this->GetForegroundValue());
213         m->SetBoundaryToForeground(GetBoundaryToForegroundFlag());
214         m->SetKernel(structuringElement);
215
216         filter=m;
217         if (GetVerboseFlag()) std::cout<<"Using the dilate filter..."<<std::endl;
218         break;
219       }
220
221     case Close:
222       {
223         typedef itk::BinaryMorphologicalClosingImageFilter<InternalImageType, InternalImageType , KernelType> FilterType;
224         typename FilterType::Pointer m = FilterType::New();
225         m->SetForegroundValue(this->GetForegroundValue());
226         m->SetSafeBorder(GetBoundaryToForegroundFlag());
227         m->SetKernel(structuringElement);
228
229         filter=m;
230         if (GetVerboseFlag()) std::cout<<"Using the closing filter..."<<std::endl;
231         break;
232       }
233
234     case Open:
235       {
236         typedef itk::BinaryMorphologicalOpeningImageFilter<InternalImageType, InternalImageType , KernelType> FilterType;
237         typename FilterType::Pointer m = FilterType::New();
238         m->SetBackgroundValue(this->GetBackgroundValue());
239         m->SetForegroundValue(this->GetForegroundValue());
240         m->SetKernel(structuringElement);
241
242         filter=m;
243         if (GetVerboseFlag()) std::cout<<"Using the opening filter..."<<std::endl;
244         break;
245       }
246
247     case CondErode:
248       {
249         typedef clitk::ConditionalBinaryErodeImageFilter<InternalImageType, InternalImageType , KernelType> FilterType;
250         typename FilterType::Pointer m = FilterType::New();
251         m->SetBackgroundValue(this->GetBackgroundValue());
252         m->SetForegroundValue(this->GetForegroundValue());
253         m->SetBoundaryToForeground(GetBoundaryToForegroundFlag());
254         m->SetKernel(structuringElement);
255           
256         filter=m;
257         if (GetVerboseFlag()) std::cout<<"Using the conditional erode filter..."<<std::endl;
258         break;
259       }
260
261     case CondDilate:
262       {
263         typedef clitk::ConditionalBinaryDilateImageFilter<InternalImageType, InternalImageType , KernelType> FilterType;
264         typename FilterType::Pointer m = FilterType::New();
265         m->SetBackgroundValue(this->GetBackgroundValue());
266         m->SetForegroundValue(this->GetForegroundValue());
267         m->SetBoundaryToForeground(GetBoundaryToForegroundFlag());
268         m->SetKernel(structuringElement);
269           
270         filter=m;
271         if (GetVerboseFlag()) std::cout<<"Using the conditional dilate filter..."<<std::endl;
272         break;
273       }
274
275     }
276   
277
278   //---------------------------------
279   // Execute the filter
280   //---------------------------------
281   filter->SetInput(input);
282   filter->Update();
283
284   //---------------------------------
285   // Write the output
286   //---------------------------------
287   typedef itk::CastImageFilter< InternalImageType, ImageType > OutputCastImageFilterType;
288   typename OutputCastImageFilterType::Pointer oCaster = OutputCastImageFilterType::New();
289   oCaster->SetInput(filter->GetOutput());
290   oCaster->Update();
291   this->SetNthOutput(0, oCaster->GetOutput());
292 }
293 //--------------------------------------------------------------------
294
295