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 CLITKEXTRACTPATIENTFILTER_TXX
20 #define CLITKEXTRACTPATIENTFILTER_TXX
23 #include "clitkImageCommon.h"
24 #include "clitkSetBackgroundImageFilter.h"
25 #include "clitkDecomposeAndReconstructImageFilter.h"
26 #include "clitkAutoCropFilter.h"
27 #include "clitkMemoryUsage.h"
28 #include "clitkSegmentationUtils.h"
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"
39 //--------------------------------------------------------------------
40 template <class TInputImageType>
41 clitk::ExtractPatientFilter<TInputImageType>::
42 ExtractPatientFilter():
44 clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
45 itk::ImageToImageFilter<TInputImageType, MaskImageType>()
47 this->SetNumberOfRequiredInputs(1);
48 SetBackgroundValue(0); // Must be zero
49 SetForegroundValue(1);
51 // Step 1: Threshold + CC + sort (Find low density areas)
52 SetUpperThreshold(-300);
53 SetLowerThreshold(-1000);
54 UseLowerThresholdOff();
56 // Step 2: DecomposeAndReconstructImageFilter (optional)
57 DecomposeAndReconstructDuringFirstStepOff();
58 InternalImageSizeType r;
61 SetMaximumNumberOfLabels1(2);
62 SetNumberOfNewLabels1(1);
64 // Step 3: Remove the air (largest area).
66 // Step 4: 2nd DecomposeAndReconstructImageFilter
67 DecomposeAndReconstructDuringSecondStepOff();
69 SetMaximumNumberOfLabels2(2);
70 SetNumberOfNewLabels2(1);
72 // Step 5: Only keep label corresponding (Keep patient's labels)
76 // Step 4: OpenClose (option)
80 //--------------------------------------------------------------------
83 //--------------------------------------------------------------------
84 template <class TInputImageType>
86 clitk::ExtractPatientFilter<TInputImageType>::
87 SetInput(const TInputImageType * image)
89 this->SetNthInput(0, const_cast<TInputImageType *>(image));
91 //--------------------------------------------------------------------
94 //--------------------------------------------------------------------
95 template <class TInputImageType>
97 clitk::ExtractPatientFilter<TInputImageType>::
98 GenerateOutputInformation() {
100 clitk::PrintMemory(GetVerboseMemoryFlag(), "Initial memory"); // OK
102 Superclass::GenerateOutputInformation();
103 input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
105 // MaskImagePointer outputImage = this->GetOutput(0);
106 // outputImage->SetRegions(input->GetLargestPossibleRegion());
108 // Get input pointers
109 static const unsigned int Dim = InputImageType::ImageDimension;
110 //input = dynamic_cast<const TInputImageType*>(itk::ProcessObject::GetInput(0));
112 //--------------------------------------------------------------------
113 //--------------------------------------------------------------------
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());
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);
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();
140 StopCurrentStep<InternalImageType>(working_image);
142 //--------------------------------------------------------------------
143 //--------------------------------------------------------------------
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());
158 working_image = f->GetOutput();
159 StopCurrentStep<InternalImageType>(working_image);
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 ?
174 typename ConnectFilterType::Pointer connectFilter2 = ConnectFilterType::New();
175 connectFilter2->SetInput(binarizeFilter2->GetOutput());
176 connectFilter2->SetBackgroundValue(this->GetBackgroundValue());
177 connectFilter2->SetFullyConnected(false);
179 typename RelabelFilterType::Pointer relabelFilter2 = RelabelFilterType::New();
180 relabelFilter2->SetInput(connectFilter2->GetOutput());
181 relabelFilter2->Update();
182 working_image = relabelFilter2->GetOutput();
185 working_image = KeepLabels<InternalImageType>
186 (working_image, GetBackgroundValue(), GetForegroundValue(), 1, 1, true);
187 StopCurrentStep<InternalImageType>(working_image);
189 //--------------------------------------------------------------------
190 //--------------------------------------------------------------------
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());
205 working_image = f->GetOutput();
206 StopCurrentStep<InternalImageType>(working_image);
209 //--------------------------------------------------------------------
210 //--------------------------------------------------------------------
212 if (GetFinalOpenClose()) {
213 StartNewStep("Final OpenClose");
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);
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);
238 //--------------------------------------------------------------------
239 //--------------------------------------------------------------------
241 typedef itk::CastImageFilter<InternalImageType, MaskImageType> CastImageFilterType;
242 typename CastImageFilterType::Pointer caster= CastImageFilterType::New();
243 caster->SetInput(working_image);
245 output = caster->GetOutput();
247 //--------------------------------------------------------------------
248 //--------------------------------------------------------------------
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);
261 //--------------------------------------------------------------------
264 //--------------------------------------------------------------------
265 template <class TInputImageType>
267 clitk::ExtractPatientFilter<TInputImageType>::
270 this->GraftOutput(output);
271 // Store image filename into AFDB
272 GetAFDB()->SetImageFilename("Patient", this->GetOutputPatientFilename());
275 //--------------------------------------------------------------------
278 #endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX