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 "clitkExtractAirwayTreeInfoFilter.h"
31 #include "itkStatisticsLabelMapFilter.h"
32 #include "itkLabelImageToStatisticsLabelMapFilter.h"
33 #include "itkRegionOfInterestImageFilter.h"
34 #include "itkBinaryThresholdImageFilter.h"
37 #include "RelativePositionPropImageFilter.h"
39 //--------------------------------------------------------------------
40 template <class ImageType>
41 clitk::ExtractMediastinumFilter<ImageType>::
42 ExtractMediastinumFilter():
44 itk::ImageToImageFilter<ImageType, ImageType>()
46 this->SetNumberOfRequiredInputs(4);
48 SetBackgroundValuePatient(0);
49 SetBackgroundValueLung(0);
50 SetBackgroundValueBones(0);
51 SetForegroundValueLeftLung(1);
52 SetForegroundValueRightLung(2);
53 SetBackgroundValue(0);
54 SetForegroundValue(1);
56 SetIntermediateSpacing(6);
57 SetFuzzyThreshold1(0.6);
58 SetFuzzyThreshold2(0.7);
60 //--------------------------------------------------------------------
63 //--------------------------------------------------------------------
64 template <class ImageType>
66 clitk::ExtractMediastinumFilter<ImageType>::
67 SetInputPatientLabelImage(const ImageType * image, ImagePixelType bg)
69 this->SetNthInput(0, const_cast<ImageType *>(image));
70 m_BackgroundValuePatient = bg;
72 //--------------------------------------------------------------------
75 //--------------------------------------------------------------------
76 template <class ImageType>
78 clitk::ExtractMediastinumFilter<ImageType>::
79 SetInputLungLabelImage(const ImageType * image, ImagePixelType bg,
80 ImagePixelType fgLeft, ImagePixelType fgRight)
82 this->SetNthInput(1, const_cast<ImageType *>(image));
83 m_BackgroundValueLung = bg;
84 m_ForegroundValueLeftLung = fgLeft;
85 m_ForegroundValueRightLung = fgRight;
87 //--------------------------------------------------------------------
90 //--------------------------------------------------------------------
91 template <class ImageType>
93 clitk::ExtractMediastinumFilter<ImageType>::
94 SetInputBonesLabelImage(const ImageType * image, ImagePixelType bg)
96 this->SetNthInput(2, const_cast<ImageType *>(image));
97 m_BackgroundValueBones = bg;
99 //--------------------------------------------------------------------
102 //--------------------------------------------------------------------
103 template <class ImageType>
105 clitk::ExtractMediastinumFilter<ImageType>::
106 SetInputTracheaLabelImage(const ImageType * image, ImagePixelType bg)
108 this->SetNthInput(3, const_cast<ImageType *>(image));
109 m_BackgroundValueTrachea = bg;
111 //--------------------------------------------------------------------
114 //--------------------------------------------------------------------
115 template <class ImageType>
116 template<class ArgsInfoType>
118 clitk::ExtractMediastinumFilter<ImageType>::
119 SetArgsInfo(ArgsInfoType mArgsInfo)
121 SetVerboseOption_GGO(mArgsInfo);
122 SetVerboseStep_GGO(mArgsInfo);
123 SetWriteStep_GGO(mArgsInfo);
124 SetVerboseWarningOff_GGO(mArgsInfo);
126 SetBackgroundValuePatient_GGO(mArgsInfo);
127 SetBackgroundValueLung_GGO(mArgsInfo);
128 SetBackgroundValueTrachea_GGO(mArgsInfo);
130 SetForegroundValueLeftLung_GGO(mArgsInfo);
131 SetForegroundValueRightLung_GGO(mArgsInfo);
133 SetIntermediateSpacing_GGO(mArgsInfo);
134 SetFuzzyThreshold1_GGO(mArgsInfo);
135 SetFuzzyThreshold2_GGO(mArgsInfo);
137 //--------------------------------------------------------------------
140 //--------------------------------------------------------------------
141 template <class ImageType>
143 clitk::ExtractMediastinumFilter<ImageType>::
144 GenerateOutputInformation() {
145 ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
146 ImagePointer outputImage = this->GetOutput(0);
147 outputImage->SetRegions(outputImage->GetLargestPossibleRegion());
149 //--------------------------------------------------------------------
152 //--------------------------------------------------------------------
153 template <class ImageType>
155 clitk::ExtractMediastinumFilter<ImageType>::
156 GenerateInputRequestedRegion()
159 Superclass::GenerateInputRequestedRegion();
160 // Get input pointers
161 ImagePointer patient = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
162 ImagePointer lung = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
163 ImagePointer bones = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(2));
164 ImagePointer trachea = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(3));
166 patient->SetRequestedRegion(patient->GetLargestPossibleRegion());
167 lung->SetRequestedRegion(lung->GetLargestPossibleRegion());
168 bones->SetRequestedRegion(bones->GetLargestPossibleRegion());
169 trachea->SetRequestedRegion(trachea->GetLargestPossibleRegion());
171 //--------------------------------------------------------------------
174 //--------------------------------------------------------------------
175 template <class ImageType>
177 clitk::ExtractMediastinumFilter<ImageType>::
180 // Get input pointers
181 ImageConstPointer patient = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(0));
182 ImageConstPointer lung = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(1));
183 ImageConstPointer bones = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(2));
184 ImageConstPointer trachea = dynamic_cast<const ImageType*>(itk::ProcessObject::GetInput(3));
186 // Get output pointer
189 // Step 1: patient minus lungs, minus bones
190 StartNewStep("Patient contours minus lungs and minus bones");
191 typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
192 typename BoolFilterType::Pointer boolFilter = BoolFilterType::New();
193 boolFilter->InPlaceOn();
194 boolFilter->SetInput1(patient);
195 boolFilter->SetInput2(lung);
196 boolFilter->SetOperationType(BoolFilterType::AndNot);
197 boolFilter->Update();
198 boolFilter->SetInput1(boolFilter->GetOutput());
199 boolFilter->SetInput2(bones);
200 boolFilter->SetOperationType(BoolFilterType::AndNot);
201 boolFilter->Update();
202 output = boolFilter->GetOutput();
204 // Auto crop to gain support area
205 output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
206 this->template StopCurrentStep<ImageType>(output);
208 // Step 2: LR limits from lung (need separate lung ?)
209 StartNewStep("Left/Right limits with lungs");
211 /* // WE DO NOT NEED THE FOLLOWING
212 // Get separate lung images to get only the right and left lung
213 // (label must be '1' because right is greater than left).
214 ImagePointer right_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 2, 0);
215 ImagePointer left_lung = clitk::SetBackground<ImageType, ImageType>(lung, lung, 1, 0);
216 writeImage<ImageType>(right_lung, "right.mhd");
217 writeImage<ImageType>(left_lung, "left.mhd");
220 typedef clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType> RelPosFilterType;
221 typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
222 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
223 relPosFilter->VerboseStepOff();
224 relPosFilter->WriteStepOff();
225 relPosFilter->SetInput(output);
226 DD(output->GetLargestPossibleRegion().GetIndex());
227 // relPosFilter->SetInputObject(left_lung);
228 relPosFilter->SetInputObject(lung);
229 relPosFilter->SetOrientationType(RelPosFilterType::LeftTo); // warning left lung is at right ;)
230 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
231 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
232 relPosFilter->Update();
233 output = relPosFilter->GetOutput();
234 DD(output->GetLargestPossibleRegion());
236 relPosFilter->SetInput(output);
237 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
238 relPosFilter->VerboseStepOff();
239 relPosFilter->WriteStepOff();
240 // relPosFilter->SetInputObject(right_lung);
241 relPosFilter->SetInputObject(lung);
242 relPosFilter->SetOrientationType(RelPosFilterType::RightTo);
243 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
244 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold1());
245 relPosFilter->Update();
246 output = relPosFilter->GetOutput();
247 DD(output->GetLargestPossibleRegion());
248 this->template StopCurrentStep<ImageType>(output);
250 // Step 3: AP limits from bones
251 StartNewStep("Ant/Post limits with bones");
252 ImageConstPointer bones_ant;
253 ImageConstPointer bones_post;
255 // Find ant-post coordinate of trachea (assume the first point is a
256 // good estimation of the ant-post position of the trachea)
257 typedef clitk::ExtractAirwayTreeInfoFilter<ImageType> AirwayFilter;
258 typename AirwayFilter::Pointer airwayfilter = AirwayFilter::New();
259 airwayfilter->SetInput(trachea);
260 airwayfilter->Update();
261 DD(airwayfilter->GetFirstTracheaPoint());
262 ImagePointType point_trachea = airwayfilter->GetFirstTracheaPoint();
263 ImageIndexType index_trachea;
264 bones->TransformPhysicalPointToIndex(point_trachea, index_trachea);
267 // Split bone image first into two parts (ant and post)
268 typedef itk::RegionOfInterestImageFilter<ImageType, ImageType> CropFilterType;
269 // typedef itk::ExtractImageFilter<ImageType, ImageType> CropFilterType;
270 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
271 ImageRegionType region = bones->GetLargestPossibleRegion();
272 ImageSizeType size = region.GetSize();
274 size[1] = index_trachea[1]; //size[1]/2.0;
276 region.SetSize(size);
277 cropFilter->SetInput(bones);
278 // cropFilter->SetExtractionRegion(region);
279 cropFilter->SetRegionOfInterest(region);
280 cropFilter->ReleaseDataFlagOff();
281 cropFilter->Update();
282 bones_ant = cropFilter->GetOutput();
283 writeImage<ImageType>(bones_ant, "b_ant.mhd");
285 // cropFilter->ResetPipeline();// = CropFilterType::New();
286 cropFilter = CropFilterType::New();
287 ImageIndexType index = region.GetIndex();
288 size[1] = bones->GetLargestPossibleRegion().GetSize()[1] - size[1];
289 index[1] = bones->GetLargestPossibleRegion().GetIndex()[1] + size[1]-1;
291 region.SetIndex(index);
292 region.SetSize(size);
293 cropFilter->SetInput(bones);
294 // cropFilter->SetExtractionRegion(region);
295 cropFilter->SetRegionOfInterest(region);
296 cropFilter->ReleaseDataFlagOff();
297 cropFilter->Update();
298 bones_post = cropFilter->GetOutput();
299 writeImage<ImageType>(bones_post, "b_post.mhd");
302 relPosFilter->SetCurrentStepNumber(0);
303 relPosFilter->ResetPipeline();// = RelPosFilterType::New();
304 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
305 relPosFilter->VerboseStepOff();
306 relPosFilter->WriteStepOff();
307 relPosFilter->SetInput(output);
308 relPosFilter->SetInputObject(bones_post);
309 relPosFilter->SetOrientationType(RelPosFilterType::AntTo);
310 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
311 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
312 relPosFilter->Update();
313 output = relPosFilter->GetOutput();
314 writeImage<ImageType>(output, "post.mhd");
316 relPosFilter->SetInput(relPosFilter->GetOutput());
317 relPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
318 relPosFilter->VerboseStepOff();
319 relPosFilter->WriteStepOff();
320 relPosFilter->SetInput(output);
321 relPosFilter->SetInputObject(bones_ant);
322 relPosFilter->SetOrientationType(RelPosFilterType::PostTo);
323 relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
324 relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold2());
325 relPosFilter->Update();
326 output = relPosFilter->GetOutput();
327 this->template StopCurrentStep<ImageType>(output);
329 output = clitk::Labelize<ImageType>(output, GetBackgroundValue(), true, 100);
330 // output = RemoveLabels<ImageType>(output, BG, param->GetLabelsToRemove());
331 output = clitk::KeepLabels<ImageType>(output, GetBackgroundValue(),
332 GetForegroundValue(), 1, 1, 0);
334 output = clitk::AutoCrop<ImageType>(output, GetBackgroundValue());
335 // cropFilter = CropFilterType::New();
336 //cropFilter->SetInput(output);
337 //cropFilter->Update();
338 //output = cropFilter->GetOutput();
340 // Final Step -> set output
341 this->SetNthOutput(0, output);
343 //--------------------------------------------------------------------
346 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX