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 CLITKEXTRACTMEDIASTINUMFILTER_TXX
20 #define CLITKEXTRACTMEDIASTINUMFILTER_TXX
23 #include "clitkCommon.h"
24 #include "clitkExtractMediastinumFilter.h"
25 #include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
26 #include "clitkSegmentationUtils.h"
27 #include "clitkExtractAirwaysTreeInfoFilter.h"
33 #include "itkStatisticsLabelMapFilter.h"
34 #include "itkLabelImageToStatisticsLabelMapFilter.h"
35 #include "itkRegionOfInterestImageFilter.h"
36 #include "itkBinaryThresholdImageFilter.h"
39 #include "RelativePositionPropImageFilter.h"
41 //--------------------------------------------------------------------
42 template <class ImageType>
43 clitk::ExtractMediastinumFilter<ImageType>::
44 ExtractMediastinumFilter():
46 clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
47 itk::ImageToImageFilter<ImageType, ImageType>()
49 this->SetNumberOfRequiredInputs(4);
51 SetBackgroundValuePatient(0);
52 SetBackgroundValueLung(0);
53 SetBackgroundValueBones(0);
54 SetForegroundValueLeftLung(1);
55 SetForegroundValueRightLung(2);
56 SetBackgroundValue(0);
57 SetForegroundValue(1);
59 SetIntermediateSpacing(6);
60 SetFuzzyThreshold1(0.4);
61 SetFuzzyThreshold2(0.6);
62 SetFuzzyThreshold3(0.2);
64 //--------------------------------------------------------------------
67 //--------------------------------------------------------------------
68 template <class ImageType>
70 clitk::ExtractMediastinumFilter<ImageType>::
71 SetInputPatientLabelImage(const ImageType * image, ImagePixelType bg)
73 this->SetNthInput(0, const_cast<ImageType *>(image));
74 m_BackgroundValuePatient = bg;
76 //--------------------------------------------------------------------
79 //--------------------------------------------------------------------
80 template <class ImageType>
82 clitk::ExtractMediastinumFilter<ImageType>::
83 SetInputLungLabelImage(const ImageType * image, ImagePixelType bg,
84 ImagePixelType fgLeft, ImagePixelType fgRight)
86 this->SetNthInput(1, const_cast<ImageType *>(image));
87 m_BackgroundValueLung = bg;
88 m_ForegroundValueLeftLung = fgLeft;
89 m_ForegroundValueRightLung = fgRight;
91 //--------------------------------------------------------------------
94 //--------------------------------------------------------------------
95 template <class ImageType>
97 clitk::ExtractMediastinumFilter<ImageType>::
98 SetInputBonesLabelImage(const ImageType * image, ImagePixelType bg)
100 this->SetNthInput(2, const_cast<ImageType *>(image));
101 m_BackgroundValueBones = bg;
103 //--------------------------------------------------------------------
106 //--------------------------------------------------------------------
107 template <class ImageType>
109 clitk::ExtractMediastinumFilter<ImageType>::
110 SetInputTracheaLabelImage(const ImageType * image, ImagePixelType bg)
112 this->SetNthInput(3, const_cast<ImageType *>(image));
113 m_BackgroundValueTrachea = bg;
115 //--------------------------------------------------------------------
118 //--------------------------------------------------------------------
119 template <class ImageType>
120 template<class ArgsInfoType>
122 clitk::ExtractMediastinumFilter<ImageType>::
123 SetArgsInfo(ArgsInfoType mArgsInfo)
125 SetVerboseOption_GGO(mArgsInfo);
126 SetVerboseStep_GGO(mArgsInfo);
127 SetWriteStep_GGO(mArgsInfo);
128 SetVerboseWarningOff_GGO(mArgsInfo);
130 SetBackgroundValuePatient_GGO(mArgsInfo);
131 SetBackgroundValueLung_GGO(mArgsInfo);
132 SetBackgroundValueTrachea_GGO(mArgsInfo);
134 SetForegroundValueLeftLung_GGO(mArgsInfo);
135 SetForegroundValueRightLung_GGO(mArgsInfo);
137 SetIntermediateSpacing_GGO(mArgsInfo);
138 SetFuzzyThreshold1_GGO(mArgsInfo);
139 SetFuzzyThreshold2_GGO(mArgsInfo);
140 SetFuzzyThreshold3_GGO(mArgsInfo);
142 //--------------------------------------------------------------------
145 //--------------------------------------------------------------------
146 template <class ImageType>
148 clitk::ExtractMediastinumFilter<ImageType>::
149 GenerateOutputInformation() {
150 ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
151 ImagePointer outputImage = this->GetOutput(0);
152 outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
154 //--------------------------------------------------------------------
157 //--------------------------------------------------------------------
158 template <class ImageType>
160 clitk::ExtractMediastinumFilter<ImageType>::
161 GenerateInputRequestedRegion()
164 Superclass::GenerateInputRequestedRegion();
165 // Get input pointers
166 ImagePointer patient = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
167 ImagePointer lung = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
168 ImagePointer bones = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
169 ImagePointer trachea = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(3));
171 patient->SetRequestedRegion(patient->GetLargestPossibleRegion());
172 lung->SetRequestedRegion(lung->GetLargestPossibleRegion());
173 bones->SetRequestedRegion(bones->GetLargestPossibleRegion());
174 trachea->SetRequestedRegion(trachea->GetLargestPossibleRegion());
176 //--------------------------------------------------------------------
179 //--------------------------------------------------------------------
180 template <class ImageType>
182 clitk::ExtractMediastinumFilter<ImageType>::
185 // Get input pointers
186 ImageConstPointer patient = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
187 ImageConstPointer lung = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(1));
188 ImageConstPointer bones = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(2));
189 ImageConstPointer trachea = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(3));
191 // Get output pointer
194 // Step 1: patient minus lungs, minus bones
195 StartNewStep("Patient contours minus lungs and minus bones");
196 typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
197 typename BoolFilterType::Pointer boolFilter = BoolFilterType::New();
198 boolFilter->InPlaceOn();
199 boolFilter->SetInput1(patient);
200 boolFilter->SetInput2(lung);
201 boolFilter->SetOperationType(BoolFilterType::AndNot);
202 boolFilter->Update();
203 boolFilter->SetInput1(boolFilter->GetOutput());
204 boolFilter->SetInput2(bones);
205 boolFilter->SetOperationType(BoolFilterType::AndNot);
206 boolFilter->Update();
207 output = boolFilter->GetOutput();
209 // Auto crop to gain support area
210 output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
211 this->template StopCurrentStep<ImageType>(output);
213 // Step 2: LR limits from lung (need separate lung ?)
214 StartNewStep("Left/Right limits with lungs");
216 /* // WE DO NOT NEED THE FOLLOWING
217 // Get separate lung images to get only the right and left lung
218 // (label must be '1' because right is greater than left).
219 ImagePointer right_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 2, 0);
220 ImagePointer left_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 1, 0);
221 writeImage<ImageType>(right_lung, "right.mhd");
222 writeImage<ImageType>(left_lung, "left.mhd");
225 typedef clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType> RelPosFilterType;
226 typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
227 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
228 relPosFilter->VerboseStepOff();
229 relPosFilter->WriteStepOff();
230 relPosFilter->SetInput(output);
231 DD(output->GetLargestPossibleRegion().GetIndex());
232 // relPosFilter->SetInputObject(left_lung);
233 relPosFilter->SetInputObject(lung);
234 relPosFilter->SetOrientationType(RelPosFilterType::LeftTo); // warning left lung is at right ;)
235 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
236 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
237 relPosFilter->Update();
238 output = relPosFilter->GetOutput();
239 DD(output->GetLargestPossibleRegion());
241 relPosFilter->SetInput(output);
242 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
243 relPosFilter->VerboseStepOff();
244 relPosFilter->WriteStepOff();
245 // relPosFilter->SetInputObject(right_lung);
246 relPosFilter->SetInputObject(lung);
247 relPosFilter->SetOrientationType(RelPosFilterType::RightTo);
248 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
249 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
250 relPosFilter->Update();
251 output = relPosFilter->GetOutput();
252 DD(output->GetLargestPossibleRegion());
253 this->template StopCurrentStep<ImageType>(output);
255 // Step 3: AP limits from bones
256 StartNewStep("Ant/Post limits with bones");
257 ImageConstPointer bones_ant;
258 ImageConstPointer bones_post;
260 // Find ant-post coordinate of trachea (assume the carena position is a
261 // good estimation of the ant-post position of the trachea)
262 ImagePointType carina;
264 GetAFDB()->GetPoint3D("Carina", carina);
266 ImageIndexType index_trachea;
267 bones->TransformPhysicalPointToIndex(carina, index_trachea);
270 // Split bone image first into two parts (ant and post)
271 typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
272 // typedef itk::ExtractImageFilter<ImageType, ImageType> CropFilterType;
273 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
274 ImageRegionType region = bones->GetLargestPossibleRegion();
275 ImageSizeType size = region.GetSize();
277 size[1] = index_trachea[1]; //size[1]/2.0;
279 region.SetSize(size);
280 cropFilter->SetInput(bones);
281 // cropFilter->SetExtractionRegion(region);
282 cropFilter->SetRegionOfInterest(region);
283 cropFilter->ReleaseDataFlagOff();
284 cropFilter->Update();
285 bones_ant = cropFilter->GetOutput();
286 writeImage<ImageType>(bones_ant, "b_ant.mhd");
288 // cropFilter->ResetPipeline();// = CropFilterType::New();
289 cropFilter = CropFilterType::New();
290 ImageIndexType index = region.GetIndex();
291 index[1] = bones->GetLargestPossibleRegion().GetIndex()[1] + size[1]-1;
292 size[1] = bones->GetLargestPossibleRegion().GetSize()[1] - size[1];
294 region.SetIndex(index);
295 region.SetSize(size);
296 cropFilter->SetInput(bones);
297 // cropFilter->SetExtractionRegion(region);
298 cropFilter->SetRegionOfInterest(region);
299 cropFilter->ReleaseDataFlagOff();
300 cropFilter->Update();
301 bones_post = cropFilter->GetOutput();
302 writeImage<ImageType>(bones_post, "b_post.mhd");
305 relPosFilter->SetCurrentStepNumber(0);
306 relPosFilter->ResetPipeline();// = RelPosFilterType::New();
307 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
308 relPosFilter->VerboseStepOff();
309 relPosFilter->WriteStepOff();
310 relPosFilter->SetInput(output);
311 relPosFilter->SetInputObject(bones_post);
312 relPosFilter->SetOrientationType(RelPosFilterType::AntTo);
313 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
314 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
315 relPosFilter->Update();
316 output = relPosFilter->GetOutput();
317 writeImage<ImageType>(output, "post.mhd");
319 relPosFilter->SetInput(relPosFilter->GetOutput());
320 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
321 relPosFilter->VerboseStepOff();
322 relPosFilter->WriteStepOff();
323 relPosFilter->SetInput(output);
324 relPosFilter->SetInputObject(bones_ant);
325 relPosFilter->SetOrientationType(RelPosFilterType::PostTo);
326 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
327 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
328 relPosFilter->Update();
329 output = relPosFilter->GetOutput();
330 this->template StopCurrentStep<ImageType>(output);
332 output = clitk::Labelize<ImageType>(output, GetBackgroundValue(), true, 100);
333 // output = RemoveLabels<ImageType>(output, BG, param->GetLabelsToRemove());
334 output = clitk::KeepLabels<ImageType>(output, GetBackgroundValue(),
335 GetForegroundValue(), 1, 1, 0);
338 // Step : Lower limits from lung (need separate lung ?)
339 StartNewStep("Lower limits with lungs");
340 relPosFilter = RelPosFilterType::New();
341 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
342 relPosFilter->VerboseStepOff();
343 relPosFilter->WriteStepOff();
344 relPosFilter->SetInput(output);
345 DD(output->GetLargestPossibleRegion().GetIndex());
346 // relPosFilter->SetInputObject(left_lung);
347 relPosFilter->SetInputObject(lung);
348 relPosFilter->SetOrientationType(RelPosFilterType::SupTo);
349 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
350 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold3());
351 relPosFilter->Update();
352 output = relPosFilter->GetOutput();
353 DD(output->GetLargestPossibleRegion());
355 output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
356 // cropFilter = CropFilterType::New();
357 //cropFilter->SetInput(output);
358 //cropFilter->Update();
359 //output = cropFilter->GetOutput();
361 // Final Step -> set output
362 this->SetNthOutput(0, output);
364 //--------------------------------------------------------------------
367 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX