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 ======================================================================-====*/
20 #include "clitkSegmentationUtils.h"
21 #include "clitkExtractSliceFilter.h"
22 #include "clitkResampleImageWithOptionsFilter.h"
25 #include <itkJoinSeriesImageFilter.h>
27 //--------------------------------------------------------------------
28 template <class ImageType>
29 clitk::SliceBySliceRelativePositionFilter<ImageType>::
30 SliceBySliceRelativePositionFilter():
31 clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>()
34 UniqueConnectedComponentBySliceOff();
35 SetIgnoreEmptySliceObjectFlag(false);
36 this->SetCombineWithOrFlag(false);
38 //--------------------------------------------------------------------
41 //--------------------------------------------------------------------
42 template <class ImageType>
44 clitk::SliceBySliceRelativePositionFilter<ImageType>::
45 SetInput(const ImageType * image)
47 // Process object is not const-correct so the const casting is required.
48 this->SetNthInput(0, const_cast<ImageType *>(image));
50 //--------------------------------------------------------------------
53 //--------------------------------------------------------------------
54 template <class ImageType>
56 clitk::SliceBySliceRelativePositionFilter<ImageType>::
57 SetInputObject(const ImageType * image)
59 // Process object is not const-correct so the const casting is required.
60 this->SetNthInput(1, const_cast<ImageType *>(image));
62 //--------------------------------------------------------------------
65 //--------------------------------------------------------------------
66 template <class ImageType>
68 clitk::SliceBySliceRelativePositionFilter<ImageType>::
71 DD(this->GetDirection());
72 DD((int)this->GetObjectBackgroundValue());
73 DDV(this->GetOrientationTypeString(), (uint)this->GetNumberOfAngles());
74 DD(this->GetIntermediateSpacingFlag());
75 DD(this->GetIntermediateSpacing());
76 DD(this->GetFuzzyThreshold());
77 DD(this->GetUniqueConnectedComponentBySlice());
78 DD(this->GetAutoCropFlag());
79 DD(this->GetInverseOrientationFlag());
80 DD(this->GetRemoveObjectFlag());
81 DD(this->GetCombineWithOrFlag());
83 //--------------------------------------------------------------------
86 //--------------------------------------------------------------------
87 template <class ImageType>
89 clitk::SliceBySliceRelativePositionFilter<ImageType>::
90 GenerateInputRequestedRegion()
93 itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
94 // Get input pointers and set requested region to common region
95 ImagePointer input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
96 ImagePointer input2 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
97 input1->SetRequestedRegion(input1->GetLargestPossibleRegion());
98 input2->SetRequestedRegion(input2->GetLargestPossibleRegion());
100 //--------------------------------------------------------------------
103 //--------------------------------------------------------------------
104 template <class ImageType>
106 clitk::SliceBySliceRelativePositionFilter<ImageType>::
107 GenerateOutputInformation()
109 if (this->GetVerboseOptionFlag()) {
114 input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
115 object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
117 //--------------------------------------------------------------------
118 // Resample object to the same spacing than input
119 if (!clitk::HaveSameSpacing<ImageType, ImageType>(object, input)) {
120 this->StartNewStep("Resample object to the same spacing than input");
121 m_working_object = clitk::ResampleImageSpacing<ImageType>(object, input->GetSpacing());
122 this->template StopCurrentStep<ImageType>(m_working_object);
125 m_working_object = object;
128 //--------------------------------------------------------------------
129 // Pad object to the same size than input
130 if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(m_working_object, input)) {
131 this->StartNewStep("Pad object to the same size than input");
132 m_working_object = clitk::ResizeImageLike<ImageType>(m_working_object,
134 this->GetObjectBackgroundValue());
135 this->template StopCurrentStep<ImageType>(m_working_object);
141 - extract vector of slices in input, in object
142 - slice by slice rel position
148 //--------------------------------------------------------------------
149 // Extract input slices
150 this->StartNewStep("Extract input slices");
151 typedef clitk::ExtractSliceFilter<ImageType> ExtractSliceFilterType;
152 typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
153 extractSliceFilter->SetInput(input);
154 extractSliceFilter->SetDirection(GetDirection());
155 extractSliceFilter->Update();
156 typedef typename ExtractSliceFilterType::SliceType SliceType;
157 std::vector<typename SliceType::Pointer> mInputSlices;
158 extractSliceFilter->GetOutputSlices(mInputSlices);
159 this->template StopCurrentStep<SliceType>(mInputSlices[0]);
161 //--------------------------------------------------------------------
162 // Extract object slices
163 this->StartNewStep("Extract object slices");
164 extractSliceFilter = ExtractSliceFilterType::New();
165 extractSliceFilter->SetInput(m_working_object);//object);
166 extractSliceFilter->SetDirection(GetDirection());
167 extractSliceFilter->Update();
168 std::vector<typename SliceType::Pointer> mObjectSlices;
169 extractSliceFilter->GetOutputSlices(mObjectSlices);
170 this->template StopCurrentStep<SliceType>(mObjectSlices[0]);
172 //--------------------------------------------------------------------
173 // Perform slice by slice relative position
174 this->StartNewStep("Perform slice by slice relative position");
175 for(unsigned int i=0; i<mInputSlices.size(); i++) {
176 // Select main CC in each object slice (required ?)
178 mObjectSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mObjectSlices[i], 0, true, 1, nb);
179 if ((!GetIgnoreEmptySliceObjectFlag()) || (nb!=0)) {
180 mObjectSlices[i] = KeepLabels<SliceType>(mObjectSlices[i], 0, 1, 1, 1, true);
183 typedef clitk::AddRelativePositionConstraintToLabelImageFilter<SliceType> RelPosFilterType;
184 typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
186 relPosFilter->VerboseStepFlagOff();
187 relPosFilter->WriteStepFlagOff();
188 relPosFilter->SetBackgroundValue(this->GetBackgroundValue());
189 relPosFilter->SetInput(mInputSlices[i]);
190 relPosFilter->SetInputObject(mObjectSlices[i]);
191 relPosFilter->SetRemoveObjectFlag(this->GetRemoveObjectFlag());
192 for(int j=0; j<this->GetNumberOfAngles(); j++) {
193 relPosFilter->AddOrientationTypeString(this->GetOrientationTypeString(j));
195 relPosFilter->SetInverseOrientationFlag(this->GetInverseOrientationFlag());
196 //relPosFilter->SetOrientationType(this->GetOrientationType());
197 relPosFilter->SetIntermediateSpacing(this->GetIntermediateSpacing());
198 relPosFilter->SetIntermediateSpacingFlag(this->GetIntermediateSpacingFlag());
199 relPosFilter->SetFuzzyThreshold(this->GetFuzzyThreshold());
200 relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop
201 relPosFilter->SetCombineWithOrFlag(this->GetCombineWithOrFlag());
202 relPosFilter->Update();
203 mInputSlices[i] = relPosFilter->GetOutput();
205 // Select main CC if needed
206 if (GetUniqueConnectedComponentBySlice()) {
207 mInputSlices[i] = Labelize<SliceType>(mInputSlices[i], 0, true, 1);
208 mInputSlices[i] = KeepLabels<SliceType>(mInputSlices[i], 0, 1, 1, 1, true);
215 m_working_input = clitk::JoinSlices<ImageType>(mInputSlices, input, GetDirection());
216 this->template StopCurrentStep<ImageType>(m_working_input);
218 //--------------------------------------------------------------------
220 if (this->GetAutoCropFlag()) {
221 this->StartNewStep("Final AutoCrop");
222 typedef clitk::AutoCropFilter<ImageType> CropFilterType;
223 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
224 cropFilter->SetInput(m_working_input);
225 cropFilter->ReleaseDataFlagOff();
226 cropFilter->Update();
227 m_working_input = cropFilter->GetOutput();
228 this->template StopCurrentStep<ImageType>(m_working_input);
231 // Update output info
232 this->GetOutput(0)->SetRegions(m_working_input->GetLargestPossibleRegion());
234 //--------------------------------------------------------------------
237 //--------------------------------------------------------------------
238 template <class ImageType>
240 clitk::SliceBySliceRelativePositionFilter<ImageType>::
244 //--------------------------------------------------------------------
245 //--------------------------------------------------------------------
246 // Final Step -> set output
247 //this->SetNthOutput(0, m_working_input);
248 this->GraftOutput(m_working_input);
251 //--------------------------------------------------------------------