]> Creatis software - clitk.git/blob - segmentation/clitkFillMaskFilter.txx
new FillMask with itk filter
[clitk.git] / segmentation / clitkFillMaskFilter.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 #ifndef CLITKFILLMASKFILTER_TXX
20 #define CLITKFILLMASKFILTER_TXX
21
22 //--------------------------------------------------------------------
23 template <class ImageType>
24 clitk::FillMaskFilter<ImageType>::FillMaskFilter():
25   itk::ImageToImageFilter<ImageType, ImageType>()
26 {
27   // Default global options
28   this->SetNumberOfRequiredInputs(1);
29   ResetDirections();
30   AddDirection(2);
31   AddDirection(1);
32   AddDirection(0);
33 }
34 //--------------------------------------------------------------------
35
36
37 //--------------------------------------------------------------------
38 template <class ImageType>
39 void 
40 clitk::FillMaskFilter<ImageType>::
41 AddDirection(int dir)
42 {
43   m_Directions.push_back(dir);
44 }
45 //--------------------------------------------------------------------
46
47
48 //--------------------------------------------------------------------
49 template <class ImageType>
50 void 
51 clitk::FillMaskFilter<ImageType>::
52 ResetDirections()
53 {
54   m_Directions.clear();
55 }
56 //--------------------------------------------------------------------
57
58
59 //--------------------------------------------------------------------
60 template <class ImageType>
61 template<class ArgsInfoType>
62 void 
63 clitk::FillMaskFilter<ImageType>::
64 SetOptionsFromArgsInfo(ArgsInfoType & mArgsInfo)
65 {
66   ResetDirections();
67   for(uint i=0; i<mArgsInfo.dir_given; i++) {
68     AddDirection(mArgsInfo.dir_arg[i]);
69   }
70 }
71 //--------------------------------------------------------------------
72
73
74 //--------------------------------------------------------------------
75 template <class ImageType>
76 template<class ArgsInfoType>
77 void 
78 clitk::FillMaskFilter<ImageType>::
79 SetOptionsToArgsInfo(ArgsInfoType & mArgsInfo)
80 {
81   mArgsInfo.dir_arg = new int[m_Directions.size()];
82   mArgsInfo.dir_given = m_Directions.size();
83   for(uint i=0; i<mArgsInfo.dir_given; i++) {
84     mArgsInfo.dir_arg[i] = m_Directions[i];
85   }
86 }
87 //--------------------------------------------------------------------
88
89
90 //--------------------------------------------------------------------
91 template <class ImageType>
92 void 
93 clitk::FillMaskFilter<ImageType>::
94 GenerateData() 
95 {
96   InputImagePointer input  = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
97
98   // Cast 
99   typedef int InternalPixelType;
100   typedef itk::Image<InternalPixelType, ImageType::ImageDimension> InternalImageType;
101   typedef itk::CastImageFilter<ImageType,InternalImageType> InputCastImageFilterType;
102   typename InputCastImageFilterType::Pointer inputCaster = InputCastImageFilterType::New();
103   inputCaster->SetInput(input);
104   inputCaster->Update();
105
106   //---------------------------------------- 
107   // Loop over directions    
108   //---------------------------------------- 
109   typename InternalImageType::Pointer output = inputCaster->GetOutput();
110   for (unsigned int i=0; i<m_Directions.size();i++) {
111     DD(i);
112     //---------------------------------------- 
113     // Fill the holes of a mask in 2D
114     //----------------------------------------
115         
116     // We define the region to be extracted.
117     typedef  itk::Image<InternalPixelType, ImageType::ImageDimension-1> ImageSliceType;
118     typedef  itk::Image<InternalPixelType, ImageType::ImageDimension-1> MaskSliceType;
119     typename InternalImageType::RegionType region3D = input->GetLargestPossibleRegion();
120     typename InternalImageType::RegionType::SizeType size3D = region3D.GetSize();
121     typename InternalImageType::RegionType::SizeType size2D = size3D;
122     size2D[m_Directions[i]]=0;
123     typename InternalImageType::IndexType start2D; 
124     start2D.Fill(0);
125     typename InternalImageType::RegionType desiredRegion;
126     desiredRegion.SetSize( size2D );
127     desiredRegion.SetIndex( start2D );
128     
129     // Extract and Join 
130     typedef itk::ExtractImageFilter<InternalImageType, ImageSliceType> ExtractImageFilterType;
131     typedef itk::JoinSeriesImageFilter<ImageSliceType, InternalImageType> JoinSeriesFilterType;
132     typename JoinSeriesFilterType::Pointer joinFilter=JoinSeriesFilterType::New();
133     joinFilter->SetSpacing(input->GetSpacing()[m_Directions[i]]);
134       
135     //---------------------------------------- 
136     // Run over the sliceIndexs
137     // ----------------------------------------
138     for(unsigned int sliceIndex=0; sliceIndex <size3D[m_Directions[i]]; sliceIndex++)
139       {
140         //---------------------------------------- 
141         // Extract mask sliceIndex
142         //----------------------------------------
143         typename ExtractImageFilterType::Pointer extractFilter=ExtractImageFilterType::New();
144         extractFilter->SetInput(output);
145         start2D[m_Directions[i]]=sliceIndex;
146         desiredRegion.SetIndex( start2D );
147         extractFilter->SetExtractionRegion( desiredRegion );
148         extractFilter->Update( );
149         typename ImageSliceType::Pointer slice= extractFilter->GetOutput();
150         
151         // Binarize the image (Before: OBJECT!=0, rest=0, After: object=1, rest=0 )
152         typedef itk::BinaryThresholdImageFilter<ImageSliceType,ImageSliceType> BinarizeFilterType;
153         typename BinarizeFilterType::Pointer binarizeFilter=BinarizeFilterType::New();
154         binarizeFilter->SetInput(slice);
155         binarizeFilter->SetUpperThreshold(0);
156         binarizeFilter->SetOutsideValue(0);
157         binarizeFilter->SetInsideValue(1);
158         // writeImage<ImageSliceType>(binarizeFilter->GetOutput(),"/home/jef/tmp/input.mhd");
159         
160         // Perform connected labelling on the slice (body+air=0 )
161         typedef itk::ConnectedComponentImageFilter<ImageSliceType, ImageSliceType> ConnectFilterType;
162         typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
163         connectFilter->SetInput(binarizeFilter->GetOutput());
164         connectFilter->SetBackgroundValue(0);
165         connectFilter->SetFullyConnected(false);
166         //connectFilter->Update();
167         //writeImage<ImageSliceType>(connectFilter->GetOutput(),"/home/jef/tmp/connect.mhd");
168         
169         // Sort the labels
170         typedef itk::RelabelComponentImageFilter<ImageSliceType, ImageSliceType> RelabelFilterType;
171         typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
172         relabelFilter->SetInput(connectFilter->GetOutput());
173         //relabelFilter->Update();
174         //writeImage<ImageSliceType>(relabelFilter->GetOutput(),"/home/jef/tmp/label.mhd");     
175         
176         // Keep the first
177         typedef itk::ThresholdImageFilter<ImageSliceType> ThresholdFilterType;
178         typename ThresholdFilterType::Pointer thresholdFilter=ThresholdFilterType::New();
179         thresholdFilter->SetInput(relabelFilter->GetOutput());
180         thresholdFilter->SetUpper(1);
181         thresholdFilter->SetOutsideValue(0);
182         // thresholdFilter->Update();
183         // writeImage<ImageSliceType>(thresholdFilter->GetOutput(),"/home/jef/tmp/bin.mhd");    
184         
185         // Invert the labels (lung 1, rest 0)
186         typename BinarizeFilterType::Pointer switchFilter=BinarizeFilterType::New();
187         switchFilter->SetInput(thresholdFilter->GetOutput());
188         switchFilter->SetUpperThreshold(0);
189         switchFilter->SetOutsideValue(0);
190         switchFilter->SetInsideValue(1);
191         switchFilter->Update();
192         //writeImage<ImageSliceType>(switchFilter->GetOutput(),"/home/jef/tmp/inv_bin.mhd");    
193         
194         //Join
195         joinFilter->SetInput( sliceIndex, switchFilter->GetOutput());
196       }
197     
198     // Join to a 3D image       
199     std::cout<<"Joining the slices..."<<std::endl;
200     joinFilter->Update();
201     
202     // Permute the axes to reset to orientation
203     typedef itk::PermuteAxesImageFilter<InternalImageType> PermuteFilterType;
204     typename PermuteFilterType::Pointer permuteFilter=PermuteFilterType::New();
205     permuteFilter->SetInput(joinFilter->GetOutput());
206     typename PermuteFilterType::PermuteOrderArrayType order;
207     order[m_Directions[i]]=2;
208     if( m_Directions[i]==2)
209       {
210         order[0]=0;
211         order[1]=1;
212       }
213     else if ( m_Directions[i]==1)
214       {
215         order[0]=0;
216         order[2]=1;
217       }
218     else if (m_Directions[i]==0)
219       {
220         order[1]=0;
221         order[2]=1;
222       }
223     permuteFilter->SetOrder(order);
224     permuteFilter->Update();
225     output = permuteFilter->GetOutput();
226     
227     // Set the image direction to the input one
228     output->SetDirection(input->GetDirection());
229     output->SetOrigin(input->GetOrigin());
230   }
231   
232   writeImage<InternalImageType>(output, "toto.mhd");
233   
234   // Cast
235   DD("cast");
236   typedef itk::CastImageFilter<InternalImageType,ImageType> OutputCastImageFilterType;
237   typename OutputCastImageFilterType::Pointer outputCaster =OutputCastImageFilterType::New();
238   outputCaster->SetInput(output);
239   outputCaster->Update();
240   
241   // Output
242   DD("Graft");
243   this->GraftOutput(outputCaster->GetOutput());
244 }
245 //--------------------------------------------------------------------
246
247 #endif //#define CLITKFILLMASKFILTER_TXX