]> Creatis software - clitk.git/blobdiff - itk/clitkSegmentationUtils.txx
Cosmetic
[clitk.git] / itk / clitkSegmentationUtils.txx
index 16c184c0d1e36ff0e3ace5cec61df5c94de295a4..24ca5194853595a1ac2b815aeeee60533f5412e1 100644 (file)
 #include <itkBinaryDilateImageFilter.h>
 #include <itkConstantPadImageFilter.h>
 #include <itkImageSliceIteratorWithIndex.h>
+#include <itkBinaryMorphologicalOpeningImageFilter.h>
+#include <itkImageDuplicator.h>
+#include <itkSignedMaurerDistanceMapImageFilter.h>
 
 namespace clitk {
 
-  //--------------------------------------------------------------------
-  template<class ImageType>
-  void ComputeBBFromImageRegion(const ImageType * image, 
-                                typename ImageType::RegionType region,
-                                typename itk::BoundingBox<unsigned long, 
-                                ImageType::ImageDimension>::Pointer bb) {
-    typedef typename ImageType::IndexType IndexType;
-    IndexType firstIndex;
-    IndexType lastIndex;
-    for(unsigned int i=0; i<image->GetImageDimension(); i++) {
-      firstIndex[i] = region.GetIndex()[i];
-      lastIndex[i] = firstIndex[i]+region.GetSize()[i];
-    }
-
-    typedef itk::BoundingBox<unsigned long, 
-                             ImageType::ImageDimension> BBType;
-    typedef typename BBType::PointType PointType;
-    PointType lastPoint;
-    PointType firstPoint;
-    image->TransformIndexToPhysicalPoint(firstIndex, firstPoint);
-    image->TransformIndexToPhysicalPoint(lastIndex, lastPoint);
-
-    bb->SetMaximum(lastPoint);
-    bb->SetMinimum(firstPoint);
-  }
-  //--------------------------------------------------------------------
-
-
-  //--------------------------------------------------------------------
-  template<int Dimension>
-  void ComputeBBIntersection(typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbo, 
-                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi1, 
-                             typename itk::BoundingBox<unsigned long, Dimension>::Pointer bbi2) {
-
-    typedef itk::BoundingBox<unsigned long, Dimension> BBType;
-    typedef typename BBType::PointType PointType;
-    PointType lastPoint;
-    PointType firstPoint;
-
-    for(unsigned int i=0; i<Dimension; i++) {
-      firstPoint[i] = std::max(bbi1->GetMinimum()[i], 
-                               bbi2->GetMinimum()[i]);
-      lastPoint[i] = std::min(bbi1->GetMaximum()[i], 
-                              bbi2->GetMaximum()[i]);
-    }
-
-    bbo->SetMaximum(lastPoint);
-    bbo->SetMinimum(firstPoint);
-  }
-  //--------------------------------------------------------------------
-
-
-  //--------------------------------------------------------------------
-  template<class ImageType>
-  void ComputeRegionFromBB(const ImageType * image, 
-                           const typename itk::BoundingBox<unsigned long, 
-                                                           ImageType::ImageDimension>::Pointer bb, 
-                           typename ImageType::RegionType & region) {
-    // Types
-    typedef typename ImageType::IndexType  IndexType;
-    typedef typename ImageType::PointType  PointType;
-    typedef typename ImageType::RegionType RegionType;
-    typedef typename ImageType::SizeType   SizeType;
-
-    // Region starting point
-    IndexType regionStart;
-    PointType start = bb->GetMinimum();
-    image->TransformPhysicalPointToIndex(start, regionStart);
-    
-    // Region size
-    SizeType regionSize;
-    PointType maxs = bb->GetMaximum();
-    PointType mins = bb->GetMinimum();
-    for(unsigned int i=0; i<ImageType::ImageDimension; i++) {
-      regionSize[i] = lrint((maxs[i] - mins[i])/image->GetSpacing()[i]);
-    }
-   
-    // Create region
-    region.SetIndex(regionStart);
-    region.SetSize(regionSize);
-  }
-  //--------------------------------------------------------------------
-
   //--------------------------------------------------------------------
   template<class ImageType, class TMaskImageType>
   typename ImageType::Pointer
@@ -310,19 +230,37 @@ namespace clitk {
 
 
   //--------------------------------------------------------------------
-  template<class ImageType>
-  typename ImageType::Pointer
-  ResizeImageLike(const ImageType * input,                       
-                  const itk::ImageBase<ImageType::ImageDimension> * like, 
-                  typename ImageType::PixelType backgroundValue) 
+  template<class MaskImageType>
+  typename MaskImageType::Pointer
+  SliceBySliceRelativePosition(const MaskImageType * input,
+                               const MaskImageType * object,
+                               int direction, 
+                               double threshold, 
+                               std::string orientation, 
+                               bool uniqueConnectedComponent, 
+                               double spacing, 
+                               bool autocropFlag, 
+                               bool singleObjectCCL) 
   {
-    typedef CropLikeImageFilter<ImageType> CropFilterType;
-    typename CropFilterType::Pointer cropFilter = CropFilterType::New();
-    cropFilter->SetInput(input);
-    cropFilter->SetCropLikeImage(like);
-    cropFilter->SetBackgroundValue(backgroundValue);
-    cropFilter->Update();
-    return cropFilter->GetOutput();  
+    typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
+    typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
+    sliceRelPosFilter->VerboseStepFlagOff();
+    sliceRelPosFilter->WriteStepFlagOff();
+    sliceRelPosFilter->SetInput(input);
+    sliceRelPosFilter->SetInputObject(object);
+    sliceRelPosFilter->SetDirection(direction);
+    sliceRelPosFilter->SetFuzzyThreshold(threshold);
+    sliceRelPosFilter->AddOrientationTypeString(orientation);
+    sliceRelPosFilter->SetIntermediateSpacingFlag((spacing != -1));
+    sliceRelPosFilter->SetIntermediateSpacing(spacing);
+    sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(uniqueConnectedComponent);
+    sliceRelPosFilter->ObjectCCLSelectionFlagOff();
+    sliceRelPosFilter->SetUseTheLargestObjectCCLFlag(singleObjectCCL);
+    //    sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); 
+    sliceRelPosFilter->SetAutoCropFlag(autocropFlag); 
+    sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
+    sliceRelPosFilter->Update();
+    return sliceRelPosFilter->GetOutput();
   }
   //--------------------------------------------------------------------
 
@@ -334,13 +272,14 @@ namespace clitk {
                                const MaskImageType * object,
                                int direction, 
                                double threshold, 
-                               std::string orientation, 
+                               double angle,
+                               bool inverseflag,
                                bool uniqueConnectedComponent, 
                                double spacing, 
                                bool autocropFlag, 
                                bool singleObjectCCL) 
   {
-    typedef SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
+    typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> SliceRelPosFilterType;
     typename SliceRelPosFilterType::Pointer sliceRelPosFilter = SliceRelPosFilterType::New();
     sliceRelPosFilter->VerboseStepFlagOff();
     sliceRelPosFilter->WriteStepFlagOff();
@@ -348,12 +287,14 @@ namespace clitk {
     sliceRelPosFilter->SetInputObject(object);
     sliceRelPosFilter->SetDirection(direction);
     sliceRelPosFilter->SetFuzzyThreshold(threshold);
-    sliceRelPosFilter->AddOrientationTypeString(orientation);
+    //    sliceRelPosFilter->AddOrientationTypeString(orientation);
+    sliceRelPosFilter->AddAnglesInRad(angle, 0.0);
     sliceRelPosFilter->SetIntermediateSpacingFlag((spacing != -1));
     sliceRelPosFilter->SetIntermediateSpacing(spacing);
-    sliceRelPosFilter->SetUniqueConnectedComponentBySlice(uniqueConnectedComponent);
-    sliceRelPosFilter->SetUseASingleObjectConnectedComponentBySliceFlag(singleObjectCCL);
-    //    sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); 
+    sliceRelPosFilter->SetUniqueConnectedComponentBySliceFlag(uniqueConnectedComponent);
+    sliceRelPosFilter->ObjectCCLSelectionFlagOff();
+    sliceRelPosFilter->SetUseTheLargestObjectCCLFlag(singleObjectCCL);
+    sliceRelPosFilter->SetInverseOrientationFlag(inverseflag); 
     sliceRelPosFilter->SetAutoCropFlag(autocropFlag); 
     sliceRelPosFilter->IgnoreEmptySliceObjectFlagOn();
     sliceRelPosFilter->Update();
@@ -361,6 +302,7 @@ namespace clitk {
   }
   //--------------------------------------------------------------------
 
+
   //--------------------------------------------------------------------
   template<class ImageType>
   bool
@@ -375,6 +317,7 @@ namespace clitk {
   }
   //--------------------------------------------------------------------
 
+
   //--------------------------------------------------------------------
   template<class ImageType>
   bool
@@ -442,7 +385,11 @@ namespace clitk {
     typename ImageType::PointType p;
     image->TransformIndexToPhysicalPoint(image->GetLargestPossibleRegion().GetIndex()+
                                          image->GetLargestPossibleRegion().GetSize(), p);
-    return CropImageAlongOneAxis<ImageType>(image, dim, max, p[dim], autoCrop, BG);
+    // Add GetSpacing because remove Lower or equal than
+    // DD(max);
+    // DD(p);
+    // DD(max+image->GetSpacing()[dim]);
+    return CropImageAlongOneAxis<ImageType>(image, dim, max+image->GetSpacing()[dim], p[dim], autoCrop, BG);
   }
   //--------------------------------------------------------------------
 
@@ -458,13 +405,15 @@ namespace clitk {
     typename ImageType::RegionType region;
     typename ImageType::SizeType size = image->GetLargestPossibleRegion().GetSize();
     typename ImageType::PointType p = image->GetOrigin();
-    p[dim] = min;
+    if (min > p[dim]) p[dim] = min; // Check if not outside the image
     typename ImageType::IndexType start;
     image->TransformPhysicalPointToIndex(p, start);
-    p[dim] = max;
+    double m = image->GetOrigin()[dim] + size[dim]*image->GetSpacing()[dim];
+    if (max > m) p[dim] = m; // Check if not outside the image
+    else p[dim] = max;
     typename ImageType::IndexType end;
     image->TransformPhysicalPointToIndex(p, end);
-    size[dim] = fabs(end[dim]-start[dim]);
+    size[dim] = abs(end[dim]-start[dim]);
     region.SetIndex(start);
     region.SetSize(size);
   
@@ -510,7 +459,6 @@ namespace clitk {
     typename ImageType::PointType dummy;
     centroids.push_back(dummy); // label 0 -> no centroid, use dummy point for BG 
     //DS FIXME (not useful ! to change ..)
-    DD(labelMap->GetNumberOfLabelObjects());
     for(uint i=0; i<labelMap->GetNumberOfLabelObjects(); i++) {
       int label = labelMap->GetLabels()[i];
       centroids.push_back(labelMap->GetLabelObject(label)->GetCentroid());
@@ -519,6 +467,30 @@ namespace clitk {
   //--------------------------------------------------------------------
 
 
+  //--------------------------------------------------------------------
+  template<class ImageType, class LabelType>
+  typename itk::LabelMap< itk::ShapeLabelObject<LabelType, ImageType::ImageDimension> >::Pointer
+  ComputeLabelMap(const ImageType * image, 
+                  typename ImageType::PixelType BG, 
+                  bool computePerimeterFlag) 
+  {
+    static const unsigned int Dim = ImageType::ImageDimension;
+    typedef itk::ShapeLabelObject< LabelType, Dim > LabelObjectType;
+    typedef itk::LabelMap< LabelObjectType > LabelMapType;
+    typedef itk::LabelImageToLabelMapFilter<ImageType, LabelMapType> ImageToMapFilterType;
+    typename ImageToMapFilterType::Pointer imageToLabelFilter = ImageToMapFilterType::New(); 
+    typedef itk::ShapeLabelMapFilter<LabelMapType, ImageType> ShapeFilterType; 
+    typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New();
+    imageToLabelFilter->SetBackgroundValue(BG);
+    imageToLabelFilter->SetInput(image);
+    statFilter->SetInput(imageToLabelFilter->GetOutput());
+    statFilter->SetComputePerimeter(computePerimeterFlag);
+    statFilter->Update();
+    return statFilter->GetOutput();
+  }
+  //--------------------------------------------------------------------
+
+
   //--------------------------------------------------------------------
   template<class ImageType>
   void
@@ -560,25 +532,6 @@ namespace clitk {
   //--------------------------------------------------------------------
 
 
-  //--------------------------------------------------------------------
-  template<class ImageType>
-  void
-  ExtractSlices(const ImageType * image, int direction, 
-                std::vector<typename itk::Image<typename ImageType::PixelType, 
-                                                ImageType::ImageDimension-1>::Pointer > & slices) 
-  {
-    typedef ExtractSliceFilter<ImageType> ExtractSliceFilterType;
-    typedef typename ExtractSliceFilterType::SliceType SliceType;
-    typename ExtractSliceFilterType::Pointer 
-      extractSliceFilter = ExtractSliceFilterType::New();
-    extractSliceFilter->SetInput(image);
-    extractSliceFilter->SetDirection(direction);
-    extractSliceFilter->Update();
-    extractSliceFilter->GetOutputSlices(slices);
-  }
-  //--------------------------------------------------------------------
-
-
   //--------------------------------------------------------------------
   template<class ImageType>
   void
@@ -723,13 +676,42 @@ namespace clitk {
     dilateFilter->SetForegroundValue(FG);
     dilateFilter->SetBoundaryToForeground(false);
     dilateFilter->SetKernel(structuringElement);
-    dilateFilter->SetInput(output);
+    if (extendSupport) dilateFilter->SetInput(output);
+    else dilateFilter->SetInput(image);
     dilateFilter->Update();
     return dilateFilter->GetOutput();
   }
   //--------------------------------------------------------------------
 
 
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  typename ImageType::Pointer 
+  Opening(const ImageType * image, typename ImageType::SizeType radius,
+         typename ImageType::PixelType BG,
+         typename ImageType::PixelType FG)
+  {
+    // Kernel 
+    typedef itk::BinaryBallStructuringElement<typename ImageType::PixelType, 
+                                              ImageType::ImageDimension> KernelType;    
+    KernelType structuringElement;
+    structuringElement.SetRadius(radius);
+    structuringElement.CreateStructuringElement();
+    
+    // Filter
+    typedef itk::BinaryMorphologicalOpeningImageFilter<ImageType, ImageType , KernelType> OpeningFilterType;
+    typename OpeningFilterType::Pointer open = OpeningFilterType::New();
+    open->SetInput(image);
+    open->SetBackgroundValue(BG);
+    open->SetForegroundValue(FG);
+    open->SetKernel(structuringElement);
+    open->Update();
+    return open->GetOutput();
+  }
+  //--------------------------------------------------------------------
+
+
+
   //--------------------------------------------------------------------
   template<class ValueType, class VectorType>
   void ConvertOption(std::string optionName, uint given, 
@@ -782,9 +764,9 @@ namespace clitk {
                                               int mainDirection, 
                                               double offsetToKeep)
   {
+    assert((mainDirection==0) || (mainDirection==1));
     typedef itk::ImageSliceIteratorWithIndex<ImageType> SliceIteratorType;
-    SliceIteratorType siter = SliceIteratorType(input, 
-                                                input->GetLargestPossibleRegion());
+    SliceIteratorType siter = SliceIteratorType(input, input->GetLargestPossibleRegion());
     siter.SetFirstDirection(0);
     siter.SetSecondDirection(1);
     siter.GoToBegin();
@@ -796,9 +778,6 @@ namespace clitk {
     while ((i<lA.size()) && (!siter.IsAtEnd())) {
       // Check that the current slice correspond to the current point
       input->TransformIndexToPhysicalPoint(siter.GetIndex(), C);
-      // DD(C);
-      // DD(i);
-      // DD(lA[i]);
       if ((fabs(C[2] - lA[i][2]))>0.01) { // is !equal with a tolerance of 0.01 mm
       }
       else {
@@ -806,10 +785,6 @@ namespace clitk {
         A = lA[i];
         B = lB[i];
         C = A;
-        // DD(A);
-        // DD(B);
-        // DD(C);
-      
         // Check that the line is not a point (A=B)
         bool p = (A[0] == B[0]) && (A[1] == B[1]);
       
@@ -842,6 +817,7 @@ namespace clitk {
   }                                                   
   //--------------------------------------------------------------------
 
+
   //--------------------------------------------------------------------
   template<class ImageType>
   void 
@@ -870,6 +846,62 @@ namespace clitk {
   //--------------------------------------------------------------------
 
 
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void 
+  And(ImageType * input, 
+      const ImageType * object, 
+      typename ImageType::PixelType BG)
+  {
+    typename ImageType::Pointer o;
+    bool resized=false;
+    if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(input, object)) {
+      o = clitk::ResizeImageLike<ImageType>(object, input, BG);
+      resized = true;
+    }
+
+    typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
+    typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
+    boolFilter->InPlaceOn();
+    boolFilter->SetInput1(input);
+    if (resized) boolFilter->SetInput2(o);  
+    else boolFilter->SetInput2(object);
+    boolFilter->SetBackgroundValue1(BG);
+    boolFilter->SetBackgroundValue2(BG);
+    boolFilter->SetOperationType(BoolFilterType::And);
+    boolFilter->Update();
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void 
+  Or(ImageType * input, 
+     const ImageType * object, 
+     typename ImageType::PixelType BG)
+  {
+    typename ImageType::Pointer o;
+    bool resized=false;
+    if (!clitk::HaveSameSizeAndSpacing<ImageType, ImageType>(input, object)) {
+      o = clitk::ResizeImageLike<ImageType>(object, input, BG);
+      resized = true;
+    }
+
+    typedef clitk::BooleanOperatorLabelImageFilter<ImageType> BoolFilterType;
+    typename BoolFilterType::Pointer boolFilter = BoolFilterType::New(); 
+    boolFilter->InPlaceOn();
+    boolFilter->SetInput1(input);
+    if (resized) boolFilter->SetInput2(o);  
+    else boolFilter->SetInput2(object);
+    boolFilter->SetBackgroundValue1(BG);
+    boolFilter->SetBackgroundValue2(BG);
+    boolFilter->SetOperationType(BoolFilterType::Or);
+    boolFilter->Update();
+  }
+  //--------------------------------------------------------------------
+
+
   //--------------------------------------------------------------------
   template<class ImageType>
   typename ImageType::Pointer
@@ -999,7 +1031,7 @@ namespace clitk {
                                                             extremaDirection, extremaOppositeFlag, p);
       if (found) {
         position2D[i] = p;
-      }    
+      }
     }
     
     // Convert 2D points in slice into 3D points
@@ -1012,13 +1044,354 @@ namespace clitk {
       p[lineDirection] += 10;
       B.push_back(p);
       // Margins ?
-      A[i][1] += margin;
-      B[i][1] += margin;
+      A[i][extremaDirection] += margin;
+      B[i][extremaDirection] += margin;
+    }
+
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  typename ImageType::Pointer
+  SliceBySliceKeepMainCCL(const ImageType * input, 
+                          typename ImageType::PixelType BG,
+                          typename ImageType::PixelType FG)  {
+    
+    // Extract slices
+    const int d = ImageType::ImageDimension-1;
+    typedef typename itk::Image<typename ImageType::PixelType, d> SliceType;
+    std::vector<typename SliceType::Pointer> slices;
+    clitk::ExtractSlices<ImageType>(input, d, slices);
+    
+    // Labelize and keep the main one
+    std::vector<typename SliceType::Pointer> o;
+    for(uint i=0; i<slices.size(); i++) {
+      o.push_back(clitk::Labelize<SliceType>(slices[i], BG, false, 1));
+      o[i] = clitk::KeepLabels<SliceType>(o[i], BG, FG, 1, 1, true);
+    }
+    
+    // Join slices
+    typename ImageType::Pointer output;
+    output = clitk::JoinSlices<ImageType>(o, input, d);
+    return output;
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  typename ImageType::Pointer
+  Clone(const ImageType * input) {
+    typedef itk::ImageDuplicator<ImageType> DuplicatorType;
+    typename DuplicatorType::Pointer duplicator = DuplicatorType::New();
+    duplicator->SetInputImage(input);
+    duplicator->Update();
+    return duplicator->GetOutput();
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  /* Consider an input object, start at A, for each slice (dim1): 
+     - compute the intersection between the AB line and the current slice
+     - remove what is at lower or greater according to dim2 of this point
+     - stop at B
+  */
+  template<class ImageType>
+  typename ImageType::Pointer
+  SliceBySliceSetBackgroundFromSingleLine(const ImageType * input, 
+                                          typename ImageType::PixelType BG, 
+                                          typename ImageType::PointType & A, 
+                                          typename ImageType::PointType & B, 
+                                          int dim1, int dim2, bool removeLowerPartFlag)
+    
+  {
+    // Extract slices
+    typedef typename itk::Image<typename ImageType::PixelType, ImageType::ImageDimension-1> SliceType;
+    typedef typename SliceType::Pointer SlicePointer;
+    std::vector<SlicePointer> slices;
+    clitk::ExtractSlices<ImageType>(input, dim1, slices);
+
+    // Start at slice that contains A, and stop at B
+    typename ImageType::IndexType Ap;
+    typename ImageType::IndexType Bp;
+    input->TransformPhysicalPointToIndex(A, Ap);
+    input->TransformPhysicalPointToIndex(B, Bp);
+    
+    // Determine slice largest region
+    typename SliceType::RegionType region = slices[0]->GetLargestPossibleRegion();
+    typename SliceType::SizeType size = region.GetSize();
+    typename SliceType::IndexType index = region.GetIndex();
+
+    // Line slope
+    double a = (Bp[dim2]-Ap[dim2])/(Bp[dim1]-Ap[dim1]);
+    double b = Ap[dim2];
+
+    // Loop from slice A to slice B
+    for(uint i=0; i<(Bp[dim1]-Ap[dim1]); i++) {
+      // Compute intersection between line AB and current slice for the dim2
+      double p = a*i+b;
+      // Change region (lower than dim2)
+      if (removeLowerPartFlag) {
+        size[dim2] = p-Ap[dim2];
+      }
+      else {
+        size[dim2] = slices[0]->GetLargestPossibleRegion().GetSize()[dim2]-p;
+        index[dim2] = p;
+      }
+      region.SetSize(size);
+      region.SetIndex(index);
+      // Fill region with BG (simple region iterator)
+      FillRegionWithValue<SliceType>(slices[i+Ap[dim1]], BG, region);
+      /*
+      typedef itk::ImageRegionIterator<SliceType> IteratorType;
+      IteratorType iter(slices[i+Ap[dim1]], region);
+      iter.GoToBegin();
+      while (!iter.IsAtEnd()) {
+        iter.Set(BG);
+        ++iter;
+      }
+      */
+      // Loop
+    }
+    
+    // Merge slices
+    typename ImageType::Pointer output;
+    output = clitk::JoinSlices<ImageType>(slices, input, dim1);
+    return output;
+  }
+  //--------------------------------------------------------------------
+
+  //--------------------------------------------------------------------
+  /* Consider an input object, slice by slice, use the point A and set
+     pixel to BG according to their position relatively to A
+  */
+  template<class ImageType>
+  typename ImageType::Pointer
+  SliceBySliceSetBackgroundFromPoints(const ImageType * input, 
+                                      typename ImageType::PixelType BG, 
+                                      int sliceDim,
+                                      std::vector<typename ImageType::PointType> & A, 
+                                      bool removeGreaterThanXFlag,
+                                      bool removeGreaterThanYFlag)
+    
+  {
+    // Extract slices
+    typedef typename itk::Image<typename ImageType::PixelType, ImageType::ImageDimension-1> SliceType;
+    typedef typename SliceType::Pointer SlicePointer;
+    std::vector<SlicePointer> slices;
+    clitk::ExtractSlices<ImageType>(input, sliceDim, slices);
+
+    // Start at slice that contains A
+    typename ImageType::IndexType Ap;
+    
+    // Determine slice largest region
+    typename SliceType::RegionType region = slices[0]->GetLargestPossibleRegion();
+    typename SliceType::SizeType size = region.GetSize();
+    typename SliceType::IndexType index = region.GetIndex();
+
+    // Loop from slice A to slice B
+    for(uint i=0; i<A.size(); i++) {
+      input->TransformPhysicalPointToIndex(A[i], Ap);
+      uint sliceIndex = Ap[2] - input->GetLargestPossibleRegion().GetIndex()[2];
+      if ((sliceIndex < 0) || (sliceIndex >= slices.size())) {
+        continue; // do not consider this slice
+      }
+      
+      // Compute region for BG
+      if (removeGreaterThanXFlag) {
+        index[0] = Ap[0];
+        size[0] = region.GetSize()[0]-(index[0]-region.GetIndex()[0]);
+      }
+      else {
+        index[0] = region.GetIndex()[0];
+        size[0] = Ap[0] - index[0];
+      }
+
+      if (removeGreaterThanYFlag) {
+        index[1] = Ap[1];
+        size[1] = region.GetSize()[1]-(index[1]-region.GetIndex()[1]);
+      }
+      else {
+        index[1] = region.GetIndex()[1];
+        size[1] = Ap[1] - index[1];
+      }
+
+      // Set region
+      region.SetSize(size);
+      region.SetIndex(index);
+
+      // Fill region with BG (simple region iterator)
+      FillRegionWithValue<SliceType>(slices[sliceIndex], BG, region);
+      // Loop
+    }
+    
+    // Merge slices
+    typename ImageType::Pointer output;
+    output = clitk::JoinSlices<ImageType>(slices, input, sliceDim);
+    return output;
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void
+  FillRegionWithValue(ImageType * input, typename ImageType::PixelType value, typename ImageType::RegionType & region)
+  {
+    typedef itk::ImageRegionIterator<ImageType> IteratorType;
+    IteratorType iter(input, region);
+    iter.GoToBegin();
+    while (!iter.IsAtEnd()) {
+      iter.Set(value);
+      ++iter;
+    }    
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void
+  GetMinMaxBoundary(ImageType * input, typename ImageType::PointType & min, 
+                    typename ImageType::PointType & max)
+  {
+    typedef typename ImageType::PointType PointType;
+    typedef typename ImageType::IndexType IndexType;
+    IndexType min_i, max_i;
+    min_i = input->GetLargestPossibleRegion().GetIndex();
+    for(uint i=0; i<ImageType::ImageDimension; i++)
+      max_i[i] = input->GetLargestPossibleRegion().GetSize()[i] + min_i[i];
+    input->TransformIndexToPhysicalPoint(min_i, min);
+    input->TransformIndexToPhysicalPoint(max_i, max);  
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  typename itk::Image<float, ImageType::ImageDimension>::Pointer
+  DistanceMap(const ImageType * input, typename ImageType::PixelType BG)//, 
+  //              typename itk::Image<float, ImageType::ImageDimension>::Pointer dmap) 
+  {
+    typedef itk::Image<float,ImageType::ImageDimension> FloatImageType;
+    typedef itk::SignedMaurerDistanceMapImageFilter<ImageType, FloatImageType> DistanceMapFilterType;
+    typename DistanceMapFilterType::Pointer filter = DistanceMapFilterType::New();
+    filter->SetInput(input);
+    filter->SetUseImageSpacing(true);
+    filter->SquaredDistanceOff();
+    filter->SetBackgroundValue(BG);
+    filter->Update();
+    return filter->GetOutput();
+  }
+  //--------------------------------------------------------------------
+
+
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  void 
+  SliceBySliceBuildLineSegmentAccordingToMinimalDistanceBetweenStructures(const ImageType * S1, 
+                                                                          const ImageType * S2, 
+                                                                          typename ImageType::PixelType BG, 
+                                                                          int sliceDimension, 
+                                                                          std::vector<typename ImageType::PointType> & A, 
+                                                                          std::vector<typename ImageType::PointType> & B)
+  {
+    // Extract slices
+    typedef typename itk::Image<typename ImageType::PixelType, 2> SliceType;
+    typedef typename SliceType::Pointer SlicePointer;
+    std::vector<SlicePointer> slices_s1;
+    std::vector<SlicePointer> slices_s2;
+    clitk::ExtractSlices<ImageType>(S1, sliceDimension, slices_s1);
+    clitk::ExtractSlices<ImageType>(S2, sliceDimension, slices_s2);
+
+    assert(slices_s1.size() == slices_s2.size());
+
+    // Prepare dmap
+    typedef itk::Image<float,2> FloatImageType;
+    typedef itk::SignedMaurerDistanceMapImageFilter<SliceType, FloatImageType> DistanceMapFilterType;
+    std::vector<typename FloatImageType::Pointer> dmaps1;
+    std::vector<typename FloatImageType::Pointer> dmaps2;
+    typename FloatImageType::Pointer dmap;
+
+    // loop on slices
+    for(uint i=0; i<slices_s1.size(); i++) {
+      // Compute dmap for S1 *TO PUT IN FONCTION*
+      dmap = clitk::DistanceMap<SliceType>(slices_s1[i], BG);
+      dmaps1.push_back(dmap);
+      writeImage<FloatImageType>(dmap, "dmap1.mha");
+      // Compute dmap for S2
+      dmap = clitk::DistanceMap<SliceType>(slices_s2[i], BG);
+      dmaps2.push_back(dmap);
+      writeImage<FloatImageType>(dmap, "dmap2.mha");
+      
+      // Look in S2 for the point the closest to S1
+      typename SliceType::PointType p = ComputeClosestPoint<SliceType>(slices_s1[i], dmaps2[i], BG);
+      typename ImageType::PointType p3D;
+      clitk::PointsUtils<ImageType>::Convert2DTo3D(p, S1, i, p3D);
+      A.push_back(p3D);
+
+      // Look in S2 for the point the closest to S1
+      p = ComputeClosestPoint<SliceType>(slices_s2[i], dmaps1[i], BG);
+      clitk::PointsUtils<ImageType>::Convert2DTo3D(p, S2, i, p3D);
+      B.push_back(p3D);
+
     }
 
+    // Debug dmap
+    /*
+      typedef itk::Image<float,3> FT;
+      FT::Pointer f = FT::New();
+      typename FT::Pointer d1 = clitk::JoinSlices<FT>(dmaps1, S1, 2);
+      typename FT::Pointer d2 = clitk::JoinSlices<FT>(dmaps2, S2, 2);
+      writeImage<FT>(d1, "d1.mha");
+      writeImage<FT>(d2, "d2.mha");
+    */
   }
   //--------------------------------------------------------------------
 
 
+  //--------------------------------------------------------------------
+  template<class ImageType>
+  typename ImageType::PointType
+  ComputeClosestPoint(const ImageType * input, 
+                      const itk::Image<float, ImageType::ImageDimension> * dmap, 
+                      typename ImageType::PixelType & BG) 
+  {
+    // Loop dmap + S2, if FG, get min
+    typedef itk::Image<float,ImageType::ImageDimension> FloatImageType;
+    typedef itk::ImageRegionConstIteratorWithIndex<ImageType> ImageIteratorType;
+    typedef itk::ImageRegionConstIterator<FloatImageType> DMapIteratorType;
+    ImageIteratorType iter1(input, input->GetLargestPossibleRegion());
+    DMapIteratorType iter2(dmap, dmap->GetLargestPossibleRegion());
+    
+    iter1.GoToBegin();
+    iter2.GoToBegin();
+    double dmin = 100000.0;
+    typename ImageType::IndexType indexmin;
+    while (!iter1.IsAtEnd()) {
+      if (iter1.Get() != BG) {
+        double d = iter2.Get();
+        if (d<dmin) {
+          indexmin = iter1.GetIndex();
+          dmin = d;
+        }
+      }
+      ++iter1;
+      ++iter2;
+    }
+    
+    // Convert in Point
+    typename ImageType::PointType p;
+    input->TransformIndexToPhysicalPoint(indexmin, p);
+    return p;
+  }
+  //--------------------------------------------------------------------
+     
+
+
+
 } // end of namespace