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 //--------------------------------------------------------------------
58 //--------------------------------------------------------------------
59 template<class IndexType, class PixelType>
63 Bifurcation(IndexType _index, PixelType _l, PixelType _l1, PixelType _l2) {
74 //--------------------------------------------------------------------
77 //--------------------------------------------------------------------
78 template <class TImageType, class TMaskImageType>
79 class ITK_EXPORT ExtractLungFilter:
80 public clitk::FilterBase,
81 public itk::ImageToImageFilter<TImageType, TMaskImageType>
85 /** Standard class typedefs. */
86 typedef itk::ImageToImageFilter<TImageType, TMaskImageType> Superclass;
87 typedef ExtractLungFilter Self;
88 typedef itk::SmartPointer<Self> Pointer;
89 typedef itk::SmartPointer<const Self> ConstPointer;
91 /** Method for creation through the object factory. */
94 /** Run-time type information (and related methods). */
95 itkTypeMacro(ExtractLungFilter, ImageToImageFilter);
98 /** Some convenient typedefs */
99 typedef TImageType ImageType;
100 typedef typename ImageType::ConstPointer InputImageConstPointer;
101 typedef typename ImageType::Pointer InputImagePointer;
102 typedef typename ImageType::RegionType InputImageRegionType;
103 typedef typename ImageType::PixelType InputImagePixelType;
104 typedef typename ImageType::SizeType InputImageSizeType;
105 typedef typename ImageType::IndexType InputImageIndexType;
107 typedef TMaskImageType MaskImageType;
108 typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
109 typedef typename MaskImageType::Pointer MaskImagePointer;
110 typedef typename MaskImageType::RegionType MaskImageRegionType;
111 typedef typename MaskImageType::PixelType MaskImagePixelType;
112 typedef typename MaskImageType::SizeType MaskImageSizeType;
113 typedef typename MaskImageType::IndexType MaskImageIndexType;
115 itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
116 typedef int InternalPixelType;
117 typedef itk::Image<InternalPixelType, ImageType::ImageDimension> InternalImageType;
118 typedef typename InternalImageType::Pointer InternalImagePointer;
119 typedef typename InternalImageType::IndexType InternalIndexType;
120 typedef LabelizeParameters<InternalPixelType> LabelParamType;
122 /** Connect inputs */
123 void SetInput(const ImageType * image);
124 void SetInputPatientMask(MaskImageType * mask, MaskImagePixelType BG);
125 itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType);
126 itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType);
127 GGO_DefineOption(patientBG, SetPatientMaskBackgroundValue, MaskImagePixelType);
129 // Set all options at a time
130 template<class ArgsInfoType>
131 void SetArgsInfo(ArgsInfoType arg);
133 // Get output (only availabe after update !)
134 typename MaskImageType::Pointer GetTracheaImage() { return trachea; }
136 // Background / Foreground
137 itkGetConstMacro(BackgroundValue, MaskImagePixelType);
138 itkGetConstMacro(ForegroundValue, MaskImagePixelType);
140 // For common segmentation processes
141 itkSetMacro(MinimalComponentSize, int);
142 itkGetConstMacro(MinimalComponentSize, int);
143 GGO_DefineOption(minSize, SetMinimalComponentSize, int);
145 // Step 1 options RemoveAir
146 itkSetMacro(UpperThreshold, InputImagePixelType);
147 itkGetConstMacro(UpperThreshold, InputImagePixelType);
148 GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType);
150 itkSetMacro(LowerThreshold, InputImagePixelType);
151 itkGetConstMacro(LowerThreshold, InputImagePixelType);
152 itkSetMacro(UseLowerThreshold, bool);
153 itkGetConstMacro(UseLowerThreshold, bool);
154 itkBooleanMacro(UseLowerThreshold);
155 GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold);
157 void SetLabelizeParameters1(LabelParamType * a) { m_LabelizeParameters1 = a; }
158 itkGetConstMacro(LabelizeParameters1, LabelParamType*);
159 GGO_DefineOption_LabelParam(1, SetLabelizeParameters1, LabelParamType);
161 // Step 2 options FindTrachea
162 itkSetMacro(UpperThresholdForTrachea, InputImagePixelType);
163 itkGetConstMacro(UpperThresholdForTrachea, InputImagePixelType);
164 GGO_DefineOption(upperThresholdForTrachea, SetUpperThresholdForTrachea, InputImagePixelType);
166 itkSetMacro(MultiplierForTrachea, double);
167 itkGetConstMacro(MultiplierForTrachea, double);
168 GGO_DefineOption(multiplierForTrachea, SetMultiplierForTrachea, double);
170 itkSetMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
171 itkGetConstMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
172 GGO_DefineOption(thresholdStepSizeForTrachea, SetThresholdStepSizeForTrachea, InputImagePixelType);
174 void AddSeed(InternalIndexType s);
175 std::vector<InternalIndexType> & GetSeeds() { return m_Seeds; }
176 GGO_DefineOption_Vector(seed, AddSeed, InternalIndexType, ImageType::ImageDimension, true);
178 // Step 3 options ExtractLung
179 itkSetMacro(NumberOfHistogramBins, int);
180 itkGetConstMacro(NumberOfHistogramBins, int);
181 GGO_DefineOption(bins, SetNumberOfHistogramBins, int);
183 void SetLabelizeParameters2(LabelParamType* a) { m_LabelizeParameters2 = a; }
184 itkGetConstMacro(LabelizeParameters2, LabelParamType*);
185 GGO_DefineOption_LabelParam(2, SetLabelizeParameters2, LabelParamType);
187 // Step 4 options RemoveTrachea
188 itkSetMacro(RadiusForTrachea, int);
189 itkGetConstMacro(RadiusForTrachea, int);
190 GGO_DefineOption(radius, SetRadiusForTrachea, int);
192 void SetLabelizeParameters3(LabelParamType * a) { m_LabelizeParameters3 = a; }
193 itkGetConstMacro(LabelizeParameters3, LabelParamType*);
194 GGO_DefineOption_LabelParam(3, SetLabelizeParameters3, LabelParamType);
196 // Step 5 options LungSeparation
197 // itkSetMacro(FinalOpenClose, bool);
198 // itkGetConstMacro(FinalOpenClose, bool);
199 // itkBooleanMacro(FinalOpenClose);
201 // Bronchial bifurcations
202 itkSetMacro(FindBronchialBifurcations, bool);
203 itkGetConstMacro(FindBronchialBifurcations, bool);
204 itkBooleanMacro(FindBronchialBifurcations);
208 virtual ~ExtractLungFilter() {}
211 InputImageConstPointer input;
212 MaskImageConstPointer patient;
213 InputImagePointer working_input;
214 typename InternalImageType::Pointer working_image;
215 typename InternalImageType::Pointer trachea_tmp;
216 MaskImagePointer trachea;
217 MaskImagePointer output;
218 unsigned int m_MaxSeedNumber;
221 itkSetMacro(BackgroundValue, MaskImagePixelType);
222 itkSetMacro(ForegroundValue, MaskImagePixelType);
223 MaskImagePixelType m_PatientMaskBackgroundValue;
224 MaskImagePixelType m_BackgroundValue;
225 MaskImagePixelType m_ForegroundValue;
226 int m_MinimalComponentSize;
229 InputImagePixelType m_UpperThreshold;
230 InputImagePixelType m_LowerThreshold;
231 bool m_UseLowerThreshold;
232 LabelParamType* m_LabelizeParameters1;
235 InputImagePixelType m_UpperThresholdForTrachea;
236 InputImagePixelType m_ThresholdStepSizeForTrachea;
237 double m_MultiplierForTrachea;
238 std::vector<InternalIndexType> m_Seeds;
241 int m_NumberOfHistogramBins;
242 LabelParamType* m_LabelizeParameters2;
245 int m_RadiusForTrachea;
246 LabelParamType* m_LabelizeParameters3;
249 // bool m_FinalOpenClose;
251 bool m_FindBronchialBifurcations;
253 virtual void GenerateOutputInformation();
254 virtual void GenerateData();
256 typedef Bifurcation<MaskImageIndexType,MaskImagePixelType> BifurcationType;
257 void TrackFromThisIndex(std::vector<BifurcationType> & listOfBifurcations,
258 MaskImagePointer skeleton,
259 MaskImageIndexType index,
260 MaskImagePixelType label);
263 ExtractLungFilter(const Self&); //purposely not implemented
264 void operator=(const Self&); //purposely not implemented
267 //--------------------------------------------------------------------
269 } // end namespace clitk
270 //--------------------------------------------------------------------
272 #ifndef ITK_MANUAL_INSTANTIATION
273 #include "clitkExtractLungFilter.txx"