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