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