Authors belong to:
- University of LYON http://www.universite-lyon.fr/
- - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
+ - Léon Bérard cancer center http://www.centreleonberard.fr
- CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
This software is distributed WITHOUT ANY WARRANTY; without even
- BSD See included LICENSE.txt file
- CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
- ======================================================================-====*/
+ ===========================================================================**/
// clitk
#include "clitkSegmentationUtils.h"
-// #include "clitkBooleanOperatorLabelImageFilter.h"
-// #include "clitkAutoCropFilter.h"
-// #include "clitkResampleImageWithOptionsFilter.h"
-// #include "clitkBooleanOperatorLabelImageFilter.h"
#include "clitkExtractSliceFilter.h"
+#include "clitkResampleImageWithOptionsFilter.h"
-// // itk
-// #include <deque>
-// #include "itkStatisticsLabelMapFilter.h"
-// #include "itkLabelImageToStatisticsLabelMapFilter.h"
-// #include "itkRegionOfInterestImageFilter.h"
-// #include "itkBinaryThresholdImageFilter.h"
-// #include "itkBinaryErodeImageFilter.h"
-// #include "itkBinaryBallStructuringElement.h"
-
-// // itk [Bloch et al]
-// #include "RelativePositionPropImageFilter.h"
+// itk
+#include <itkJoinSeriesImageFilter.h>
//--------------------------------------------------------------------
template <class ImageType>
clitk::SliceBySliceRelativePositionFilter<ImageType>::
SliceBySliceRelativePositionFilter():
- clitk::FilterBase(),
- itk::ImageToImageFilter<ImageType, ImageType>()
+ clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>()
{
- this->SetNumberOfRequiredInputs(2);
SetDirection(2);
- SetObjectBackgroundValue(0);
+ UniqueConnectedComponentBySliceOff();
+ SetIgnoreEmptySliceObjectFlag(false);
+ UseASingleObjectConnectedComponentBySliceFlagOn();
+ this->VerboseStepFlagOff();
+ this->WriteStepFlagOff();
+ this->SetCombineWithOrFlag(false);
}
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::SliceBySliceRelativePositionFilter<ImageType>::
-SetInput(const ImageType * image) {
+SetInput(const ImageType * image)
+{
// Process object is not const-correct so the const casting is required.
this->SetNthInput(0, const_cast<ImageType *>(image));
}
template <class ImageType>
void
clitk::SliceBySliceRelativePositionFilter<ImageType>::
-SetInputObject(const ImageType * image) {
+SetInputObject(const ImageType * image)
+{
// Process object is not const-correct so the const casting is required.
this->SetNthInput(1, const_cast<ImageType *>(image));
}
template <class ImageType>
void
clitk::SliceBySliceRelativePositionFilter<ImageType>::
-GenerateOutputInformation() {
- ImagePointer input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
- ImagePointer outputImage = this->GetOutput(0);
- outputImage->SetRegions(input->GetLargestPossibleRegion());
+PrintOptions()
+{
+ DD(this->GetDirection());
+ DD((int)this->GetObjectBackgroundValue());
+ DDV(this->GetOrientationTypeString(), (uint)this->GetNumberOfAngles());
+ DD(this->GetIntermediateSpacingFlag());
+ DD(this->GetIntermediateSpacing());
+ DD(this->GetFuzzyThreshold());
+ DD(this->GetUniqueConnectedComponentBySlice());
+ DD(this->GetAutoCropFlag());
+ DD(this->GetInverseOrientationFlag());
+ DD(this->GetRemoveObjectFlag());
+ DD(this->GetCombineWithOrFlag());
}
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::SliceBySliceRelativePositionFilter<ImageType>::
-GenerateInputRequestedRegion() {
+GenerateInputRequestedRegion()
+{
// Call default
itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
// Get input pointers and set requested region to common region
}
//--------------------------------------------------------------------
-
+
//--------------------------------------------------------------------
template <class ImageType>
void
clitk::SliceBySliceRelativePositionFilter<ImageType>::
-GenerateData() {
+GenerateOutputInformation()
+{
+ if (this->GetVerboseOptionFlag()) {
+ PrintOptions();
+ }
+
// Get input pointer
input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
object = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(1));
//--------------------------------------------------------------------
// Resample object to the same spacing than input
if (!clitk::HaveSameSpacing<ImageType, ImageType>(object, input)) {
- StartNewStep("Resample object to the same spacing than input");
+ this->StartNewStep("Resample object to the same spacing than input");
m_working_object = clitk::ResampleImageSpacing<ImageType>(object, input->GetSpacing());
- StopCurrentStep<ImageType>(m_working_object);
+ this->template StopCurrentStep<ImageType>(m_working_object);
}
else {
- DD("no resampling");
m_working_object = object;
}
//--------------------------------------------------------------------
// Pad object to the same size than input
if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(m_working_object, input)) {
- StartNewStep("Pad object to the same size than input");
- m_working_object = clitk::EnlargeImageLike<ImageType>(m_working_object,
- input,
- GetObjectBackgroundValue());
- StopCurrentStep<ImageType>(m_working_object);
+ this->StartNewStep("Pad object to the same size than input");
+ m_working_object = clitk::ResizeImageLike<ImageType>(m_working_object,
+ input,
+ this->GetObjectBackgroundValue());
+ this->template StopCurrentStep<ImageType>(m_working_object);
}
else {
- DD("no pad");
}
-
+
/*
+ - extract vector of slices in input, in object
+ - slice by slice rel position
+ - joint result
+ - post process
+ */
//--------------------------------------------------------------------
// Extract input slices
- StartNewStep("Extract input slices");
+ this->StartNewStep("Extract input slices");
typedef clitk::ExtractSliceFilter<ImageType> ExtractSliceFilterType;
- typename ExtractSliceFilterType::Pointer extractSliceFilter = Extractslicefilter::New();
+ typename ExtractSliceFilterType::Pointer extractSliceFilter = ExtractSliceFilterType::New();
extractSliceFilter->SetInput(input);
extractSliceFilter->SetDirection(GetDirection());
extractSliceFilter->Update();
typedef typename ExtractSliceFilterType::SliceType SliceType;
- std::vector<typename SliceType::Pointer> & mInputSlices = extractSliceFilter->GetOutput();
- DD(mInputSlices.size());
- StopCurrentStep<SliceType>(mInputSlices[5]);
+ std::vector<typename SliceType::Pointer> mInputSlices;
+ extractSliceFilter->GetOutputSlices(mInputSlices);
+ this->template StopCurrentStep<SliceType>(mInputSlices[0]);
//--------------------------------------------------------------------
// Extract object slices
-
- StartNewStep("Extract object slices");
- extractSliceFilter = Extractslicefilter::New();
- extractSliceFilter->SetInput(input);
+ this->StartNewStep("Extract object slices");
+ extractSliceFilter = ExtractSliceFilterType::New();
+ extractSliceFilter->SetInput(m_working_object);//object);
extractSliceFilter->SetDirection(GetDirection());
extractSliceFilter->Update();
- std::vector<typename SliceType::Pointer> & mObjectSlices = extractSliceFilter->GetOutput();
- DD(mObjectSlices.size());
- StopCurrentStep<SliceType>(mInputSlices[5]);
+ std::vector<typename SliceType::Pointer> mObjectSlices;
+ extractSliceFilter->GetOutputSlices(mObjectSlices);
+ this->template StopCurrentStep<SliceType>(mObjectSlices[0]);
-
//--------------------------------------------------------------------
// Perform slice by slice relative position
- StartNewStep("Perform slice by slice relative position");
- for(int i=0; i<mInputSlices.size(); i++) {
- DD(i);
- typedef clitk::AddRelativePositionConstraintToLabelImageFilter<SliceType> RelPosFilterType;
- typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
- relPosFilter->VerboseStepOff();
- relPosFilter->WriteStepOff();
- relPosFilter->SetInput(mInputSlices[i]);
- relPosFilter->SetInputObject(mObjectSlices[i]);
- relPosFilter->SetOrientationType(GetOrientationType());
- relPosFilter->SetIntermediateSpacing(GetIntermediateSpacing());
- relPosFilter->SetFuzzyThreshold(GetFuzzyThreshold());
- relPosFilter->Update();
- mInputSlices[i] = relPosFilter->GetOutput();
+ this->StartNewStep("Perform slice by slice relative position");
+ for(unsigned int i=0; i<mInputSlices.size(); i++) {
+
+ // Count the number of CCL (allow to ignore empty slice)
+ int nb=0;
+ mObjectSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mObjectSlices[i], 0, true, 1, nb);
+ if ((!GetIgnoreEmptySliceObjectFlag()) || (nb!=0)) {
+
+ // Select or not a single CCL ?
+ if (GetUseASingleObjectConnectedComponentBySliceFlag()) {
+ mObjectSlices[i] = KeepLabels<SliceType>(mObjectSlices[i], 0, 1, 1, 1, true);
+ }
+
+ // Relative position
+ typedef clitk::AddRelativePositionConstraintToLabelImageFilter<SliceType> RelPosFilterType;
+ typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
+
+ relPosFilter->VerboseStepFlagOff();
+ relPosFilter->WriteStepFlagOff();
+ relPosFilter->SetBackgroundValue(this->GetBackgroundValue());
+ relPosFilter->SetInput(mInputSlices[i]);
+ relPosFilter->SetInputObject(mObjectSlices[i]);
+ relPosFilter->SetRemoveObjectFlag(this->GetRemoveObjectFlag());
+ for(int j=0; j<this->GetNumberOfAngles(); j++) {
+ relPosFilter->AddOrientationTypeString(this->GetOrientationTypeString(j));
+ }
+ relPosFilter->SetInverseOrientationFlag(this->GetInverseOrientationFlag());
+ //relPosFilter->SetOrientationType(this->GetOrientationType());
+ relPosFilter->SetIntermediateSpacing(this->GetIntermediateSpacing());
+ relPosFilter->SetIntermediateSpacingFlag(this->GetIntermediateSpacingFlag());
+ relPosFilter->SetFuzzyThreshold(this->GetFuzzyThreshold());
+ relPosFilter->AutoCropFlagOff(); // important ! because we join the slices after this loop
+ relPosFilter->SetCombineWithOrFlag(this->GetCombineWithOrFlag());
+ relPosFilter->Update();
+ mInputSlices[i] = relPosFilter->GetOutput();
+
+ // Select main CC if needed
+ if (GetUniqueConnectedComponentBySlice()) {
+ mInputSlices[i] = Labelize<SliceType>(mInputSlices[i], 0, true, 1);
+ mInputSlices[i] = KeepLabels<SliceType>(mInputSlices[i], 0, 1, 1, 1, true);
+ }
+
+ }
}
- typedef itk::JoinSeriesImageFilter<SliceType, ImageType> JointSeriesFilterType;
- typename JointSeriesFilterType::Pointer jointFilter = JointSeriesFilterType::New();
- for(int i=0; i<mInputSlices.size(); i++) {
- jointFilter->SetInput(i, mInputSlices[i]);
+
+ // Join the slices
+ m_working_input = clitk::JoinSlices<ImageType>(mInputSlices, input, GetDirection());
+ this->template StopCurrentStep<ImageType>(m_working_input);
+
+ //--------------------------------------------------------------------
+ // Step 7: autocrop
+ if (this->GetAutoCropFlag()) {
+ this->StartNewStep("Final AutoCrop");
+ typedef clitk::AutoCropFilter<ImageType> CropFilterType;
+ typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+ cropFilter->SetInput(m_working_input);
+ cropFilter->ReleaseDataFlagOff();
+ cropFilter->Update();
+ m_working_input = cropFilter->GetOutput();
+ this->template StopCurrentStep<ImageType>(m_working_input);
}
- m_working_input = jointFilter->GetOutput();
- DD(m_working_input->GetSpacing());
- DD(m_working_input->GetOrigin());
- StopCurrentStep<ImageType>(m_working_input);
- */
+ // Update output info
+ this->GetOutput(0)->SetRegions(m_working_input->GetLargestPossibleRegion());
+}
+//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::SliceBySliceRelativePositionFilter<ImageType>::
+GenerateData()
+{
+ // Get input pointer
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Final Step -> set output
- this->SetNthOutput(0, m_working_input);
+ //this->SetNthOutput(0, m_working_input);
+ this->GraftOutput(m_working_input);
return;
}
//--------------------------------------------------------------------