1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
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
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.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
19 #ifndef CLITKFILLMASKFILTER_TXX
20 #define CLITKFILLMASKFILTER_TXX
22 //--------------------------------------------------------------------
23 template <class ImageType>
24 clitk::FillMaskFilter<ImageType>::FillMaskFilter():
25 itk::ImageToImageFilter<ImageType, ImageType>()
27 // Default global options
28 this->SetNumberOfRequiredInputs(1);
31 //--------------------------------------------------------------------
34 //--------------------------------------------------------------------
35 template <class ImageType>
37 clitk::FillMaskFilter<ImageType>::
40 m_Directions.push_back(dir);
42 //--------------------------------------------------------------------
45 //--------------------------------------------------------------------
46 template <class ImageType>
48 clitk::FillMaskFilter<ImageType>::
53 //--------------------------------------------------------------------
56 //--------------------------------------------------------------------
57 template <class ImageType>
58 template<class ArgsInfoType>
60 clitk::FillMaskFilter<ImageType>::
61 SetOptionsFromArgsInfo(ArgsInfoType & mArgsInfo)
64 for(uint i=0; i<mArgsInfo.dir_given; i++) {
65 AddDirection(mArgsInfo.dir_arg[i]);
68 //--------------------------------------------------------------------
71 //--------------------------------------------------------------------
72 template <class ImageType>
73 template<class ArgsInfoType>
75 clitk::FillMaskFilter<ImageType>::
76 SetOptionsToArgsInfo(ArgsInfoType & mArgsInfo)
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];
84 //--------------------------------------------------------------------
87 //--------------------------------------------------------------------
88 template <class ImageType>
90 clitk::FillMaskFilter<ImageType>::
93 InputImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
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();
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 //----------------------------------------
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;
121 typename InternalImageType::RegionType desiredRegion;
122 desiredRegion.SetSize( size2D );
123 desiredRegion.SetIndex( start2D );
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]]);
131 //----------------------------------------
132 // Run over the sliceIndexs
133 // ----------------------------------------
134 for(unsigned int sliceIndex=0; sliceIndex <size3D[m_Directions[i]]; sliceIndex++)
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();
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");
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");
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");
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");
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");
191 joinFilter->SetInput( sliceIndex, switchFilter->GetOutput());
194 // Join to a 3D image
195 joinFilter->Update();
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)
208 else if ( m_Directions[i]==1)
213 else if (m_Directions[i]==0)
218 permuteFilter->SetOrder(order);
219 permuteFilter->Update();
220 output = permuteFilter->GetOutput();
222 // Set the image direction to the input one
223 output->SetDirection(input->GetDirection());
224 output->SetOrigin(input->GetOrigin());
228 typedef itk::CastImageFilter<InternalImageType,ImageType> OutputCastImageFilterType;
229 typename OutputCastImageFilterType::Pointer outputCaster =OutputCastImageFilterType::New();
230 outputCaster->SetInput(output);
231 outputCaster->Update();
234 this->GraftOutput(outputCaster->GetOutput());
236 //--------------------------------------------------------------------
238 #endif //#define CLITKFILLMASKFILTER_TXX