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>
37 clitk::ExtractBonesFilter<TInputImageType>::
40 clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
41 itk::ImageToImageFilter<TInputImageType, MaskImageType>()
43 // Default global options
44 this->SetNumberOfRequiredInputs(1);
45 SetBackgroundValue(0); // Must be zero
46 SetForegroundValue(1);
47 SetInitialSmoothing(false);
49 SetSmoothingConductanceParameter(3.0);
50 SetSmoothingNumberOfIterations(5);
51 SetSmoothingTimeStep(0.0625);
52 SetSmoothingUseImageSpacing(false);
54 SetMinimalComponentSize(100);
55 SetUpperThreshold1(1500);
56 SetLowerThreshold1(100);
57 SetFullConnectivity(false);
59 SetUpperThreshold2(1500);
60 SetLowerThreshold2(10);
67 //--------------------------------------------------------------------
70 //--------------------------------------------------------------------
71 template <class TInputImageType>
73 clitk::ExtractBonesFilter<TInputImageType>::
74 SetInput(const TInputImageType * image)
76 this->SetNthInput(0, const_cast<TInputImageType *>(image));
78 //--------------------------------------------------------------------
81 //--------------------------------------------------------------------
82 template <class TInputImageType>
83 template<class ArgsInfoType>
85 clitk::ExtractBonesFilter<TInputImageType>::
86 SetArgsInfo(ArgsInfoType mArgsInfo)
88 SetVerboseOption_GGO(mArgsInfo);
89 SetVerboseStep_GGO(mArgsInfo);
90 SetWriteStep_GGO(mArgsInfo);
91 SetVerboseWarningOff_GGO(mArgsInfo);
93 SetOutputBonesFilename_GGO(mArgsInfo);
95 SetInitialSmoothing_GGO(mArgsInfo);
96 SetSmoothingConductanceParameter_GGO(mArgsInfo);
97 SetSmoothingNumberOfIterations_GGO(mArgsInfo);
98 SetSmoothingTimeStep_GGO(mArgsInfo);
99 SetSmoothingUseImageSpacing_GGO(mArgsInfo);
101 SetMinimalComponentSize_GGO(mArgsInfo);
102 SetUpperThreshold1_GGO(mArgsInfo);
103 SetLowerThreshold1_GGO(mArgsInfo);
104 SetFullConnectivity_GGO(mArgsInfo);
106 SetUpperThreshold2_GGO(mArgsInfo);
107 SetLowerThreshold2_GGO(mArgsInfo);
108 SetRadius2_GGO(mArgsInfo);
109 SetSampleRate2_GGO(mArgsInfo);
110 SetAutoCrop_GGO(mArgsInfo);
112 SetAFDBFilename_GGO(mArgsInfo);
114 //--------------------------------------------------------------------
117 //--------------------------------------------------------------------
118 template <class TInputImageType>
120 clitk::ExtractBonesFilter<TInputImageType>::
121 GenerateOutputInformation() {
123 // Get input pointers
124 InputImagePointer input = dynamic_cast<TInputImageType*>(itk::ProcessObject::GetInput(0));
125 Superclass::GenerateOutputInformation();
126 MaskImagePointer outputImage = this->GetOutput(0);
127 outputImage->SetRegions(input->GetLargestPossibleRegion());
133 typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> InputBinarizeFilterType;
134 typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> BinarizeFilterType;
135 typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
136 typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelFilterType;
137 typedef clitk::SetBackgroundImageFilter<InternalImageType,InternalImageType, InternalImageType> SetBackgroundFilterType;
138 typedef itk::CastImageFilter<InternalImageType,MaskImageType> CastImageFilterType;
139 typedef itk::ImageFileWriter<MaskImageType> WriterType;
141 //---------------------------------
142 // Smoothing [Optional]
143 //---------------------------------
144 if (GetInitialSmoothing()) {
145 StartNewStep("Initial Smoothing");
146 typedef itk::CurvatureAnisotropicDiffusionImageFilter<InputImageType, InputImageType> FilterType;
147 typename FilterType::Pointer df = FilterType::New();
148 df->SetConductanceParameter(GetSmoothingConductanceParameter());
149 df->SetNumberOfIterations(GetSmoothingNumberOfIterations());
150 df->SetTimeStep(GetSmoothingTimeStep());
151 df->SetUseImageSpacing(GetSmoothingUseImageSpacing());
154 filtered_input = df->GetOutput();
155 StopCurrentStep<InputImageType>(filtered_input);
158 filtered_input = input;
161 //--------------------------------------------------------------------
162 //--------------------------------------------------------------------
163 StartNewStep("Initial Labeling");
164 typename InternalImageType::Pointer firstLabelImage;
166 //---------------------------------
167 // Binarize the image
168 //---------------------------------
169 typename InputBinarizeFilterType::Pointer binarizeFilter=InputBinarizeFilterType::New();
170 binarizeFilter->SetInput(filtered_input);
171 binarizeFilter->SetLowerThreshold(GetLowerThreshold1());
172 binarizeFilter->SetUpperThreshold(GetUpperThreshold1());
173 binarizeFilter->SetInsideValue(this->GetForegroundValue());
174 binarizeFilter->SetOutsideValue(this->GetBackgroundValue());
176 //---------------------------------
177 // Label the connected components
178 //---------------------------------
179 typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
180 connectFilter->SetInput(binarizeFilter->GetOutput());
181 connectFilter->SetBackgroundValue(this->GetBackgroundValue());
182 connectFilter->SetFullyConnected(GetFullConnectivity());
184 //---------------------------------
185 // Sort the labels according to size
186 //---------------------------------
187 typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
188 relabelFilter->SetInput(connectFilter->GetOutput());
189 relabelFilter->SetMinimumObjectSize(GetMinimalComponentSize());
191 //---------------------------------
193 //---------------------------------
194 typename BinarizeFilterType::Pointer binarizeFilter2=BinarizeFilterType::New();
195 binarizeFilter2->SetInput(relabelFilter->GetOutput());
196 binarizeFilter2->SetLowerThreshold(1);
197 binarizeFilter2->SetUpperThreshold(1);
198 binarizeFilter2->SetInsideValue(this->GetForegroundValue());
199 binarizeFilter2->SetOutsideValue(this->GetBackgroundValue());
200 binarizeFilter2->Update();
202 firstLabelImage = binarizeFilter2->GetOutput();
203 StopCurrentStep<InternalImageType>(firstLabelImage);
205 //--------------------------------------------------------------------
206 //--------------------------------------------------------------------
207 StartNewStep("Neighborhood connected filter");
208 typename InternalImageType::Pointer secondLabelImage;
210 //---------------------------------
211 //Neighborhood connected RG
212 //---------------------------------
213 typedef itk::NeighborhoodConnectedImageFilter<InputImageType, InternalImageType>
214 NeighborhoodConnectedImageFilterType;
215 typename NeighborhoodConnectedImageFilterType::Pointer neighborhoodConnectedImageFilter=
216 NeighborhoodConnectedImageFilterType::New();
219 neighborhoodConnectedImageFilter->SetLower(GetLowerThreshold2());
220 neighborhoodConnectedImageFilter->SetUpper(GetUpperThreshold2());
221 neighborhoodConnectedImageFilter->SetReplaceValue(this->GetForegroundValue());
222 neighborhoodConnectedImageFilter->SetRadius(GetRadius2());
223 neighborhoodConnectedImageFilter->SetInput(filtered_input);
225 // Seeds from label image
226 typedef itk::ImageRegionIteratorWithIndex<InternalImageType> IteratorType;
227 IteratorType it(firstLabelImage, firstLabelImage->GetLargestPossibleRegion());
228 typename InputImageType::IndexType index;
229 unsigned int counter=0;
230 while (!it.IsAtEnd())
232 if (it.Get()==this->GetForegroundValue())
236 neighborhoodConnectedImageFilter->AddSeed(index);
239 while (!it.IsAtEnd() && i< (unsigned int) GetSampleRate2())
248 neighborhoodConnectedImageFilter->Update();
249 secondLabelImage = neighborhoodConnectedImageFilter->GetOutput();
251 //--------------------------------------------------------------------
252 //--------------------------------------------------------------------
253 StartNewStep("Combine the images");
254 typedef clitk::SetBackgroundImageFilter<InternalImageType, InternalImageType, InternalImageType>
255 SetBackgroundImageFilterType;
256 typename SetBackgroundImageFilterType::Pointer setBackgroundFilter=SetBackgroundImageFilterType::New();
257 setBackgroundFilter->SetInput(firstLabelImage);
258 setBackgroundFilter->SetInput2(secondLabelImage);
259 setBackgroundFilter->SetMaskValue(this->GetForegroundValue());
260 setBackgroundFilter->SetOutsideValue(this->GetForegroundValue());
261 setBackgroundFilter->Update();
263 output = setBackgroundFilter->GetOutput();
265 //--------------------------------------------------------------------
266 //--------------------------------------------------------------------
269 StartNewStep("AutoCrop");
270 typedef clitk::AutoCropFilter<InternalImageType> CropFilterType;
271 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
272 cropFilter->SetInput(output);
273 cropFilter->SetBackgroundValue(GetBackgroundValue());
274 cropFilter->Update();
275 output = cropFilter->GetOutput();
276 StopCurrentStep<InternalImageType>(output);
277 outputImage->SetRegions(output->GetLargestPossibleRegion());
281 //--------------------------------------------------------------------
284 //--------------------------------------------------------------------
285 template <class TInputImageType>
287 clitk::ExtractBonesFilter<TInputImageType>::
290 //--------------------------------------------------------------------
291 //--------------------------------------------------------------------
293 typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
294 typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
295 caster->SetInput(output);
297 this->GraftOutput(caster->GetOutput());
299 // Store image filenames into AFDB
300 GetAFDB()->SetImageFilename("bones", this->GetOutputBonesFilename());
304 //--------------------------------------------------------------------
307 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX