]> Creatis software - clitk.git/blob - segmentation/clitkExtractLungFilter.h
add smooth option to extract bones
[clitk.git] / segmentation / clitkExtractLungFilter.h
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to: 
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
8
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.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ======================================================================-====*/
18
19 #ifndef CLITKEXTRACTLUNGSFILTER_H
20 #define CLITKEXTRACTLUNGSFILTER_H
21
22 // clitk 
23 #include "clitkFilterBase.h"
24 #include "clitkDecomposeAndReconstructImageFilter.h"
25 #include "clitkExplosionControlledThresholdConnectedImageFilter.h"
26 #include "clitkSegmentationUtils.h"
27
28 // itk
29 #include "itkStatisticsImageFilter.h"
30
31 namespace clitk {
32   
33   //--------------------------------------------------------------------
34   /*
35     Try to extract the Lung part of a thorax CT. Inspired by
36     Rikxoort2009, Section IIA, MedPhys.
37
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).
42
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.
46
47     - Left and right lung are separated (if necessary) by erosion and
48     reconstructed by conditional dilation. 
49
50     - TRACHEA is available at the end
51
52     TODO ********** Remaining holes can be       filled afterwards (clitkFillMask).
53
54   */
55   //--------------------------------------------------------------------
56   
57
58   //--------------------------------------------------------------------
59 template<class IndexType, class PixelType>
60 class Bifurcation
61 {
62 public:
63   Bifurcation(IndexType _index, PixelType _l, PixelType _l1, PixelType _l2) {
64     index = _index;
65     _l = l;
66     _l1 = l1;
67     _l2 = l2;
68   }
69   IndexType index;
70   PixelType l;
71   PixelType l1;
72   PixelType l2;
73 };
74   //--------------------------------------------------------------------
75
76
77   //--------------------------------------------------------------------
78   template <class TImageType, class TMaskImageType>
79   class ITK_EXPORT ExtractLungFilter: 
80     public clitk::FilterBase, 
81     public itk::ImageToImageFilter<TImageType, TMaskImageType> 
82   {
83     
84   public:
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;
90     
91     /** Method for creation through the object factory. */
92     itkNewMacro(Self);  
93     
94     /** Run-time type information (and related methods). */
95     itkTypeMacro(ExtractLungFilter, ImageToImageFilter);
96     FILTERBASE_INIT;
97
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; 
106         
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; 
114
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;
121     
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);
128
129     // Set all options at a time
130     template<class ArgsInfoType>
131       void SetArgsInfo(ArgsInfoType arg);
132
133     // Get output (only availabe after update !)
134     typename MaskImageType::Pointer GetTracheaImage() { return trachea; }
135
136     // Background / Foreground
137     itkGetConstMacro(BackgroundValue, MaskImagePixelType);
138     itkGetConstMacro(ForegroundValue, MaskImagePixelType);
139
140     // For common segmentation processes
141     itkSetMacro(MinimalComponentSize, int);
142     itkGetConstMacro(MinimalComponentSize, int);
143     GGO_DefineOption(minSize, SetMinimalComponentSize, int);
144
145     // Step 1 options RemoveAir
146     itkSetMacro(UpperThreshold, InputImagePixelType);
147     itkGetConstMacro(UpperThreshold, InputImagePixelType);
148     GGO_DefineOption(upper, SetUpperThreshold, InputImagePixelType);
149
150     itkSetMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
151     itkGetConstMacro(NumberOfSlicesToSkipBeforeSearchingSeed, int);
152     GGO_DefineOption(skipslices, SetNumberOfSlicesToSkipBeforeSearchingSeed, int);
153     
154     itkSetMacro(LowerThreshold, InputImagePixelType);
155     itkGetConstMacro(LowerThreshold, InputImagePixelType);
156     itkSetMacro(UseLowerThreshold, bool);
157     itkGetConstMacro(UseLowerThreshold, bool);
158     itkBooleanMacro(UseLowerThreshold);
159     GGO_DefineOption_WithTest(lower, SetLowerThreshold, InputImagePixelType, UseLowerThreshold);
160
161     void SetLabelizeParameters1(LabelParamType * a) { m_LabelizeParameters1 = a; }
162     itkGetConstMacro(LabelizeParameters1, LabelParamType*);
163     GGO_DefineOption_LabelParam(1, SetLabelizeParameters1, LabelParamType);
164
165     // Step 2 options FindTrachea
166     itkSetMacro(UpperThresholdForTrachea, InputImagePixelType);
167     itkGetConstMacro(UpperThresholdForTrachea, InputImagePixelType);
168     GGO_DefineOption(upperThresholdForTrachea, SetUpperThresholdForTrachea, InputImagePixelType);
169
170     itkSetMacro(MultiplierForTrachea, double);
171     itkGetConstMacro(MultiplierForTrachea, double);
172     GGO_DefineOption(multiplierForTrachea, SetMultiplierForTrachea, double);
173
174     itkSetMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
175     itkGetConstMacro(ThresholdStepSizeForTrachea, InputImagePixelType);
176     GGO_DefineOption(thresholdStepSizeForTrachea, SetThresholdStepSizeForTrachea, InputImagePixelType);
177
178     void AddSeed(InternalIndexType s);
179     std::vector<InternalIndexType> & GetSeeds() { return  m_Seeds; }
180     GGO_DefineOption_Vector(seed, AddSeed, InternalIndexType, ImageType::ImageDimension, true);
181
182     // Step 3 options ExtractLung
183     itkSetMacro(NumberOfHistogramBins, int);
184     itkGetConstMacro(NumberOfHistogramBins, int);
185     GGO_DefineOption(bins, SetNumberOfHistogramBins, int);
186
187     void SetLabelizeParameters2(LabelParamType* a) { m_LabelizeParameters2 = a; }
188     itkGetConstMacro(LabelizeParameters2, LabelParamType*);
189     GGO_DefineOption_LabelParam(2, SetLabelizeParameters2, LabelParamType);
190
191     // Step 4 options RemoveTrachea
192     itkSetMacro(RadiusForTrachea, int);
193     itkGetConstMacro(RadiusForTrachea, int);
194     GGO_DefineOption(radius, SetRadiusForTrachea, int);
195     
196     void SetLabelizeParameters3(LabelParamType * a) { m_LabelizeParameters3 = a; }
197     itkGetConstMacro(LabelizeParameters3, LabelParamType*);
198     GGO_DefineOption_LabelParam(3, SetLabelizeParameters3, LabelParamType);
199
200     // Step 5 options LungSeparation
201     //     itkSetMacro(FinalOpenClose, bool);
202     //     itkGetConstMacro(FinalOpenClose, bool);
203     //     itkBooleanMacro(FinalOpenClose);
204
205     // Bronchial bifurcations
206     itkSetMacro(FindBronchialBifurcations, bool);
207     itkGetConstMacro(FindBronchialBifurcations, bool);
208     itkBooleanMacro(FindBronchialBifurcations);
209
210   protected:
211     ExtractLungFilter();
212     virtual ~ExtractLungFilter() {}
213
214     // Main members
215     InputImageConstPointer input;
216     MaskImageConstPointer patient;
217     InputImagePointer working_input;
218     typename InternalImageType::Pointer working_image;  
219     typename InternalImageType::Pointer trachea_tmp;
220     MaskImagePointer trachea;
221     MaskImagePointer output;
222     unsigned int m_MaxSeedNumber;
223
224     // Global options
225     itkSetMacro(BackgroundValue, MaskImagePixelType);
226     itkSetMacro(ForegroundValue, MaskImagePixelType);
227     MaskImagePixelType m_PatientMaskBackgroundValue;
228     MaskImagePixelType m_BackgroundValue;
229     MaskImagePixelType m_ForegroundValue;
230     int m_MinimalComponentSize;
231
232     // Step 1
233     InputImagePixelType m_UpperThreshold;
234     InputImagePixelType m_LowerThreshold;
235     bool m_UseLowerThreshold;
236     LabelParamType* m_LabelizeParameters1;
237
238     // Step 2
239     InputImagePixelType m_UpperThresholdForTrachea;
240     InputImagePixelType m_ThresholdStepSizeForTrachea;
241     double m_MultiplierForTrachea;
242     std::vector<InternalIndexType> m_Seeds;
243     int m_NumberOfSlicesToSkipBeforeSearchingSeed;
244
245     // Step 3
246     int m_NumberOfHistogramBins;
247     LabelParamType* m_LabelizeParameters2;
248
249     // Step 4
250     int m_RadiusForTrachea;
251     LabelParamType* m_LabelizeParameters3;
252
253     // Step 5
254     //     bool m_FinalOpenClose;
255     
256     bool m_FindBronchialBifurcations;
257     
258     virtual void GenerateOutputInformation();
259     virtual void GenerateData();
260
261     typedef Bifurcation<MaskImageIndexType,MaskImagePixelType> BifurcationType;
262     void TrackFromThisIndex(std::vector<BifurcationType> & listOfBifurcations, 
263                             MaskImagePointer skeleton, 
264                             MaskImageIndexType index,
265                             MaskImagePixelType label);
266         
267
268     bool SearchForTracheaSeed(int skip);
269     void SearchForTrachea();
270     void TracheaRegionGrowing();
271     double ComputeTracheaVolume();
272
273   private:
274     ExtractLungFilter(const Self&); //purposely not implemented
275     void operator=(const Self&); //purposely not implemented
276     
277   }; // end class
278   //--------------------------------------------------------------------
279
280 } // end namespace clitk
281 //--------------------------------------------------------------------
282
283 #ifndef ITK_MANUAL_INSTANTIATION
284 #include "clitkExtractLungFilter.txx"
285 #endif
286
287 #endif