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 CLITKEXTRACTLUNGSFILTER_H
20 #define CLITKEXTRACTLUNGSFILTER_H
23 #include "clitkFilterBase.h"
24 #include "clitkDecomposeAndReconstructImageFilter.h"
25 #include "clitkExplosionControlledThresholdConnectedImageFilter.h"
26 #include "clitkSegmentationUtils.h"
29 #include "itkStatisticsImageFilter.h"
33 //--------------------------------------------------------------------
35 Try to extract the Lung part of a thorax CT. Inspired by
36 Rikxoort2009, Section IIA, MedPhys.
38 - First, all air besides lungs and thrachea is removed, by
39 removing the second largest label of the firstLabelImage and
40 setting the remainder to 0HU . This modified input is optimally
41 thresholded (Otsu1979).
43 - Trachea and bronchi are grown from seeds in the top of the image
44 by explosion controlled region growing, slightly dilated and
45 removed from the second label image.
47 - Left and right lung are separated (if necessary) by erosion and
48 reconstructed by conditional dilation.
50 - TRACHEA is available at the end
52 TODO ********** Remaining holes can be filled afterwards (clitkFillMask).
55 //--------------------------------------------------------------------
57 //--------------------------------------------------------------------
58 template <class TImageType, class TMaskImageType>
59 class ITK_EXPORT ExtractLungFilter:
60 public virtual clitk::FilterBase,
61 public itk::ImageToImageFilter<TImageType, TMaskImageType>
65 /** Standard class typedefs. */
66 typedef itk::ImageToImageFilter<TImageType, TMaskImageType> Superclass;
67 typedef ExtractLungFilter Self;
68 typedef itk::SmartPointer<Self> Pointer;
69 typedef itk::SmartPointer<const Self> ConstPointer;
71 /** Method for creation through the object factory. */
74 /** Run-time type information (and related methods). */
75 itkTypeMacro(ExtractLungFilter, ImageToImageFilter);
78 /** Some convenient typedefs */
79 typedef TImageType ImageType;
80 typedef typename ImageType::ConstPointer InputImageConstPointer;
81 typedef typename ImageType::Pointer InputImagePointer;
82 typedef typename ImageType::RegionType InputImageRegionType;
83 typedef typename ImageType::PixelType InputImagePixelType;
84 typedef typename ImageType::SizeType InputImageSizeType;
85 typedef typename ImageType::IndexType InputImageIndexType;
86 typedef typename ImageType::PointType InputImagePointType;
88 typedef TMaskImageType MaskImageType;
89 typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
90 typedef typename MaskImageType::Pointer MaskImagePointer;
91 typedef typename MaskImageType::RegionType MaskImageRegionType;
92 typedef typename MaskImageType::PixelType MaskImagePixelType;
93 typedef typename MaskImageType::SizeType MaskImageSizeType;
94 typedef typename MaskImageType::IndexType MaskImageIndexType;
95 typedef typename MaskImageType::PointType MaskImagePointType;
97 itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
98 typedef int InternalPixelType;
99 typedef itk::Image<InternalPixelType, ImageType::ImageDimension> InternalImageType;
100 typedef typename InternalImageType::Pointer InternalImagePointer;
101 typedef typename InternalImageType::IndexType InternalIndexType;
102 typedef LabelizeParameters<InternalPixelType> LabelParamType;
104 /** Connect inputs */
105 void SetInput(const ImageType * image);
106 void SetInputPatientMask(MaskImageType * mask, MaskImagePixelType BG);
107 itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType);
108 itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType);
109 GGO_DefineOption(patientBG, SetPatientMaskBackgroundValue, MaskImagePixelType);
111 // Set all options at a time
112 template<class ArgsInfoType>
113 void SetArgsInfo(ArgsInfoType arg);
115 // Get output (only availabe after update !)
116 typename MaskImageType::Pointer GetTracheaImage() { return trachea; }
118 // Background / Foreground
119 itkGetConstMacro(BackgroundValue, MaskImagePixelType);
120 itkGetConstMacro(ForegroundValue, MaskImagePixelType);
122 // For common segmentation processes
123 itkSetMacro(MinimalComponentSize, int);
124 itkGetConstMacro(MinimalComponentSize, int);
125 GGO_DefineOption(minSize, SetMinimalComponentSize, int);
127 // Step 1 options RemoveAir
128 itkSetMacro(UpperThreshold, InputImagePixelType);
129 itkGetConstMacro(UpperThreshold, InputImagePixelType);
130 GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType);
132 itkSetMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
133 itkGetConstMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
134 GGO_DefineOption(skipslices, SetNumberOfSlicesToSkipBeforeSearchingSeed, int);
136 itkSetMacro(LowerThreshold, InputImagePixelType);
137 itkGetConstMacro(LowerThreshold, InputImagePixelType);
138 itkSetMacro(UseLowerThreshold, bool);
139 itkGetConstMacro(UseLowerThreshold, bool);
140 itkBooleanMacro(UseLowerThreshold);
141 GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold);
143 void SetLabelizeParameters1(LabelParamType * a) { m_LabelizeParameters1 = a; }
144 itkGetConstMacro(LabelizeParameters1, LabelParamType*);
145 GGO_DefineOption_LabelParam(1, SetLabelizeParameters1, LabelParamType);
147 // Step 2 options FindTrachea
148 itkSetMacro(UpperThresholdForTrachea, InputImagePixelType);
149 itkGetConstMacro(UpperThresholdForTrachea, InputImagePixelType);
150 GGO_DefineOption(upperThresholdForTrachea, SetUpperThresholdForTrachea, InputImagePixelType);
152 itkSetMacro(MultiplierForTrachea, double);
153 itkGetConstMacro(MultiplierForTrachea, double);
154 GGO_DefineOption(multiplierForTrachea, SetMultiplierForTrachea, double);
156 itkSetMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
157 itkGetConstMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
158 GGO_DefineOption(thresholdStepSizeForTrachea, SetThresholdStepSizeForTrachea, InputImagePixelType);
160 void AddSeed(InternalIndexType s);
161 std::vector<InternalIndexType> & GetSeeds() { return m_Seeds; }
162 GGO_DefineOption_Vector(seed, AddSeed, InternalIndexType, ImageType::ImageDimension, true);
164 // Step 3 options ExtractLung
165 itkSetMacro(NumberOfHistogramBins, int);
166 itkGetConstMacro(NumberOfHistogramBins, int);
167 GGO_DefineOption(bins, SetNumberOfHistogramBins, int);
169 void SetLabelizeParameters2(LabelParamType* a) { m_LabelizeParameters2 = a; }
170 itkGetConstMacro(LabelizeParameters2, LabelParamType*);
171 GGO_DefineOption_LabelParam(2, SetLabelizeParameters2, LabelParamType);
173 // Step 4 options RemoveTrachea
174 itkSetMacro(RadiusForTrachea, int);
175 itkGetConstMacro(RadiusForTrachea, int);
176 GGO_DefineOption(radius, SetRadiusForTrachea, int);
178 void SetLabelizeParameters3(LabelParamType * a) { m_LabelizeParameters3 = a; }
179 itkGetConstMacro(LabelizeParameters3, LabelParamType*);
180 GGO_DefineOption_LabelParam(3, SetLabelizeParameters3, LabelParamType);
182 // Step 5 final openclose
183 itkSetMacro(FinalOpenClose, bool);
184 itkGetConstMacro(FinalOpenClose, bool);
185 itkBooleanMacro(FinalOpenClose);
186 GGO_DefineOption_Flag(openclose, SetFinalOpenClose);
188 itkSetMacro(FinalOpenCloseRadius, int);
189 itkGetConstMacro(FinalOpenCloseRadius, int);
190 GGO_DefineOption(opencloseRadius, SetFinalOpenCloseRadius, int);
194 virtual ~ExtractLungFilter() {}
197 InputImageConstPointer input;
198 MaskImageConstPointer patient;
199 InputImagePointer working_input;
200 typename InternalImageType::Pointer working_image;
201 typename InternalImageType::Pointer trachea_tmp;
202 MaskImagePointer trachea;
203 MaskImagePointer output;
204 unsigned int m_MaxSeedNumber;
207 itkSetMacro(BackgroundValue, MaskImagePixelType);
208 itkSetMacro(ForegroundValue, MaskImagePixelType);
209 MaskImagePixelType m_PatientMaskBackgroundValue;
210 MaskImagePixelType m_BackgroundValue;
211 MaskImagePixelType m_ForegroundValue;
212 int m_MinimalComponentSize;
215 InputImagePixelType m_UpperThreshold;
216 InputImagePixelType m_LowerThreshold;
217 bool m_UseLowerThreshold;
218 LabelParamType* m_LabelizeParameters1;
221 InputImagePixelType m_UpperThresholdForTrachea;
222 InputImagePixelType m_ThresholdStepSizeForTrachea;
223 double m_MultiplierForTrachea;
224 std::vector<InternalIndexType> m_Seeds;
225 int m_NumberOfSlicesToSkipBeforeSearchingSeed;
228 int m_NumberOfHistogramBins;
229 LabelParamType* m_LabelizeParameters2;
232 int m_RadiusForTrachea;
233 LabelParamType* m_LabelizeParameters3;
236 bool m_FinalOpenClose;
237 int m_FinalOpenCloseRadius;
240 virtual void GenerateOutputInformation();
241 virtual void GenerateData();
243 // Functions for trachea extraction
244 bool SearchForTracheaSeed(int skip);
245 void SearchForTrachea();
246 void TracheaRegionGrowing();
247 double ComputeTracheaVolume();
250 ExtractLungFilter(const Self&); //purposely not implemented
251 void operator=(const Self&); //purposely not implemented
254 //--------------------------------------------------------------------
256 } // end namespace clitk
257 //--------------------------------------------------------------------
259 #ifndef ITK_MANUAL_INSTANTIATION
260 #include "clitkExtractLungFilter.txx"