]> Creatis software - clitk.git/blobdiff - segmentation/clitkExtractLymphStationsFilter.txx.save
merge cvs -> git
[clitk.git] / segmentation / clitkExtractLymphStationsFilter.txx.save
diff --git a/segmentation/clitkExtractLymphStationsFilter.txx.save b/segmentation/clitkExtractLymphStationsFilter.txx.save
new file mode 100644 (file)
index 0000000..a7b3244
--- /dev/null
@@ -0,0 +1,289 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#ifndef CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
+#define CLITKEXTRACTLYMPHSTATIONSFILTER_TXX
+
+// clitk
+#include "clitkCommon.h"
+#include "clitkExtractLymphStationsFilter.h"
+#include "clitkAddRelativePositionConstraintToLabelImageFilter.h"
+#include "clitkSegmentationUtils.h"
+#include "clitkAutoCropFilter.h"
+#include "clitkSegmentationUtils.h"
+#include "clitkSliceBySliceRelativePositionFilter.h"
+
+// itk
+#include <itkStatisticsLabelMapFilter.h>
+#include <itkLabelImageToStatisticsLabelMapFilter.h>
+#include <itkRegionOfInterestImageFilter.h>
+#include <itkBinaryThresholdImageFilter.h>
+#include <itkImageSliceConstIteratorWithIndex.h>
+#include <itkBinaryThinningImageFilter.h>
+
+// itk ENST
+#include "RelativePositionPropImageFilter.h"
+
+//--------------------------------------------------------------------
+template <class TImageType>
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractLymphStationsFilter():
+  clitk::FilterBase(),
+  clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
+  itk::ImageToImageFilter<TImageType, MaskImageType>()
+{
+  this->SetNumberOfRequiredInputs(1);
+  SetBackgroundValue(0);
+  SetForegroundValue(1);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateOutputInformation() { 
+  //  Superclass::GenerateOutputInformation();
+  
+  // Get input
+  LoadAFDB();
+  m_mediastinum = GetAFDB()->template GetImage <MaskImageType>("mediastinum");  
+  m_trachea = GetAFDB()->template GetImage <MaskImageType>("trachea");  
+  ImagePointType carina;
+  GetAFDB()->GetPoint3D("carina", carina);
+  DD(carina);
+  m_CarinaZPositionInMM = carina[2];
+  DD(m_CarinaZPositionInMM);
+  ImagePointType mlb;
+  GetAFDB()->GetPoint3D("middleLobeBronchus", mlb);
+  m_MiddleLobeBronchusZPositionInMM = mlb[2];
+  DD(m_MiddleLobeBronchusZPositionInMM);
+
+  // ----------------------------------------------------------------
+  // ----------------------------------------------------------------
+  // Superior limit = carina
+  // Inferior limit = origin right middle lobe bronchus
+  StartNewStep("Inf/Sup mediastinum limits with carina/bronchus");
+  ImageRegionType region = m_mediastinum->GetLargestPossibleRegion(); DD(region);
+  ImageSizeType size = region.GetSize();
+  ImageIndexType index = region.GetIndex();
+  DD(m_CarinaZPositionInMM);
+  DD(m_MiddleLobeBronchusZPositionInMM);
+  index[2] = floor((m_MiddleLobeBronchusZPositionInMM - m_mediastinum->GetOrigin()[2]) / m_mediastinum->GetSpacing()[2]);
+  size[2] = 1+ceil((m_CarinaZPositionInMM-m_MiddleLobeBronchusZPositionInMM) / m_mediastinum->GetSpacing()[2]); // +1 to 
+  region.SetSize(size);
+  region.SetIndex(index);
+  DD(region);
+  typedef itk::RegionOfInterestImageFilter<MaskImageType, MaskImageType> CropFilterType;
+  typename CropFilterType::Pointer cropFilter = CropFilterType::New();
+  cropFilter->SetInput(m_mediastinum);
+  cropFilter->SetRegionOfInterest(region);
+  cropFilter->Update();
+  m_working_image = cropFilter->GetOutput();
+  // Auto Crop (because following rel pos is faster)
+  m_working_image = clitk::AutoCrop<MaskImageType>(m_working_image, 0); 
+  StopCurrentStep<MaskImageType>(m_working_image);
+  m_output = m_working_image;
+
+  // ----------------------------------------------------------------
+  // ----------------------------------------------------------------
+  // Separate trachea in two CCL
+  StartNewStep("Separate trachea under carina");
+  // DD(region);
+  ImageRegionType trachea_region = m_trachea->GetLargestPossibleRegion();
+  for(int i=0; i<3; i++) {
+    index[i] = floor(((index[i]*m_mediastinum->GetSpacing()[i])+m_mediastinum->GetOrigin()[i]
+                      -m_trachea->GetOrigin()[i])/m_trachea->GetSpacing()[i]);
+    // DD(index[i]);
+    size[i] = ceil((size[i]*m_mediastinum->GetSpacing()[i])/m_trachea->GetSpacing()[i]);
+    //  DD(size[i]);
+    if (index[i] < 0) { 
+      size[i] += index[i];
+      index[i] = 0;       
+    }
+    if (size[i]+index[i] > (trachea_region.GetSize()[i] + trachea_region.GetIndex()[i])) {
+      size[i] = trachea_region.GetSize()[i] + trachea_region.GetIndex()[i] - index[i];
+    }
+  }
+  // DD(index);
+  //   DD(size);
+  region.SetIndex(index);
+  region.SetSize(size);  
+  //  typedef itk::RegionOfInterestImageFilter<MaskImageType, MaskImageType> CropFilterType;
+  //  typename CropFilterType::Pointer 
+  cropFilter = CropFilterType::New();
+ //  m_trachea.Print(std::cout);
+  cropFilter->SetInput(m_trachea);
+  cropFilter->SetRegionOfInterest(region);
+  cropFilter->Update();
+  m_working_trachea = cropFilter->GetOutput();
+
+  // Labelize and consider two main labels
+  m_working_trachea = Labelize<MaskImageType>(m_working_trachea, 0, true, 1);
+
+  // Detect wich label is at Left
+  typedef itk::ImageSliceConstIteratorWithIndex<MaskImageType> SliceIteratorType;
+  SliceIteratorType iter(m_working_trachea, m_working_trachea->GetLargestPossibleRegion());
+  iter.SetFirstDirection(0);
+  iter.SetSecondDirection(1);
+  iter.GoToBegin();
+  bool stop = false;
+  ImagePixelType leftLabel;
+  ImagePixelType rightLabel;
+  while (!stop) {
+    if (iter.Get() != GetBackgroundValue()) {
+      //     DD(iter.GetIndex());
+      //       DD((int)iter.Get());
+      leftLabel = iter.Get();
+      stop = true;
+    }
+    ++iter;
+  }
+  if (leftLabel == 1) rightLabel = 2;
+  else rightLabel = 1;
+  DD((int)leftLabel);
+  DD((int)rightLabel);  
+
+  // End step
+  StopCurrentStep<MaskImageType>(m_working_trachea);
+  
+  //-----------------------------------------------------
+  /*  DD("TEST Skeleton");
+  typedef itk::BinaryThinningImageFilter<MaskImageType, MaskImageType> SkeletonFilterType;
+  typename SkeletonFilterType::Pointer skeletonFilter = SkeletonFilterType::New();
+  skeletonFilter->SetInput(m_working_trachea);
+  skeletonFilter->Update();
+  writeImage<MaskImageType>(skeletonFilter->GetOutput(), "skel.mhd");
+  writeImage<MaskImageType>(skeletonFilter->GetThinning(), "skel2.mhd");  
+  */
+
+  //-----------------------------------------------------
+  StartNewStep("Left limits with bronchus (slice by slice)");  
+  // Select LeftLabel (set right label to 0)
+  MaskImagePointer temp = SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea, rightLabel, 0);
+  writeImage<MaskImageType>(temp, "temp1.mhd");
+
+  m_working_image = 
+    clitk::SliceBySliceRelativePosition<MaskImageType>(m_working_image, 
+                                                      temp, 
+                                                      2, GetFuzzyThreshold(), "RightTo");
+  /*
+  typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
+  typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
+  sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  sliceRelPosFilter->VerboseStepOn();
+  sliceRelPosFilter->WriteStepOn();
+  sliceRelPosFilter->SetInput(m_working_image);
+  sliceRelPosFilter->SetInputObject(temp);
+  sliceRelPosFilter->SetDirection(2);
+  sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold());
+  sliceRelPosFilter->SetOrientationTypeString("RightTo");
+  sliceRelPosFilter->Update();
+  m_working_image = sliceRelPosFilter->GetOutput();*/
+  writeImage<MaskImageType>(m_working_image, "afterslicebyslice.mhd");
+
+
+  typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
+  typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
+
+
+  //-----------------------------------------------------
+  StartNewStep("Right limits with bronchus (slice by slice)");
+  // Select LeftLabel (set right label to 0)
+  temp = SetBackground<MaskImageType, MaskImageType>(m_working_trachea, m_working_trachea, leftLabel, 0);
+  writeImage<MaskImageType>(temp, "temp2.mhd");
+
+  sliceRelPosFilter = SliceRelPosFilterType::New();
+  sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  sliceRelPosFilter->VerboseStepOff();
+  sliceRelPosFilter->WriteStepOff();
+  sliceRelPosFilter->SetInput(m_working_image);
+  sliceRelPosFilter->SetInputObject(temp);
+  sliceRelPosFilter->SetDirection(2);
+  sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold());
+  sliceRelPosFilter->SetOrientationTypeString("LeftTo");
+  sliceRelPosFilter->Update();
+  m_working_image = sliceRelPosFilter->GetOutput();
+  writeImage<MaskImageType>(m_working_image, "afterslicebyslice.mhd");
+  DD("end");
+  m_output = m_working_image;
+  StopCurrentStep<MaskImageType>(m_output);
+
+  //-----------------------------------------------------
+  StartNewStep("Trial Post position according to trachea");
+  // Post: do not extend past the post wall of the 2 main bronchi
+  sliceRelPosFilter = SliceRelPosFilterType::New();
+  sliceRelPosFilter->SetCurrentStepBaseId(this->GetCurrentStepId());
+  sliceRelPosFilter->VerboseStepOn();
+  sliceRelPosFilter->WriteStepOn();
+  sliceRelPosFilter->SetInput(m_output);
+  sliceRelPosFilter->SetInputObject(m_trachea);
+  sliceRelPosFilter->SetDirection(2);
+  sliceRelPosFilter->SetFuzzyThreshold(GetFuzzyThreshold());
+  // It means "not PostTo" (different from AntTo)
+  sliceRelPosFilter->NotFlagOn();
+  //sliceRelPosFilter->SetOrientationType(SliceRelPosFilterType::RelPosFilterType::PostTo);
+  sliceRelPosFilter->SetOrientationTypeString("PostTo");
+  sliceRelPosFilter->Update();
+  m_output = sliceRelPosFilter->GetOutput();
+  writeImage<MaskImageType>(m_output, "postrelpos.mhd");
+
+
+  // Set output image information (required)
+  MaskImagePointer outputImage = this->GetOutput(0);
+  outputImage->SetRegions(m_working_image->GetLargestPossibleRegion());
+  outputImage->SetOrigin(m_working_image->GetOrigin());
+  outputImage->SetRequestedRegion(m_working_image->GetLargestPossibleRegion());
+  DD("end2");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateInputRequestedRegion() {
+  DD("GenerateInputRequestedRegion");
+  // Call default
+  //  Superclass::GenerateInputRequestedRegion();
+  // Following needed because output region can be greater than input (trachea)
+  //ImagePointer mediastinum = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(0));
+  //ImagePointer trachea = dynamic_cast<TImageType*>(itk::ProcessObject::GetInput(1));
+  DD("set reg");
+  m_mediastinum->SetRequestedRegion(m_mediastinum->GetLargestPossibleRegion());
+  m_trachea->SetRequestedRegion(m_trachea->GetLargestPossibleRegion());
+  DD("end");
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void 
+clitk::ExtractLymphStationsFilter<TImageType>::
+GenerateData() {
+  DD("GenerateData");
+  // Final Step -> graft output (if SetNthOutput => redo)
+  this->GraftOutput(m_output);
+}
+//--------------------------------------------------------------------
+  
+
+#endif //#define CLITKBOOLEANOPERATORLABELIMAGEFILTER_TXX