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