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://www.centreleonberard.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 ===========================================================================*/
18 #ifndef clitkDecomposeThroughErosionImageFilter_txx
19 #define clitkDecomposeThroughErosionImageFilter_txx
21 /* =================================================
22 * @file clitkDecomposeThroughErosionImageFilter.txx
28 ===================================================*/
34 //-------------------------------------------------------------------
35 // Update with the number of dimensions
36 //-------------------------------------------------------------------
37 template<class InputImageType, class OutputImageType>
38 DecomposeThroughErosionImageFilter<InputImageType, OutputImageType>::DecomposeThroughErosionImageFilter()
45 m_ErosionPaddingValue=static_cast<OutputPixelType>(-1);
46 for (unsigned int i=0; i<InputImageDimension; i++)
48 m_NumberOfNewLabels=1;
49 m_FullyConnected=true;
50 m_MinimumObjectSize=10;
51 m_MinimumNumberOfIterations=1;
55 //-------------------------------------------------------------------
56 // Update with the number of dimensions and the pixeltype
57 //-------------------------------------------------------------------
58 template<class InputImageType, class OutputImageType>
60 DecomposeThroughErosionImageFilter<InputImageType, OutputImageType>::GenerateData()
63 //---------------------------------
65 //---------------------------------
68 typedef itk::Image<InternalPixelType, InputImageDimension> InternalImageType;
71 typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> InputBinaryThresholdImageFilter;
72 typedef itk::BinaryBallStructuringElement<InputPixelType,InputImageDimension > KernelType;
73 typedef itk::BinaryErodeImageFilter<InternalImageType, InternalImageType , KernelType> BinaryErodeImageFilterType;
74 typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> BinaryThresholdImageFilterType;
75 typedef itk::StatisticsImageFilter<InternalImageType> StatisticsImageFilterType;
76 typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
77 typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelImageFilterType;
78 typedef clitk::SetBackgroundImageFilter<InternalImageType, InternalImageType, InternalImageType> SetBackgroundImageFilterType;
80 //---------------------------------
82 //---------------------------------
83 typename InputBinaryThresholdImageFilter::Pointer inputBinarizer=InputBinaryThresholdImageFilter::New();
84 inputBinarizer->SetInput(this->GetInput());
85 inputBinarizer->SetLowerThreshold(m_Lower);
86 inputBinarizer->SetUpperThreshold(m_Upper);
87 inputBinarizer ->SetInsideValue(m_Inside);
88 inputBinarizer ->SetOutsideValue(m_Outside);
89 if(m_Verbose) std::cout<<"Binarizing the input..."<<std::endl;
90 inputBinarizer->Update();
92 //---------------------------------
94 //---------------------------------
95 typename ConnectFilterType::Pointer inputConnectFilter=ConnectFilterType::New();
96 inputConnectFilter->SetInput(inputBinarizer->GetOutput());
97 inputConnectFilter->SetBackgroundValue(0);
98 inputConnectFilter->SetFullyConnected(m_FullyConnected);
99 if(m_Verbose) std::cout<<"Labelling the connected components..."<<std::endl;
100 // inputConnectFilter->Update();
102 //---------------------------------
103 // Count the initial labels
104 //---------------------------------
105 typename StatisticsImageFilterType::Pointer inputStatisticsImageFilter=StatisticsImageFilterType::New();
106 inputStatisticsImageFilter->SetInput(inputConnectFilter->GetOutput());
107 if(m_Verbose) std::cout<<"Counting the initial labels..."<<std::endl;
108 inputStatisticsImageFilter->Update();
109 unsigned int initialNumberOfLabels= inputStatisticsImageFilter->GetMaximum();
110 if(m_Verbose) std::cout<<"The input contained "<<initialNumberOfLabels<<" disctictive label(s)..."<<std::endl;
111 if(m_Verbose) std::cout<<"Performing erosions till at least "<<initialNumberOfLabels+m_NumberOfNewLabels<<" distinctive labels are counted..."<<std::endl;
113 //---------------------------------
114 // Structuring element
115 //---------------------------------
116 KernelType structuringElement;
117 structuringElement.SetRadius(m_Radius);
118 structuringElement.CreateStructuringElement();
120 //---------------------------------
121 // Repeat while not decomposed
122 //---------------------------------
123 typename InternalImageType::Pointer current=inputBinarizer->GetOutput();
124 typename InternalImageType::Pointer output=inputBinarizer->GetOutput();
125 unsigned int iteration=0;
126 unsigned int max =initialNumberOfLabels;
128 while ( (iteration < m_MinimumNumberOfIterations) || ( (max< initialNumberOfLabels + m_NumberOfNewLabels ) && (iteration<100 ) ) )
132 if(m_Verbose) std::cout<<"Eroding image (iteration "<<iteration<<")..."<<std::endl;
134 //---------------------------------
136 //---------------------------------
137 typename BinaryErodeImageFilterType::Pointer erosionFilter=BinaryErodeImageFilterType::New();
138 erosionFilter->SetInput (current);
139 erosionFilter->SetForegroundValue (1);
140 erosionFilter->SetBackgroundValue (-1);
141 erosionFilter->SetBoundaryToForeground(false);
142 erosionFilter->SetKernel(structuringElement);
143 erosionFilter->Update();
144 current=erosionFilter->GetOutput();
146 //---------------------------------
147 // Binarize (remove -1)
148 //---------------------------------
149 typename BinaryThresholdImageFilterType::Pointer binarizer=BinaryThresholdImageFilterType::New();
150 binarizer->SetInput(erosionFilter->GetOutput());
151 binarizer->SetLowerThreshold(1);
152 binarizer->SetUpperThreshold(1);
153 binarizer ->SetInsideValue(1);
154 binarizer ->SetOutsideValue(0);
155 if(m_Verbose) std::cout<<"Binarizing the eroded image..."<<std::endl;
156 //binarizer->Update();
159 //---------------------------------
160 // ReLabel the connected components
161 //---------------------------------
162 typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
163 connectFilter->SetInput(binarizer->GetOutput());
164 connectFilter->SetBackgroundValue(0);
165 connectFilter->SetFullyConnected(m_FullyConnected);
166 if(m_Verbose) std::cout<<"Labelling the connected components..."<<std::endl;
167 //connectFilter->Update();
169 //---------------------------------
171 //---------------------------------
172 typename RelabelImageFilterType::Pointer relabelFilter=RelabelImageFilterType::New();
173 relabelFilter->SetInput(connectFilter->GetOutput());
174 relabelFilter->SetMinimumObjectSize(m_MinimumObjectSize);
175 //relabelFilter->Update();
178 //---------------------------------
180 //---------------------------------
181 typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
182 statisticsImageFilter->SetInput(relabelFilter->GetOutput());
183 statisticsImageFilter->Update();
184 max= statisticsImageFilter->GetMaximum();
185 if(m_Verbose) std::cout<<"Counted "<<max<<" label (s) larger then "<<m_MinimumObjectSize<<" voxels..."<<std::endl;
186 output=statisticsImageFilter->GetOutput();
193 //---------------------------------
194 // Binarize current (remove -1)
195 //---------------------------------
196 typename BinaryThresholdImageFilterType::Pointer binarizer=BinaryThresholdImageFilterType::New();
197 binarizer->SetInput(current);
198 binarizer->SetLowerThreshold(1);
199 binarizer->SetUpperThreshold(1);
200 binarizer ->SetInsideValue(1);
201 binarizer ->SetOutsideValue(0);
202 if(m_Verbose) std::cout<<"Binarizing the eroded image..."<<std::endl;
203 //binarizer->Update();
205 //---------------------------------
206 // ReLabel the connected components
207 //---------------------------------
208 typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
209 connectFilter->SetInput(binarizer->GetOutput());
210 connectFilter->SetBackgroundValue(0);
211 connectFilter->SetFullyConnected(m_FullyConnected);
212 if(m_Verbose) std::cout<<"Labelling the connected components..."<<std::endl;
213 connectFilter->Update();
215 //---------------------------------
217 //---------------------------------
218 typename RelabelImageFilterType::Pointer relabelFilter=RelabelImageFilterType::New();
219 relabelFilter->SetInput(connectFilter->GetOutput());
220 //relabelFilter->SetMinimumObjectSize(m_MinimumObjectSize); // Preserve all intensities
221 //relabelFilter->Update();
223 //---------------------------------
224 // Set -1 to padding value
225 //---------------------------------
226 typename SetBackgroundImageFilterType::Pointer setBackgroundFilter =SetBackgroundImageFilterType::New();
227 setBackgroundFilter->SetInput(relabelFilter->GetOutput());
228 setBackgroundFilter->SetInput2(current);
229 setBackgroundFilter->SetMaskValue(-1);
230 setBackgroundFilter->SetOutsideValue(m_ErosionPaddingValue);
231 if(m_Verbose) std::cout<<"Setting the eroded region to "<<m_ErosionPaddingValue<<"..."<<std::endl;
233 //---------------------------------
235 //---------------------------------
236 typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
237 typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
238 caster->SetInput(setBackgroundFilter->GetOutput());
241 //---------------------------------
243 //---------------------------------
244 this->SetNthOutput(0, caster->GetOutput());
250 #endif //#define clitkDecomposeThroughErosionImageFilter_txx