]> Creatis software - clitk.git/blob - segmentation/clitkExtractPatientFilter.txx
correct options scheme
[clitk.git] / segmentation / clitkExtractPatientFilter.txx
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 CLITKEXTRACTPATIENTFILTER_TXX
20 #define CLITKEXTRACTPATIENTFILTER_TXX
21
22 // clitk
23 #include "clitkImageCommon.h"
24 #include "clitkSetBackgroundImageFilter.h"
25 #include "clitkDecomposeAndReconstructImageFilter.h"
26 #include "clitkAutoCropFilter.h"
27 #include "clitkMemoryUsage.h"
28
29 // itk
30 #include "itkBinaryThresholdImageFilter.h"
31 #include "itkConnectedComponentImageFilter.h"
32 #include "itkRelabelComponentImageFilter.h"
33 #include "itkBinaryMorphologicalClosingImageFilter.h"
34 #include "itkBinaryMorphologicalOpeningImageFilter.h"
35 #include "itkBinaryBallStructuringElement.h"
36 #include "itkCastImageFilter.h"
37
38 //--------------------------------------------------------------------
39 template <class TInputImageType>
40 clitk::ExtractPatientFilter<TInputImageType>::
41 ExtractPatientFilter():
42   clitk::FilterBase(),
43   clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
44   itk::ImageToImageFilter<TInputImageType, MaskImageType>()
45 {
46   this->SetNumberOfRequiredInputs(1);
47   SetBackgroundValue(0); // Must be zero
48   SetForegroundValue(1);
49
50   // Step 1: Threshold + CC + sort (Find low density areas)
51   SetUpperThreshold(-300);
52   SetLowerThreshold(-1000);
53   UseLowerThresholdOff();
54
55   // Step 2: DecomposeAndReconstructImageFilter (optional)
56   DecomposeAndReconstructDuringFirstStepOff();
57   InternalImageSizeType r;
58   r.Fill(1);
59   SetRadius1(r);
60   SetMaximumNumberOfLabels1(2);
61   SetNumberOfNewLabels1(1);
62
63   // Step 3: Remove the air (largest area).
64
65   // Step 4: 2nd DecomposeAndReconstructImageFilter
66   DecomposeAndReconstructDuringSecondStepOff();
67   SetRadius2(r);
68   SetMaximumNumberOfLabels2(2);
69   SetNumberOfNewLabels2(1);
70   
71   // Step 5: Only keep label corresponding (Keep patient's labels)
72   SetFirstKeep(1);
73   SetLastKeep(1);
74   
75   // Step 4: OpenClose (option)
76   FinalOpenCloseOff();
77   AutoCropOn();
78 }
79 //--------------------------------------------------------------------
80
81
82 //--------------------------------------------------------------------
83 template <class TInputImageType>
84 void 
85 clitk::ExtractPatientFilter<TInputImageType>::
86 SetInput(const TInputImageType * image) 
87 {
88   this->SetNthInput(0, const_cast<TInputImageType *>(image));
89 }
90 //--------------------------------------------------------------------
91
92
93 //--------------------------------------------------------------------
94 template <class TInputImageType>
95 void 
96 clitk::ExtractPatientFilter<TInputImageType>::
97 GenerateOutputInformation() { 
98
99   clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK
100
101   Superclass::GenerateOutputInformation();
102   input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
103
104   // MaskImagePointer outputImage = this->GetOutput(0);
105 //   outputImage->SetRegions(input->GetLargestPossibleRegion());
106
107   // Get input pointers
108   static const unsigned int Dim = InputImageType::ImageDimension;
109   //input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
110     
111   //--------------------------------------------------------------------
112   //--------------------------------------------------------------------
113   // Step 1: 
114   StartNewStep("Find low densities areas");
115   typedef itk::BinaryThresholdImageFilter<InputImageType, InternalImageType> BinarizeFilterType;  
116   typename BinarizeFilterType::Pointer binarizeFilter=BinarizeFilterType::New();
117   binarizeFilter->SetInput(input);
118   if (m_UseLowerThreshold) binarizeFilter->SetLowerThreshold(GetLowerThreshold());
119   binarizeFilter->SetUpperThreshold(GetUpperThreshold());
120   binarizeFilter ->SetInsideValue(this->GetForegroundValue());
121   binarizeFilter ->SetOutsideValue(this->GetBackgroundValue());
122
123   // Connected component labeling
124   typedef itk::ConnectedComponentImageFilter<InternalImageType, InternalImageType> ConnectFilterType;
125   typename ConnectFilterType::Pointer connectFilter=ConnectFilterType::New();
126   connectFilter->SetInput(binarizeFilter->GetOutput());
127   connectFilter->SetBackgroundValue(this->GetBackgroundValue());
128   connectFilter->SetFullyConnected(false);
129   
130   // Sort labels according to size
131   typedef itk::RelabelComponentImageFilter<InternalImageType, InternalImageType> RelabelFilterType;
132   typename RelabelFilterType::Pointer relabelFilter=RelabelFilterType::New();
133   relabelFilter->InPlaceOn();
134   relabelFilter->SetInput(connectFilter->GetOutput());
135   relabelFilter->Update();
136   working_image = relabelFilter->GetOutput();
137   
138   // End
139   StopCurrentStep<InternalImageType>(working_image);
140
141   //--------------------------------------------------------------------
142   //--------------------------------------------------------------------
143   // [Optional] 
144   if (GetDecomposeAndReconstructDuringFirstStep()) {
145     StartNewStep("First Decompose & Reconstruct step");
146     typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> FilterType;
147     typename FilterType::Pointer f = FilterType::New();
148     f->SetInput(working_image);
149     // f->SetVerbose(m_Verbose);
150     f->SetRadius(GetRadius1());
151     f->SetMaximumNumberOfLabels(GetMaximumNumberOfLabels1());
152     f->SetBackgroundValue(this->GetBackgroundValue());
153     f->SetForegroundValue(this->GetForegroundValue());
154     f->SetFullyConnected(true);
155     f->SetNumberOfNewLabels(GetNumberOfNewLabels1());
156     f->Update();
157     working_image = f->GetOutput();
158     StopCurrentStep<InternalImageType>(working_image);
159   }
160   
161   //--------------------------------------------------------------------
162   //--------------------------------------------------------------------
163   StartNewStep("Remove the air (largest area)");
164   typedef itk::BinaryThresholdImageFilter<InternalImageType, InternalImageType> iBinarizeFilterType;  
165   typename iBinarizeFilterType::Pointer binarizeFilter2 = iBinarizeFilterType::New();
166   binarizeFilter2->SetInput(working_image);
167   binarizeFilter2->SetLowerThreshold(GetFirstKeep());
168   binarizeFilter2->SetUpperThreshold(GetLastKeep());
169   binarizeFilter2 ->SetInsideValue(0);
170   binarizeFilter2 ->SetOutsideValue(1);
171   //  binarizeFilter2 ->Update(); // NEEDED ?
172
173   typename ConnectFilterType::Pointer connectFilter2 = ConnectFilterType::New();
174   connectFilter2->SetInput(binarizeFilter2->GetOutput());
175   connectFilter2->SetBackgroundValue(this->GetBackgroundValue());
176   connectFilter2->SetFullyConnected(false);
177
178   typename RelabelFilterType::Pointer relabelFilter2 = RelabelFilterType::New();
179   relabelFilter2->SetInput(connectFilter2->GetOutput());
180   relabelFilter2->Update();
181   working_image = relabelFilter2->GetOutput();
182   
183   // Keep main label
184   working_image = KeepLabels<InternalImageType>
185     (working_image, GetBackgroundValue(), GetForegroundValue(), 1, 1, true);  
186   StopCurrentStep<InternalImageType>(working_image);
187
188   //--------------------------------------------------------------------
189   //--------------------------------------------------------------------
190   // [Optional] 
191   if (GetDecomposeAndReconstructDuringSecondStep()) {
192     StartNewStep("Second Decompose & Reconstruct step");
193     typedef clitk::DecomposeAndReconstructImageFilter<InternalImageType,InternalImageType> FilterType;
194     typename FilterType::Pointer f = FilterType::New();
195     f->SetInput(working_image);
196     // f->SetVerbose(m_Verbose);
197     f->SetRadius(GetRadius2());
198     f->SetMaximumNumberOfLabels(GetMaximumNumberOfLabels2());
199     f->SetBackgroundValue(this->GetBackgroundValue());
200     f->SetForegroundValue(this->GetForegroundValue());
201     f->SetFullyConnected(true);
202     f->SetNumberOfNewLabels(GetNumberOfNewLabels2());
203     f->Update();
204     working_image = f->GetOutput();
205     StopCurrentStep<InternalImageType>(working_image);
206   }
207
208   //--------------------------------------------------------------------
209   //--------------------------------------------------------------------
210   // [Optional]
211   if (GetFinalOpenClose()) {
212     StartNewStep("Final OpenClose");
213     // Open
214     typedef itk::BinaryBallStructuringElement<InternalPixelType,Dim> KernelType;
215     KernelType structuringElement;
216     structuringElement.SetRadius(1);
217     structuringElement.CreateStructuringElement();
218     typedef itk::BinaryMorphologicalOpeningImageFilter<InternalImageType, InternalImageType , KernelType> OpenFilterType;
219     typename OpenFilterType::Pointer openFilter = OpenFilterType::New();
220     openFilter->SetInput(working_image);
221     openFilter->SetBackgroundValue(this->GetBackgroundValue());
222     openFilter->SetForegroundValue(this->GetForegroundValue());
223     openFilter->SetKernel(structuringElement);  
224     // Close
225     typedef itk::BinaryMorphologicalClosingImageFilter<InternalImageType, InternalImageType , KernelType> CloseFilterType;
226     typename CloseFilterType::Pointer closeFilter = CloseFilterType::New();
227     closeFilter->SetInput(openFilter->GetOutput());
228     closeFilter->SetSafeBorder(true);
229     closeFilter->SetForegroundValue(this->GetForegroundValue());
230     //  closeFilter->SetBackgroundValue(SetBackgroundValue());
231     closeFilter->SetKernel(structuringElement);
232     closeFilter->Update();  
233     working_image = closeFilter->GetOutput();
234     StopCurrentStep<InternalImageType>(working_image);
235   }
236
237   //--------------------------------------------------------------------
238   //--------------------------------------------------------------------
239   // Final Cast 
240   typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
241   typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
242   caster->SetInput(working_image);
243   caster->Update();
244   output = caster->GetOutput();
245
246   //--------------------------------------------------------------------
247   //--------------------------------------------------------------------
248   // [Optional]
249   if (GetAutoCrop()) {
250   StartNewStep("AutoCrop");
251     typedef clitk::AutoCropFilter<MaskImageType> CropFilterType;
252     typename CropFilterType::Pointer cropFilter = CropFilterType::New();
253     cropFilter->SetInput(output);
254     cropFilter->SetBackgroundValue(GetBackgroundValue());
255     cropFilter->Update();   
256     output = cropFilter->GetOutput();
257     StopCurrentStep<MaskImageType>(output);
258   }
259 }
260 //--------------------------------------------------------------------
261
262
263 //--------------------------------------------------------------------
264 template <class TInputImageType>
265 void 
266 clitk::ExtractPatientFilter<TInputImageType>::
267 GenerateData() {
268   // Final Graft
269   this->GraftOutput(output);
270   // Store image filename into AFDB
271   GetAFDB()->SetImageFilename("Patient", this->GetOutputPatientFilename());  
272   WriteAFDB();
273 }
274 //--------------------------------------------------------------------
275   
276
277 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX