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"
27 #include "clitkFilterWithAnatomicalFeatureDatabaseManagement.h"
31 #include "itkStatisticsImageFilter.h"
32 #include "itkTreeContainer.h"
36 //--------------------------------------------------------------------
38 Try to extract the Lung part of a thorax CT. Inspired by
39 Rikxoort2009, Section IIA, MedPhys.
41 - First, all air besides lungs and thrachea is removed, by
42 removing the second largest label of the firstLabelImage and
43 setting the remainder to 0HU . This modified input is optimally
44 thresholded (Otsu1979).
46 - Trachea and bronchi are grown from seeds in the top of the image
47 by explosion controlled region growing, slightly dilated and
48 removed from the second label image.
50 - Left and right lung are separated (if necessary) by erosion and
51 reconstructed by conditional dilation.
53 - TRACHEA is available at the end
55 TODO ********** Remaining holes can be filled afterwards (clitkFillMask).
58 //--------------------------------------------------------------------
61 //--------------------------------------------------------------------
66 typedef itk::Index<3> IndexType;
67 typedef itk::Point<double, 3> PointType;
68 typedef double PixelType;
69 Bifurcation(IndexType _index, PixelType _l, PixelType _l1, PixelType _l2) {
80 typedef itk::Index<3> NodeType;
81 typedef tree<NodeType> TreeType;
82 typedef TreeType::iterator TreeIterator;
83 TreeIterator treeIter;
85 //--------------------------------------------------------------------
88 //--------------------------------------------------------------------
89 template <class TImageType, class TMaskImageType>
90 class ITK_EXPORT ExtractLungFilter:
91 public virtual clitk::FilterBase,
92 public clitk::FilterWithAnatomicalFeatureDatabaseManagement,
93 public itk::ImageToImageFilter<TImageType, TMaskImageType>
97 /** Standard class typedefs. */
98 typedef itk::ImageToImageFilter<TImageType, TMaskImageType> Superclass;
99 typedef ExtractLungFilter Self;
100 typedef itk::SmartPointer<Self> Pointer;
101 typedef itk::SmartPointer<const Self> ConstPointer;
103 /** Method for creation through the object factory. */
106 /** Run-time type information (and related methods). */
107 itkTypeMacro(ExtractLungFilter, ImageToImageFilter);
110 /** Some convenient typedefs */
111 typedef TImageType ImageType;
112 typedef typename ImageType::ConstPointer InputImageConstPointer;
113 typedef typename ImageType::Pointer InputImagePointer;
114 typedef typename ImageType::RegionType InputImageRegionType;
115 typedef typename ImageType::PixelType InputImagePixelType;
116 typedef typename ImageType::SizeType InputImageSizeType;
117 typedef typename ImageType::IndexType InputImageIndexType;
118 typedef typename ImageType::PointType InputImagePointType;
120 typedef TMaskImageType MaskImageType;
121 typedef typename MaskImageType::ConstPointer MaskImageConstPointer;
122 typedef typename MaskImageType::Pointer MaskImagePointer;
123 typedef typename MaskImageType::RegionType MaskImageRegionType;
124 typedef typename MaskImageType::PixelType MaskImagePixelType;
125 typedef typename MaskImageType::SizeType MaskImageSizeType;
126 typedef typename MaskImageType::IndexType MaskImageIndexType;
127 typedef typename MaskImageType::PointType MaskImagePointType;
129 itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
130 typedef int InternalPixelType;
131 typedef itk::Image<InternalPixelType, ImageType::ImageDimension> InternalImageType;
132 typedef typename InternalImageType::Pointer InternalImagePointer;
133 typedef typename InternalImageType::IndexType InternalIndexType;
134 typedef LabelizeParameters<InternalPixelType> LabelParamType;
136 typedef Bifurcation BifurcationType;
137 typedef MaskImageIndexType NodeType;
138 typedef tree<NodeType> TreeType;
139 typedef typename TreeType::iterator TreeIterator;
141 /** Connect inputs */
142 void SetInput(const ImageType * image);
143 void SetInputPatientMask(MaskImageType * mask, MaskImagePixelType BG);
144 itkSetMacro(PatientMaskBackgroundValue, MaskImagePixelType);
145 itkGetConstMacro(PatientMaskBackgroundValue, MaskImagePixelType);
146 GGO_DefineOption(patientBG, SetPatientMaskBackgroundValue, MaskImagePixelType);
148 // Set all options at a time
149 template<class ArgsInfoType>
150 void SetArgsInfo(ArgsInfoType arg);
152 // Get output (only availabe after update !)
153 typename MaskImageType::Pointer GetTracheaImage() { return trachea; }
155 // Background / Foreground
156 itkGetConstMacro(BackgroundValue, MaskImagePixelType);
157 itkGetConstMacro(ForegroundValue, MaskImagePixelType);
159 // For common segmentation processes
160 itkSetMacro(MinimalComponentSize, int);
161 itkGetConstMacro(MinimalComponentSize, int);
162 GGO_DefineOption(minSize, SetMinimalComponentSize, int);
164 // Step 1 options RemoveAir
165 itkSetMacro(UpperThreshold, InputImagePixelType);
166 itkGetConstMacro(UpperThreshold, InputImagePixelType);
167 GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType);
169 itkSetMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
170 itkGetConstMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
171 GGO_DefineOption(skipslices, SetNumberOfSlicesToSkipBeforeSearchingSeed, int);
173 itkSetMacro(LowerThreshold, InputImagePixelType);
174 itkGetConstMacro(LowerThreshold, InputImagePixelType);
175 itkSetMacro(UseLowerThreshold, bool);
176 itkGetConstMacro(UseLowerThreshold, bool);
177 itkBooleanMacro(UseLowerThreshold);
178 GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold);
180 void SetLabelizeParameters1(LabelParamType * a) { m_LabelizeParameters1 = a; }
181 itkGetConstMacro(LabelizeParameters1, LabelParamType*);
182 GGO_DefineOption_LabelParam(1, SetLabelizeParameters1, LabelParamType);
184 // Step 2 options FindTrachea
185 itkSetMacro(UpperThresholdForTrachea, InputImagePixelType);
186 itkGetConstMacro(UpperThresholdForTrachea, InputImagePixelType);
187 GGO_DefineOption(upperThresholdForTrachea, SetUpperThresholdForTrachea, InputImagePixelType);
189 itkSetMacro(MultiplierForTrachea, double);
190 itkGetConstMacro(MultiplierForTrachea, double);
191 GGO_DefineOption(multiplierForTrachea, SetMultiplierForTrachea, double);
193 itkSetMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
194 itkGetConstMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
195 GGO_DefineOption(thresholdStepSizeForTrachea, SetThresholdStepSizeForTrachea, InputImagePixelType);
197 void AddSeed(InternalIndexType s);
198 std::vector<InternalIndexType> & GetSeeds() { return m_Seeds; }
199 GGO_DefineOption_Vector(seed, AddSeed, InternalIndexType, ImageType::ImageDimension, true);
201 // Step 3 options ExtractLung
202 itkSetMacro(NumberOfHistogramBins, int);
203 itkGetConstMacro(NumberOfHistogramBins, int);
204 GGO_DefineOption(bins, SetNumberOfHistogramBins, int);
206 void SetLabelizeParameters2(LabelParamType* a) { m_LabelizeParameters2 = a; }
207 itkGetConstMacro(LabelizeParameters2, LabelParamType*);
208 GGO_DefineOption_LabelParam(2, SetLabelizeParameters2, LabelParamType);
210 // Step 4 options RemoveTrachea
211 itkSetMacro(RadiusForTrachea, int);
212 itkGetConstMacro(RadiusForTrachea, int);
213 GGO_DefineOption(radius, SetRadiusForTrachea, int);
215 void SetLabelizeParameters3(LabelParamType * a) { m_LabelizeParameters3 = a; }
216 itkGetConstMacro(LabelizeParameters3, LabelParamType*);
217 GGO_DefineOption_LabelParam(3, SetLabelizeParameters3, LabelParamType);
219 // Step 5 options LungSeparation
220 // itkSetMacro(FinalOpenClose, bool);
221 // itkGetConstMacro(FinalOpenClose, bool);
222 // itkBooleanMacro(FinalOpenClose);
224 // Bronchial bifurcations
225 itkSetMacro(FindBronchialBifurcations, bool);
226 itkGetConstMacro(FindBronchialBifurcations, bool);
227 itkBooleanMacro(FindBronchialBifurcations);
231 virtual ~ExtractLungFilter() {}
234 InputImageConstPointer input;
235 MaskImageConstPointer patient;
236 InputImagePointer working_input;
237 typename InternalImageType::Pointer working_image;
238 typename InternalImageType::Pointer trachea_tmp;
239 MaskImagePointer trachea;
240 MaskImagePointer output;
241 unsigned int m_MaxSeedNumber;
244 itkSetMacro(BackgroundValue, MaskImagePixelType);
245 itkSetMacro(ForegroundValue, MaskImagePixelType);
246 MaskImagePixelType m_PatientMaskBackgroundValue;
247 MaskImagePixelType m_BackgroundValue;
248 MaskImagePixelType m_ForegroundValue;
249 int m_MinimalComponentSize;
252 InputImagePixelType m_UpperThreshold;
253 InputImagePixelType m_LowerThreshold;
254 bool m_UseLowerThreshold;
255 LabelParamType* m_LabelizeParameters1;
258 InputImagePixelType m_UpperThresholdForTrachea;
259 InputImagePixelType m_ThresholdStepSizeForTrachea;
260 double m_MultiplierForTrachea;
261 std::vector<InternalIndexType> m_Seeds;
262 int m_NumberOfSlicesToSkipBeforeSearchingSeed;
265 int m_NumberOfHistogramBins;
266 LabelParamType* m_LabelizeParameters2;
269 int m_RadiusForTrachea;
270 LabelParamType* m_LabelizeParameters3;
273 // bool m_FinalOpenClose;
274 bool m_FindBronchialBifurcations;
276 virtual void GenerateOutputInformation();
277 virtual void GenerateData();
279 TreeType m_SkeletonTree;
281 void TrackFromThisIndex(std::vector<BifurcationType> & listOfBifurcations,
282 MaskImagePointer skeleton,
283 MaskImageIndexType index,
284 MaskImagePixelType label,
285 TreeIterator currentNode);
288 bool SearchForTracheaSeed(int skip);
289 void SearchForTrachea();
290 void TracheaRegionGrowing();
291 double ComputeTracheaVolume();
294 ExtractLungFilter(const Self&); //purposely not implemented
295 void operator=(const Self&); //purposely not implemented
298 //--------------------------------------------------------------------
300 } // end namespace clitk
301 //--------------------------------------------------------------------
303 #ifndef ITK_MANUAL_INSTANTIATION
304 #include "clitkExtractLungFilter.txx"