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 UseASingleObjectConnectedComponentBySliceFlagOn();
37 this->VerboseStepFlagOff();
38 this->WriteStepFlagOff();
39 this->SetCombineWithOrFlag(false);
41 //--------------------------------------------------------------------
44 //--------------------------------------------------------------------
45 template <class ImageType>
47 clitk::SliceBySliceRelativePositionFilter<ImageType>::
48 SetInput(const ImageType * image)
50 // Process object is not const-correct so the const casting is required.
51 this->SetNthInput(0, const_cast<ImageType *>(image));
53 //--------------------------------------------------------------------
56 //--------------------------------------------------------------------
57 template <class ImageType>
59 clitk::SliceBySliceRelativePositionFilter<ImageType>::
60 SetInputObject(const ImageType * image)
62 // Process object is not const-correct so the const casting is required.
63 this->SetNthInput(1, const_cast<ImageType *>(image));
65 //--------------------------------------------------------------------
68 //--------------------------------------------------------------------
69 template <class ImageType>
71 clitk::SliceBySliceRelativePositionFilter<ImageType>::
74 DD(this->GetDirection());
75 DD((int)this->GetObjectBackgroundValue());
76 DDV(this->GetOrientationTypeString(), (uint)this->GetNumberOfAngles());
77 DD(this->GetIntermediateSpacingFlag());
78 DD(this->GetIntermediateSpacing());
79 DD(this->GetFuzzyThreshold());
80 DD(this->GetUniqueConnectedComponentBySlice());
81 DD(this->GetAutoCropFlag());
82 DD(this->GetInverseOrientationFlag());
83 DD(this->GetRemoveObjectFlag());
84 DD(this->GetCombineWithOrFlag());
86 //--------------------------------------------------------------------
89 //--------------------------------------------------------------------
90 template <class ImageType>
92 clitk::SliceBySliceRelativePositionFilter<ImageType>::
93 GenerateInputRequestedRegion()
96 itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
97 // Get input pointers and set requested region to common region
98 ImagePointer input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
99 ImagePointer input2 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
100 input1->SetRequestedRegion(input1->GetLargestPossibleRegion());
101 input2->SetRequestedRegion(input2->GetLargestPossibleRegion());
103 //--------------------------------------------------------------------
106 //--------------------------------------------------------------------
107 template <class ImageType>
109 clitk::SliceBySliceRelativePositionFilter<ImageType>::
110 GenerateOutputInformation()
112 if (this->GetVerboseOptionFlag()) {
117 input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
118 object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
120 //--------------------------------------------------------------------
121 // Resample object to the same spacing than input
122 if (!clitk::HaveSameSpacing<ImageType, ImageType>(object, input)) {
123 this->StartNewStep("Resample object to the same spacing than input");
124 m_working_object = clitk::ResampleImageSpacing<ImageType>(object, input->GetSpacing());
125 this->template StopCurrentStep<ImageType>(m_working_object);
128 m_working_object = object;
131 //--------------------------------------------------------------------
132 // Pad object to the same size than input
133 if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(m_working_object, input)) {
134 this->StartNewStep("Pad object to the same size than input");
135 m_working_object = clitk::ResizeImageLike<ImageType>(m_working_object,
137 this->GetObjectBackgroundValue());
138 this->template StopCurrentStep<ImageType>(m_working_object);
144 - extract vector of slices in input, in object
145 - slice by slice rel position
151 //--------------------------------------------------------------------
152 // Extract input slices
153 this->StartNewStep("Extract input slices");
154 typedef clitk::ExtractSliceFilter<ImageType> ExtractSliceFilterType;
155 typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
156 extractSliceFilter->SetInput(input);
157 extractSliceFilter->SetDirection(GetDirection());
158 extractSliceFilter->Update();
159 typedef typename ExtractSliceFilterType::SliceType SliceType;
160 std::vector<typename SliceType::Pointer> mInputSlices;
161 extractSliceFilter->GetOutputSlices(mInputSlices);
162 this->template StopCurrentStep<SliceType>(mInputSlices[0]);
164 //--------------------------------------------------------------------
165 // Extract object slices
166 this->StartNewStep("Extract object slices");
167 extractSliceFilter = ExtractSliceFilterType::New();
168 extractSliceFilter->SetInput(m_working_object);//object);
169 extractSliceFilter->SetDirection(GetDirection());
170 extractSliceFilter->Update();
171 std::vector<typename SliceType::Pointer> mObjectSlices;
172 extractSliceFilter->GetOutputSlices(mObjectSlices);
173 this->template StopCurrentStep<SliceType>(mObjectSlices[0]);
175 //--------------------------------------------------------------------
176 // Perform slice by slice relative position
177 this->StartNewStep("Perform slice by slice relative position");
178 for(unsigned int i=0; i<mInputSlices.size(); i++) {
180 // Count the number of CCL (allow to ignore empty slice)
182 mObjectSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mObjectSlices[i], 0, true, 1, nb);
183 if ((!GetIgnoreEmptySliceObjectFlag()) || (nb!=0)) {
185 // Select or not a single CCL ?
186 if (GetUseASingleObjectConnectedComponentBySliceFlag()) {
187 mObjectSlices[i] = KeepLabels<SliceType>(mObjectSlices[i], 0, 1, 1, 1, true);
191 typedef clitk::AddRelativePositionConstraintToLabelImageFilter<SliceType> RelPosFilterType;
192 typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
194 relPosFilter->VerboseStepFlagOff();
195 relPosFilter->WriteStepFlagOff();
196 relPosFilter->SetBackgroundValue(this->GetBackgroundValue());
197 relPosFilter->SetInput(mInputSlices[i]);
198 relPosFilter->SetInputObject(mObjectSlices[i]);
199 relPosFilter->SetRemoveObjectFlag(this->GetRemoveObjectFlag());
200 for(int j=0; j<this->GetNumberOfAngles(); j++) {
201 relPosFilter->AddOrientationTypeString(this->GetOrientationTypeString(j));
203 relPosFilter->SetInverseOrientationFlag(this->GetInverseOrientationFlag());
204 //relPosFilter->SetOrientationType(this->GetOrientationType());
205 relPosFilter->SetIntermediateSpacing(this->GetIntermediateSpacing());
206 relPosFilter->SetIntermediateSpacingFlag(this->GetIntermediateSpacingFlag());
207 relPosFilter->SetFuzzyThreshold(this->GetFuzzyThreshold());
208 relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop
209 relPosFilter->SetCombineWithOrFlag(this->GetCombineWithOrFlag());
210 relPosFilter->Update();
211 mInputSlices[i] = relPosFilter->GetOutput();
213 // Select main CC if needed
214 if (GetUniqueConnectedComponentBySlice()) {
215 mInputSlices[i] = Labelize<SliceType>(mInputSlices[i], 0, true, 1);
216 mInputSlices[i] = KeepLabels<SliceType>(mInputSlices[i], 0, 1, 1, 1, true);
223 m_working_input = clitk::JoinSlices<ImageType>(mInputSlices, input, GetDirection());
224 this->template StopCurrentStep<ImageType>(m_working_input);
226 //--------------------------------------------------------------------
228 if (this->GetAutoCropFlag()) {
229 this->StartNewStep("Final AutoCrop");
230 typedef clitk::AutoCropFilter<ImageType> CropFilterType;
231 typename CropFilterType::Pointer cropFilter = CropFilterType::New();
232 cropFilter->SetInput(m_working_input);
233 cropFilter->ReleaseDataFlagOff();
234 cropFilter->Update();
235 m_working_input = cropFilter->GetOutput();
236 this->template StopCurrentStep<ImageType>(m_working_input);
239 // Update output info
240 this->GetOutput(0)->SetRegions(m_working_input->GetLargestPossibleRegion());
242 //--------------------------------------------------------------------
245 //--------------------------------------------------------------------
246 template <class ImageType>
248 clitk::SliceBySliceRelativePositionFilter<ImageType>::
252 //--------------------------------------------------------------------
253 //--------------------------------------------------------------------
254 // Final Step -> set output
255 //this->SetNthOutput(0, m_working_input);
256 this->GraftOutput(m_working_input);
259 //--------------------------------------------------------------------