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://www.centreleonberard.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"
27 #include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
30 #include "itkStatisticsImageFilter.h"
34 //--------------------------------------------------------------------
36 Try to extract the Lung part of a thorax CT. Inspired by
37 Rikxoort2009, Section IIA, MedPhys.
39 - First, all air besides lungs and thrachea is removed, by
40 removing the second largest label of the firstLabelImage and
41 setting the remainder to 0HU . This modified input is optimally
42 thresholded (Otsu1979).
44 - Trachea and bronchi are grown from seeds in the top of the image
45 by explosion controlled region growing, slightly dilated and
46 removed from the second label image.
48 - Left and right lung are separated (if necessary) by erosion and
49 reconstructed by conditional dilation.
51 - TRACHEA is available at the end
53 TODO ********** Remaining holes can be filled afterwards (clitkFillMask).
56 //--------------------------------------------------------------------
58 //--------------------------------------------------------------------
59 template <class TImageType>
60 class ITK_EXPORT ExtractLungFilter:
61 public virtual clitk::FilterBase,
62 public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
63 public itk::ImageToImageFilter<TImageType, itk::Image<uchar, TImageType::ImageDimension> >
67 /** Standard class typedefs. */
68 typedef itk::Image<uchar, TImageType::ImageDimension> MaskImageType;
69 typedef itk::ImageToImageFilter<TImageType, MaskImageType> Superclass;
70 typedef ExtractLungFilter Self;
71 typedef itk::SmartPointer<Self> Pointer;
72 typedef itk::SmartPointer<const Self> ConstPointer;
74 /** Method for creation through the object factory. */
77 /** Run-time type information (and related methods). */
78 itkTypeMacro(ExtractLungFilter, ImageToImageFilter);
81 /** Some convenient typedefs */
82 typedef TImageType ImageType;
83 typedef typename ImageType::ConstPointer InputImageConstPointer;
84 typedef typename ImageType::Pointer InputImagePointer;
85 typedef typename ImageType::RegionType InputImageRegionType;
86 typedef typename ImageType::PixelType InputImagePixelType;
87 typedef typename ImageType::SizeType InputImageSizeType;
88 typedef typename ImageType::IndexType InputImageIndexType;
89 typedef typename ImageType::PointType InputImagePointType;
91 typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
92 typedef typename MaskImageType::Pointer MaskImagePointer;
93 typedef typename MaskImageType::RegionType MaskImageRegionType;
94 typedef typename MaskImageType::PixelType MaskImagePixelType;
95 typedef typename MaskImageType::SizeType MaskImageSizeType;
96 typedef typename MaskImageType::IndexType MaskImageIndexType;
97 typedef typename MaskImageType::PointType MaskImagePointType;
99 itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
100 // typedef int InternalPixelType;
101 typedef uchar InternalPixelType;
102 typedef itk::Image<InternalPixelType, ImageType::ImageDimension> InternalImageType;
103 typedef typename InternalImageType::Pointer InternalImagePointer;
104 typedef typename InternalImageType::IndexType InternalIndexType;
105 typedef LabelizeParameters<InternalPixelType> LabelParamType;
107 /** Connect inputs */
108 void SetInput(const ImageType * image);
109 itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType);
110 itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType);
112 // Output filename (for AFBD)
113 itkSetMacro(OutputLungFilename, std::string);
114 itkGetMacro(OutputLungFilename, std::string);
116 itkSetMacro(OutputTracheaFilename, std::string);
117 itkGetMacro(OutputTracheaFilename, std::string);
119 // Get output (only availabe after update !)
120 typename MaskImageType::Pointer GetTracheaImage() { return trachea; }
122 // Background / Foreground
123 itkGetConstMacro(BackgroundValue, MaskImagePixelType);
124 itkGetConstMacro(ForegroundValue, MaskImagePixelType);
126 // For common segmentation processes
127 itkSetMacro(MinimalComponentSize, int);
128 itkGetConstMacro(MinimalComponentSize, int);
130 // Step 1 options RemoveAir
131 itkSetMacro(UpperThreshold, InputImagePixelType);
132 itkGetConstMacro(UpperThreshold, InputImagePixelType);
134 itkSetMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
135 itkGetConstMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
137 itkSetMacro(LowerThreshold, InputImagePixelType);
138 itkGetConstMacro(LowerThreshold, InputImagePixelType);
139 itkSetMacro(UseLowerThreshold, bool);
140 itkGetConstMacro(UseLowerThreshold, bool);
141 itkBooleanMacro(UseLowerThreshold);
143 void SetLabelizeParameters1(LabelParamType * a) { m_LabelizeParameters1 = a; }
144 itkGetConstMacro(LabelizeParameters1, LabelParamType*);
146 itkSetMacro(TracheaSeedAlgorithm, int);
147 itkGetConstMacro(TracheaSeedAlgorithm, int);
149 // Step 2 options FindTrachea
150 itkSetMacro(UpperThresholdForTrachea, InputImagePixelType);
151 itkGetConstMacro(UpperThresholdForTrachea, InputImagePixelType);
153 itkSetMacro(MultiplierForTrachea, double);
154 itkGetConstMacro(MultiplierForTrachea, double);
156 itkSetMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
157 itkGetConstMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
159 // options FindTrachea2
160 itkSetMacro(NumSlices, int);
161 itkGetConstMacro(NumSlices, int);
162 itkSetMacro(MaxElongation, double);
163 itkGetConstMacro(MaxElongation, double);
164 itkSetMacro(SeedPreProcessingThreshold, int);
165 itkGetConstMacro(SeedPreProcessingThreshold, int);
167 void AddSeedInPixels(InternalIndexType s);
168 void AddSeed(InputImagePointType s);
169 std::vector<InternalIndexType> & GetSeeds() { return m_Seeds; }
171 itkSetMacro(TracheaVolumeMustBeCheckedFlag, bool);
172 itkGetConstMacro(TracheaVolumeMustBeCheckedFlag, bool);
173 itkBooleanMacro(TracheaVolumeMustBeCheckedFlag);
175 itkSetMacro(VerboseRegionGrowingFlag, bool);
176 itkGetConstMacro(VerboseRegionGrowingFlag, bool);
177 itkBooleanMacro(VerboseRegionGrowingFlag);
179 itkSetMacro(RemoveSmallLabelBeforeSeparationFlag, bool);
180 itkGetConstMacro(RemoveSmallLabelBeforeSeparationFlag, bool);
181 itkBooleanMacro(RemoveSmallLabelBeforeSeparationFlag);
183 // Step 3 options ExtractLung
184 itkSetMacro(NumberOfHistogramBins, int);
185 itkGetConstMacro(NumberOfHistogramBins, int);
187 void SetLabelizeParameters2(LabelParamType* a) { m_LabelizeParameters2 = a; }
188 itkGetConstMacro(LabelizeParameters2, LabelParamType*);
190 // Step 4 options RemoveTrachea
191 itkSetMacro(RadiusForTrachea, int);
192 itkGetConstMacro(RadiusForTrachea, int);
194 void SetLabelizeParameters3(LabelParamType * a) { m_LabelizeParameters3 = a; }
195 itkGetConstMacro(LabelizeParameters3, LabelParamType*);
197 // Step 5 final openclose
198 itkSetMacro(OpenCloseFlag, bool);
199 itkGetConstMacro(OpenCloseFlag, bool);
200 itkBooleanMacro(OpenCloseFlag);
202 itkSetMacro(OpenCloseRadius, int);
203 itkGetConstMacro(OpenCloseRadius, int);
206 itkSetMacro(FillHolesFlag, bool);
207 itkGetConstMacro(FillHolesFlag, bool);
208 itkBooleanMacro(FillHolesFlag);
211 itkSetMacro(SeparateLungsFlag, bool);
212 itkGetConstMacro(SeparateLungsFlag, bool);
213 itkBooleanMacro(SeparateLungsFlag);
216 itkSetMacro(AutoCrop, bool);
217 itkGetConstMacro(AutoCrop, bool);
218 itkBooleanMacro(AutoCrop);
222 virtual ~ExtractLungFilter() {}
225 InputImageConstPointer input;
226 MaskImagePointer patient;
227 InputImagePointer working_input;
228 std::string m_OutputLungFilename;
229 std::string m_OutputTracheaFilename;
230 MaskImagePointer working_mask;
231 MaskImagePointer trachea;
232 unsigned int m_MaxSeedNumber;
235 itkSetMacro(BackgroundValue, MaskImagePixelType);
236 itkSetMacro(ForegroundValue, MaskImagePixelType);
237 MaskImagePixelType m_PatientMaskBackgroundValue;
238 MaskImagePixelType m_BackgroundValue;
239 MaskImagePixelType m_ForegroundValue;
240 int m_MinimalComponentSize;
242 bool m_RemoveSmallLabelBeforeSeparationFlag;
245 InputImagePixelType m_UpperThreshold;
246 InputImagePixelType m_LowerThreshold;
247 bool m_UseLowerThreshold;
248 LabelParamType* m_LabelizeParameters1;
251 int m_TracheaSeedAlgorithm;
252 InputImagePixelType m_UpperThresholdForTrachea;
253 InputImagePixelType m_ThresholdStepSizeForTrachea;
254 double m_MultiplierForTrachea;
255 std::vector<InternalIndexType> m_Seeds;
256 std::vector<InputImagePointType> m_SeedsInMM;
257 int m_NumberOfSlicesToSkipBeforeSearchingSeed;
258 bool m_TracheaVolumeMustBeCheckedFlag;
259 bool m_VerboseRegionGrowingFlag;
261 double m_MaxElongation;
262 int m_SeedPreProcessingThreshold;
265 int m_NumberOfHistogramBins;
266 LabelParamType* m_LabelizeParameters2;
269 int m_RadiusForTrachea;
270 LabelParamType* m_LabelizeParameters3;
273 bool m_OpenCloseFlag;
274 int m_OpenCloseRadius;
277 bool m_FillHolesFlag;
278 InputImageSizeType m_FillHolesDirections;
280 bool m_SeparateLungsFlag;
283 virtual void GenerateOutputInformation();
284 virtual void GenerateInputRequestedRegion();
285 virtual void GenerateData();
287 // Functions for trachea extraction
288 bool SearchForTracheaSeed(int skip);
289 bool SearchForTracheaSeed2(int numberOfSlices);
290 void SearchForTrachea();
291 void TracheaRegionGrowing();
292 double ComputeTracheaVolume();
295 ExtractLungFilter(const Self&); //purposely not implemented
296 void operator=(const Self&); //purposely not implemented
299 //--------------------------------------------------------------------
301 } // end namespace clitk
302 //--------------------------------------------------------------------
304 #ifndef ITK_MANUAL_INSTANTIATION
305 #include "clitkExtractLungFilter.txx"