]> Creatis software - clitk.git/blobdiff - itk/clitkSliceBySliceRelativePositionFilter.txx
Add Extrude option to clitkMeshToBinaryImageFilter
[clitk.git] / itk / clitkSliceBySliceRelativePositionFilter.txx
index af9c4c5c35f3378e5d0c6e90c1da399c224acfab..0548146d2051ffe0b61289dc2d07fbf52d6af95b 100644 (file)
 
 // 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);
+  UniqueConnectedComponentBySliceFlagOff();
+  SetIgnoreEmptySliceObjectFlag(false);
+  UseTheLargestObjectCCLFlagOff();
+  this->VerboseStepFlagOff();
+  this->WriteStepFlagOff();
+  this->SetCombineWithOrFlag(false);
+  ObjectCCLSelectionFlagOff();
+  SetObjectCCLSelectionDimension(0);
+  SetObjectCCLSelectionDirection(1);
+  ObjectCCLSelectionIgnoreSingleCCLFlagOff();
 }
 //--------------------------------------------------------------------
 
@@ -54,7 +49,8 @@ SliceBySliceRelativePositionFilter():
 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));
 }
@@ -65,7 +61,8 @@ SetInput(const 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));
 }
@@ -76,10 +73,25 @@ SetInputObject(const 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(std::ostream & os) 
+{
+  os << "Slice direction = " << this->GetDirection() << std::endl
+     << "BG value        = " << this->GetBackgroundValue() << std::endl;
+  for(int i=0; i<this->GetNumberOfAngles(); i++)
+    os << "Orientation     = " << this->GetOrientationTypeString()[i] << std::endl;
+  os << "InverseOrientationFlag  = " << this->GetInverseOrientationFlag() << std::endl        
+     << "SpacingFlag     = " << this->GetIntermediateSpacingFlag() << std::endl
+     << "Spacing         = " << this->GetIntermediateSpacing() << std::endl
+     << "FuzzyThreshold  = " << this->GetFuzzyThreshold() << std::endl
+     << "UniqueConnectedComponentBySliceFlag  = " << this->GetUniqueConnectedComponentBySliceFlag() << std::endl
+     << "AutoCropFlag    = " << this->GetAutoCropFlag() << std::endl    
+     << "RemoveObjectFlag= " << this->GetRemoveObjectFlag() << std::endl    
+     << "CombineWithOrFlag = " << this->GetCombineWithOrFlag() << std::endl    
+     << "UseTheLargestObjectCCLFlag = " << this->GetUseTheLargestObjectCCLFlag() << std::endl    
+     << "ObjectCCLSelectionFlag = " << this->GetObjectCCLSelectionFlag() << std::endl    
+     << "ObjectCCLSelectionDimension = " << this->GetObjectCCLSelectionDimension() << std::endl    
+     << "ObjectCCLSelectionIgnoreSingleCCLFlag = " << this->GetObjectCCLSelectionIgnoreSingleCCLFlag() << std::endl    
+     << "IgnoreEmptySliceObjectFlag = " << this->GetIgnoreEmptySliceObjectFlag() << std::endl;    
 }
 //--------------------------------------------------------------------
 
@@ -88,7 +100,8 @@ GenerateOutputInformation() {
 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
@@ -99,12 +112,17 @@ GenerateInputRequestedRegion() {
 }
 //--------------------------------------------------------------------
 
-  
+
 //--------------------------------------------------------------------
 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));
@@ -112,91 +130,186 @@ GenerateData() {
   //--------------------------------------------------------------------
   // 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 (GetUseTheLargestObjectCCLFlag()) {
+        mObjectSlices[i] = KeepLabels<SliceType>(mObjectSlices[i], 0, 1, 1, 1, true);
+      }
+
+      // Select a single according to a position if more than one CCL
+      if (GetObjectCCLSelectionFlag()) {
+        // if several CCL, choose the most extrema according a direction, 
+        // if not -> should we consider this slice ? 
+        if (nb<2) {
+          if (GetObjectCCLSelectionIgnoreSingleCCLFlag()) {
+            mObjectSlices[i] = SetBackground<SliceType, SliceType>(mObjectSlices[i], mObjectSlices[i], 
+                                                                   1, this->GetBackgroundValue(), 
+                                                                   true);
+          }
+        }
+        int dim = GetObjectCCLSelectionDimension();
+        int direction = GetObjectCCLSelectionDirection();
+        std::vector<typename SliceType::PointType> centroids;
+        ComputeCentroids<SliceType>(mObjectSlices[i], this->GetBackgroundValue(), centroids);
+        uint index=1;
+        for(uint j=1; j<centroids.size(); j++) {
+          if (direction == 1) {
+            if (centroids[j][dim] > centroids[index][dim]) index = j;
+          }
+          else {
+            if (centroids[j][dim] < centroids[index][dim]) index = j;
+          }
+        }
+        for(uint v=1; v<centroids.size(); v++) {
+          if (v != index) {
+            mObjectSlices[i] = SetBackground<SliceType, SliceType>(mObjectSlices[i], mObjectSlices[i], 
+                                                                   (char)v, this->GetBackgroundValue(), 
+                                                                   true);
+          }
+        }
+      } // end GetbjectCCLSelectionFlag = 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());
+      // This flag (InverseOrientation) *must* be set before
+      // AddOrientation because AddOrientation can change it.
+      relPosFilter->SetInverseOrientationFlag(this->GetInverseOrientationFlag());
+      for(int j=0; j<this->GetNumberOfAngles(); j++) {
+        relPosFilter->AddOrientationTypeString(this->GetOrientationTypeString(j));
+        //DD(this->GetOrientationTypeString(j));
+      }
+      //DD(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 (GetUniqueConnectedComponentBySliceFlag()) {
+        mInputSlices[i] = Labelize<SliceType>(mInputSlices[i], 0, true, 1);
+        mInputSlices[i] = KeepLabels<SliceType>(mInputSlices[i], 0, 1, 1, 1, true);
+      }
+
+      /*
+      // Select unique CC according to the most in a given direction
+      if (GetUniqueConnectedComponentBySliceAccordingToADirection()) {
+        int nb;
+        mInputSlices[i] = LabelizeAndCountNumberOfObjects<SliceType>(mInputSlices[i], 0, true, 1, nb);
+        std::vector<typename ImageType::PointType> & centroids;
+        ComputeCentroids
+        }
+      */
+    }
   }
-  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;
 }
 //--------------------------------------------------------------------