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 CLITKEXTRACTBONESSFILTER_TXX
20 #define CLITKEXTRACTBONESSFILTER_TXX
23 #include "clitkImageCommon.h"
24 #include "clitkSetBackgroundImageFilter.h"
25 #include "clitkSegmentationUtils.h"
26 #include "clitkAutoCropFilter.h"
29 #include "itkBinaryThresholdImageFilter.h"
30 #include "itkConnectedComponentImageFilter.h"
31 #include "itkRelabelComponentImageFilter.h"
32 #include "itkNeighborhoodConnectedImageFilter.h"
33 #include "itkCurvatureAnisotropicDiffusionImageFilter.h"
35 //--------------------------------------------------------------------
36 template <class TInputImageType, class TOutputImageType>
37 clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
40 itk::ImageToImageFilter<TInputImageType, TOutputImageType>()
42 // Default global options
43 this->SetNumberOfRequiredInputs(1);
44 SetBackgroundValue(0); // Must be zero
45 SetForegroundValue(1);
46 SetInitialSmoothing(false);
48 SetSmoothingConductanceParameter(3.0);
49 SetSmoothingNumberOfIterations(5);
50 SetSmoothingTimeStep(0.0625);
51 SetSmoothingUseImageSpacing(false);
53 SetMinimalComponentSize(100);
54 SetUpperThreshold1(1500);
55 SetLowerThreshold1(100);
56 SetFullConnectivity(false);
58 SetUpperThreshold2(1500);
59 SetLowerThreshold2(10);
66 //--------------------------------------------------------------------
69 //--------------------------------------------------------------------
70 template <class TInputImageType, class TOutputImageType>
72 clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
73 SetInput(const TInputImageType * image)
75 this->SetNthInput(0, const_cast<TInputImageType *>(image));
77 //--------------------------------------------------------------------
80 //--------------------------------------------------------------------
81 template <class TInputImageType, class TOutputImageType>
82 template<class ArgsInfoType>
84 clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
85 SetArgsInfo(ArgsInfoType mArgsInfo)
87 SetVerboseOption_GGO(mArgsInfo);
88 SetVerboseStep_GGO(mArgsInfo);
89 SetWriteStep_GGO(mArgsInfo);
90 SetVerboseWarningOff_GGO(mArgsInfo);
92 SetInitialSmoothing_GGO(mArgsInfo);
93 SetSmoothingConductanceParameter_GGO(mArgsInfo);
94 SetSmoothingNumberOfIterations_GGO(mArgsInfo);
95 SetSmoothingTimeStep_GGO(mArgsInfo);
96 SetSmoothingUseImageSpacing_GGO(mArgsInfo);
98 SetMinimalComponentSize_GGO(mArgsInfo);
99 SetUpperThreshold1_GGO(mArgsInfo);
100 SetLowerThreshold1_GGO(mArgsInfo);
101 SetFullConnectivity_GGO(mArgsInfo);
103 SetUpperThreshold2_GGO(mArgsInfo);
104 SetLowerThreshold2_GGO(mArgsInfo);
105 SetRadius2_GGO(mArgsInfo);
106 SetSampleRate2_GGO(mArgsInfo);
107 SetAutoCrop_GGO(mArgsInfo);
109 //--------------------------------------------------------------------
112 //--------------------------------------------------------------------
113 template <class TInputImageType, class TOutputImageType>
115 clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
116 GenerateOutputInformation() {
117 // Get input pointers
118 InputImagePointer input = dynamic_cast<TInputImageType*>(itk::ProcessObject::GetInput(0));
119 // InputImagePointer input = dynamic_cast<TInputImageType*>(itk::ProcessObject::GetInput(0));
120 Superclass::GenerateOutputInformation();
121 OutputImagePointer outputImage = this->GetOutput(0);
122 outputImage->SetRegions(input->GetLargestPossibleRegion());
125 typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> InputBinarizeFilterType;
126 typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> BinarizeFilterType;
127 typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
128 typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelFilterType;
129 typedef clitk::SetBackgroundImageFilter<InternalImageType,InternalImageType, InternalImageType> SetBackgroundFilterType;
130 typedef itk::CastImageFilter<InternalImageType,OutputImageType> CastImageFilterType;
131 typedef itk::ImageFileWriter<OutputImageType> WriterType;
133 //---------------------------------
134 // Smoothing [Optional]
135 //---------------------------------
136 if (GetInitialSmoothing()) {
137 StartNewStep("Initial Smoothing");
138 typedef itk::CurvatureAnisotropicDiffusionImageFilter<InputImageType, InputImageType> FilterType;
139 typename FilterType::Pointer df = FilterType::New();
140 df->SetConductanceParameter(GetSmoothingConductanceParameter());
141 df->SetNumberOfIterations(GetSmoothingNumberOfIterations());
142 df->SetTimeStep(GetSmoothingTimeStep());
143 df->SetUseImageSpacing(GetSmoothingUseImageSpacing());
146 filtered_input = df->GetOutput();
147 StopCurrentStep<InputImageType>(filtered_input);
150 filtered_input = input;
153 //--------------------------------------------------------------------
154 //--------------------------------------------------------------------
155 StartNewStep("Initial Labeling");
156 typename InternalImageType::Pointer firstLabelImage;
158 //---------------------------------
159 // Binarize the image
160 //---------------------------------
161 typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
162 binarizeFilter->SetInput(filtered_input);
163 binarizeFilter->SetLowerThreshold(GetLowerThreshold1());
164 binarizeFilter->SetUpperThreshold(GetUpperThreshold1());
165 binarizeFilter->SetInsideValue(this->GetForegroundValue());
166 binarizeFilter->SetOutsideValue(this->GetBackgroundValue());
168 //---------------------------------
169 // Label the connected components
170 //---------------------------------
171 typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
172 connectFilter->SetInput(binarizeFilter->GetOutput());
173 connectFilter->SetBackgroundValue(this->GetBackgroundValue());
174 connectFilter->SetFullyConnected(GetFullConnectivity());
176 //---------------------------------
177 // Sort the labels according to size
178 //---------------------------------
179 typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
180 relabelFilter->SetInput(connectFilter->GetOutput());
181 relabelFilter->SetMinimumObjectSize(GetMinimalComponentSize());
183 //---------------------------------
185 //---------------------------------
186 typename BinarizeFilterType::Pointer binarizeFilter2=BinarizeFilterType::New();
187 binarizeFilter2->SetInput(relabelFilter->GetOutput());
188 binarizeFilter2->SetLowerThreshold(1);
189 binarizeFilter2->SetUpperThreshold(1);
190 binarizeFilter2->SetInsideValue(this->GetForegroundValue());
191 binarizeFilter2->SetOutsideValue(this->GetBackgroundValue());
192 binarizeFilter2->Update();
194 firstLabelImage = binarizeFilter2->GetOutput();
195 StopCurrentStep<InternalImageType>(firstLabelImage);
197 //--------------------------------------------------------------------
198 //--------------------------------------------------------------------
199 StartNewStep("Neighborhood connected filter");
200 typename InternalImageType::Pointer secondLabelImage;
202 //---------------------------------
203 //Neighborhood connected RG
204 //---------------------------------
205 typedef itk::NeighborhoodConnectedImageFilter<InputImageType, InternalImageType>
206 NeighborhoodConnectedImageFilterType;
207 typename NeighborhoodConnectedImageFilterType::Pointer neighborhoodConnectedImageFilter=
208 NeighborhoodConnectedImageFilterType::New();
211 neighborhoodConnectedImageFilter->SetLower(GetLowerThreshold2());
212 neighborhoodConnectedImageFilter->SetUpper(GetUpperThreshold2());
213 neighborhoodConnectedImageFilter->SetReplaceValue(this->GetForegroundValue());
214 neighborhoodConnectedImageFilter->SetRadius(GetRadius2());
215 neighborhoodConnectedImageFilter->SetInput(filtered_input);
217 // Seeds from label image
218 typedef itk::ImageRegionIteratorWithIndex<InternalImageType> IteratorType;
219 IteratorType it(firstLabelImage, firstLabelImage->GetLargestPossibleRegion());
220 typename InputImageType::IndexType index;
221 unsigned int counter=0;
222 while (!it.IsAtEnd())
224 if (it.Get()==this->GetForegroundValue())
228 neighborhoodConnectedImageFilter->AddSeed(index);
231 while (!it.IsAtEnd() && i< (unsigned int) GetSampleRate2())
240 neighborhoodConnectedImageFilter->Update();
241 secondLabelImage = neighborhoodConnectedImageFilter->GetOutput();
243 //--------------------------------------------------------------------
244 //--------------------------------------------------------------------
245 StartNewStep("Combine the images");
246 typedef clitk::SetBackgroundImageFilter<InternalImageType, InternalImageType, InternalImageType>
247 SetBackgroundImageFilterType;
248 typename SetBackgroundImageFilterType::Pointer setBackgroundFilter=SetBackgroundImageFilterType::New();
249 setBackgroundFilter->SetInput(firstLabelImage);
250 setBackgroundFilter->SetInput2(secondLabelImage);
251 setBackgroundFilter->SetMaskValue(this->GetForegroundValue());
252 setBackgroundFilter->SetOutsideValue(this->GetForegroundValue());
253 setBackgroundFilter->Update();
255 output = setBackgroundFilter->GetOutput();
257 //--------------------------------------------------------------------
258 //--------------------------------------------------------------------
261 StartNewStep("AutoCrop");
262 typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
263 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
264 cropFilter->SetInput(output);
265 cropFilter->SetBackgroundValue(GetBackgroundValue());
266 cropFilter->Update();
267 output = cropFilter->GetOutput();
268 StopCurrentStep<InternalImageType>(output);
269 outputImage->SetRegions(output->GetLargestPossibleRegion());
273 //--------------------------------------------------------------------
276 //--------------------------------------------------------------------
277 template <class TInputImageType, class TOutputImageType>
279 clitk::ExtractBonesFilter<TInputImageType, TOutputImageType>::
282 //--------------------------------------------------------------------
283 //--------------------------------------------------------------------
285 typedef itk::CastImageFilter<InternalImageType, OutputImageType> CastImageFilterType;
286 typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
287 caster->SetInput(output);
289 //this->SetNthOutput(0, caster->GetOutput());
290 this->GraftOutput(caster->GetOutput());
293 //--------------------------------------------------------------------
296 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX