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