diff --git a/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx b/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx
index cf99e600baa07513eaa2f625704fdc0d6f5cbab7..3bfc0af9e44686e12664c6aa34cda4e7e30bec4c 100644
--- a/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx
+++ b/Applications/DisparityMap/otbPixelWiseBlockMatching.cxx
@@ -384,7 +384,7 @@ private:
       m_SSDBlockMatcher->SetMaximumVerticalDisparity(maxvdisp);
       if (IsParameterEnabled("bm.subpixel"))
         {
-        m_SSDBlockMatcher->DoSubPixelInterpolationOn();
+        //m_SSDBlockMatcher->DoSubPixelInterpolationOn();
         }
       
       AddProcess(m_SSDBlockMatcher,"SSD block matching");
@@ -428,7 +428,7 @@ private:
       m_NCCBlockMatcher->MinimizeOff();
       if (IsParameterEnabled("bm.subpixel"))
         {
-        m_NCCBlockMatcher->DoSubPixelInterpolationOn();
+        //m_NCCBlockMatcher->DoSubPixelInterpolationOn();
         }
       
       AddProcess(m_NCCBlockMatcher,"NCC block matching");
@@ -473,7 +473,7 @@ private:
       m_LPBlockMatcher->SetMaximumVerticalDisparity(maxvdisp);
       if (IsParameterEnabled("bm.subpixel"))
         {
-        m_LPBlockMatcher->DoSubPixelInterpolationOn();
+        //m_LPBlockMatcher->DoSubPixelInterpolationOn();
         }
       
       AddProcess(m_LPBlockMatcher,"Lp block matching");
diff --git a/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h b/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h
index e12a245d1be7bf240fbe5337dc88d423e849b236..10422ebcc8473048113662356681e1b499f18d6c 100644
--- a/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h
+++ b/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.h
@@ -172,15 +172,16 @@ private:
 } // End Namespace Functor
 
 /** \class PixelWiseBlockMatchingImageFilter
- *  \brief Perform horizontal 1D block matching between two images
+ *  \brief Perform 2D block matching between two images
  *
- *  This filter performs pixel-wise horizontal 1D block-matching
+ *  This filter performs pixel-wise 2D block-matching
  *  between a pair of image. This is especially useful in the case of
  *  stereo pairs in epipolar geometry, where displacements
  *  corresponding to differences of elevation occur in the horizontal
- *  direction only. Please note that only integer pixel displacement
- *  are explored. For finer results, consider up-sampling the input
- *  images or search for another filter.
+ *  direction only (in that case, the exploration along the vertical 
+ *  direction can be disabled). Please note that only integer pixel 
+ *  displacement are explored. For finer results, consider up-sampling 
+ *  the input images or use the SubPixelDisparityImageFilter.
  *
  *  The block-matching metric itself is defined by a template functor
  *  on neighborhood iterators. A wide range of block-matching
@@ -191,26 +192,36 @@ private:
  *  flag to off using the MinimizeOff() method will make the filter
  *  try to maximize the metric.
  *
- *  Only a user defined range of disparities between the two images is
- *  explored, which can be set by using the SetMinimumDisparity() and
- *  SetMaximumDisparity() methods.
+ *  Only a user defined area of disparities between the two images is
+ *  explored, which can be set by using the SetMinimumHorizontalDisparity()
+ *  , SetMinimumVerticalDisparity(), SetMaximumHorizontalDisparity() 
+ *  and SetMaximumVerticalDisparity() methods.
  *
- *  This filter has two outputs: the first is the disparity image,
- *  which can be retrieved using the GetDisparityOutput() method, and
- *  contains the estimated local horizontal displacement between both
- *  input images (displacement from left image to right image). The
- *  second is the metric image, which contains the metric optimum value
- *  corresponding to this estimated displacement.
+ *  This filter has three outputs: the first is the metric image, 
+ *  which contains the metric optimum value corresponding to the 
+ *  estimated displacement. The second and last outputs are the 
+ *  horizontal and vertical disparity maps, which can be retrieved 
+ *  using the GetHorizontalDisparityOutput() and GetVerticalDisparityOutput()
+ *  methods. They contain the horizontal and vertical local displacement
+ *  between the two input images (displacement is given in pixels, from left
+ *  image to right image).
  *
- *  Mask is not mandatory. The mask allows to indicate pixels validity
- *  with respect to the left image. If a mask image is provided, only
- *  pixels whose mask values are strictly positive will be considered
- *  for disparity exploration. The other will exhibit a null value for
- *  the metric and a disparity corresponding to the minimum allowed
+ *  Masks are not mandatory. A mask allows to indicate pixels validity in
+ *  either left or right image. Left and right masks can be used independently.
+ *  If masks are used, only pixels whose mask values are strictly positive
+ *  will be considered for disparity matching. The other will exhibit a null 
+ *  metric value and a disparity corresponding to the minimum allowed
  *  disparity.
  *
+ *  The disparity exploration can also be reduced thanks to initial disparity
+ *  maps. The user can provide initial disparity estimate (using the same image
+ *  type and size as the output disparities), or global disparity values. Then
+ *  an exploration radius indicates the disparity range to be explored around 
+ *  the initial estimate (global minimum and maximum values are still in use).
+ *
  *  \sa FineRegistrationImageFilter
  *  \sa StereorectificationDeformationFieldSource
+ *  \sa SubPixelDisparityImageFilter
  *
  *  \ingroup Streamed
  *  \ingroup Threaded
@@ -345,10 +356,6 @@ public:
   /** Get the initial disparity fields */
   const TOutputDisparityImage * GetHorizontalDisparityInput() const;
   const TOutputDisparityImage * GetVerticalDisparityInput() const;
-  
-  itkSetMacro(DoSubPixelInterpolation, bool);
-  itkGetConstReferenceMacro(DoSubPixelInterpolation,bool);
-  itkBooleanMacro(DoSubPixelInterpolation);
 
 protected:
   /** Constructor */
@@ -369,12 +376,7 @@ protected:
 private:
   PixelWiseBlockMatchingImageFilter(const Self&); //purposely not implemented
   void operator=(const Self&); //purposely not implemeFnted
-
-  bool InterpolateSubPixelPosition(ConstNeighborhoodIteratorType & leftPatch,
-                                    itk::ImageRegionIterator<OutputDisparityImageType> & hDispIt,
-                                    itk::ImageRegionIterator<OutputDisparityImageType> & vDispIt,
-                                    itk::ImageRegionIterator<OutputMetricImageType> & metricIt);
-  
+ 
   /** The radius of the blocks */
   SizeType                      m_Radius;
 
@@ -399,14 +401,13 @@ private:
   /** Block-matching functor */
   BlockMatchingFunctorType      m_Functor;
   
-  /** Initial horizontal disparity (0 by default, used if an exploration radius is set) */
+  /** Initial horizontal disparity (0 by default, used if an exploration radius is set and if no input horizontal 
+    disparity map is given) */
   int                           m_InitHorizontalDisparity;
   
-  /** Initial vertical disparity (0 by default, used if an exploration radius is set) */
+  /** Initial vertical disparity (0 by default, used if an exploration radius is set and if no input vertical 
+    disparity map is given) */
   int                           m_InitVerticalDisparity;
-  
-  /** flag to perform sub-pixel interpolation */
-  bool                          m_DoSubPixelInterpolation;
 };
 } // end namespace otb
 
diff --git a/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.txx b/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.txx
index de2f319cb6a9113f0a03896ad14fb29cd9308cc2..1bceba04f194fc04c39c82717c7a455fdd9751c6 100644
--- a/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.txx
+++ b/Code/DisparityMap/otbPixelWiseBlockMatchingImageFilter.txx
@@ -61,7 +61,7 @@ TOutputDisparityImage,TMaskImage,TBlockMatchingFunctor>
   // Default exploration radius : 0 (not used)
   m_ExplorationRadius.Fill(0);
   
-  m_DoSubPixelInterpolation = false;
+//   m_DoSubPixelInterpolation = false;
 }
 
 
@@ -678,243 +678,243 @@ TOutputDisparityImage,TMaskImage,TBlockMatchingFunctor>
     }
     }
   
-  // subpixel interpolation case
-  if (m_DoSubPixelInterpolation)
-    {
-    itk::ConstNeighborhoodIterator<TInputImage>     leftIt(m_Radius,inLeftPtr,outputRegionForThread);
-    itk::ImageRegionIterator<TOutputDisparityImage> outHDispIt(outHDispPtr,outputRegionForThread);
-    itk::ImageRegionIterator<TOutputDisparityImage> outVDispIt(outVDispPtr,outputRegionForThread);
-    itk::ImageRegionIterator<TOutputMetricImage>    outMetricIt(outMetricPtr,outputRegionForThread);
-    
-    itk::ConstantBoundaryCondition<TInputImage> nbc1;
-    leftIt.OverrideBoundaryCondition(&nbc1);
-    
-    leftIt.GoToBegin();
-    outHDispIt.GoToBegin();
-    outVDispIt.GoToBegin();
-    outMetricIt.GoToBegin();
-    
-    while (!leftIt.IsAtEnd()
-          || !outHDispIt.IsAtEnd()
-          || !outVDispIt.IsAtEnd()
-          || !outMetricIt.IsAtEnd())
-      {
-      bool isInterpolated = InterpolateSubPixelPosition(leftIt,outHDispIt,outVDispIt,outMetricIt);
-      
-      ++leftIt;
-      ++outHDispIt;
-      ++outVDispIt;
-      ++outMetricIt;
-      }
-    
-    }
+//   // subpixel interpolation case
+//   if (m_DoSubPixelInterpolation)
+//     {
+//     itk::ConstNeighborhoodIterator<TInputImage>     leftIt(m_Radius,inLeftPtr,outputRegionForThread);
+//     itk::ImageRegionIterator<TOutputDisparityImage> outHDispIt(outHDispPtr,outputRegionForThread);
+//     itk::ImageRegionIterator<TOutputDisparityImage> outVDispIt(outVDispPtr,outputRegionForThread);
+//     itk::ImageRegionIterator<TOutputMetricImage>    outMetricIt(outMetricPtr,outputRegionForThread);
+//     
+//     itk::ConstantBoundaryCondition<TInputImage> nbc1;
+//     leftIt.OverrideBoundaryCondition(&nbc1);
+//     
+//     leftIt.GoToBegin();
+//     outHDispIt.GoToBegin();
+//     outVDispIt.GoToBegin();
+//     outMetricIt.GoToBegin();
+//     
+//     while (!leftIt.IsAtEnd()
+//           || !outHDispIt.IsAtEnd()
+//           || !outVDispIt.IsAtEnd()
+//           || !outMetricIt.IsAtEnd())
+//       {
+//       bool isInterpolated = InterpolateSubPixelPosition(leftIt,outHDispIt,outVDispIt,outMetricIt);
+//       
+//       ++leftIt;
+//       ++outHDispIt;
+//       ++outVDispIt;
+//       ++outMetricIt;
+//       }
+//     
+//     }
   
 }
 
-template <class TInputImage, class TOutputMetricImage,
-class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
-bool
-PixelWiseBlockMatchingImageFilter<TInputImage,TOutputMetricImage,
-TOutputDisparityImage,TMaskImage,TBlockMatchingFunctor>
-::InterpolateSubPixelPosition(ConstNeighborhoodIteratorType & leftPatch,
-                              itk::ImageRegionIterator<OutputDisparityImageType> & hDispIt,
-                              itk::ImageRegionIterator<OutputDisparityImageType> & vDispIt,
-                              itk::ImageRegionIterator<OutputMetricImageType> & metricIt)
-{
-  IndexType curLeftPos = leftPatch.GetIndex();
-  SizeType curRadius = leftPatch.GetRadius();
-  
-  const TInputImage *     inRightPtr   = this->GetRightInput();
-  RegionType rightLargestRegion = inRightPtr->GetLargestPossibleRegion();
-  
-  float hDisp_f = static_cast<float>(hDispIt.Get());
-  float vDisp_f = static_cast<float>(vDispIt.Get());
-  
-  int hDisp_i = static_cast<int>(vcl_floor(hDisp_f + 0.5));
-  int vDisp_i = static_cast<int>(vcl_floor(vDisp_f + 0.5));
-  
-  IndexType curRightPos(curLeftPos);
-  curRightPos[0]+=hDisp_i;
-  curRightPos[1]+=vDisp_i;
-  
-  // check if the current right position is inside the right image
-  if (!rightLargestRegion.IsInside(curRightPos))
-    {
-    return false;
-    }
-    
-  // compute metric around current right position
-  bool horizontalInterpolation = false;
-  bool verticalInterpolation = false;
-  
-    // metrics for neighbors positions, sorted like this :
-    //  [up,up-right,right,down-right,down,down-left,left,up-left]
-  double neighborsMetric[8] = {0,0,0,0,0,0,0,0};
-  int firstNeighbor = 0;
-  int stepNeighbor = 4;
-  
-  RegionType smallRightRegion;
-  smallRightRegion.SetIndex(0,curRightPos[0]-1);
-  smallRightRegion.SetIndex(1,curRightPos[1]-1);
-  smallRightRegion.SetSize(0,3);
-  smallRightRegion.SetSize(1,3);
-  
-  itk::ConstNeighborhoodIterator<TInputImage>     rightIt(curRadius,inRightPtr,smallRightRegion);
-  
-  if (m_MinimumVerticalDisparity < vDisp_i && vDisp_i < m_MaximumVerticalDisparity)
-    {
-    IndexType upIndex(curRightPos);
-    upIndex[1]+= (-1);
-    IndexType downIndex(curRightPos);
-    downIndex[1]+= 1;
-    if ( rightLargestRegion.IsInside(upIndex) && rightLargestRegion.IsInside(downIndex) )
-      {
-      verticalInterpolation = true;
-      
-      rightIt.SetLocation(upIndex);
-      neighborsMetric[0] = m_Functor(leftPatch,rightIt);
-      
-      rightIt.SetLocation(downIndex);
-      neighborsMetric[4] = m_Functor(leftPatch,rightIt);
-      
-      }
-    }
-  
-  if (m_MinimumHorizontalDisparity < hDisp_i && hDisp_i < m_MaximumHorizontalDisparity)
-    {
-    IndexType leftIndex(curRightPos);
-    leftIndex[0]+= (-1);
-    IndexType rightIndex(curRightPos);
-    rightIndex[0]+= 1;
-    if ( rightLargestRegion.IsInside(leftIndex) && rightLargestRegion.IsInside(rightIndex) )
-      {
-      horizontalInterpolation = true;
-      firstNeighbor = 2;
-      
-      rightIt.SetLocation(rightIndex);
-      neighborsMetric[2] = m_Functor(leftPatch,rightIt);
-      
-      rightIt.SetLocation(leftIndex);
-      neighborsMetric[6] = m_Functor(leftPatch,rightIt);
-      
-      }
-    }
-  
-  if ( !verticalInterpolation && !horizontalInterpolation)
-    {
-    return false;
-    }
-  
-  // if both vertical and horizontal interpolation, compute metrics on corners
-  if (verticalInterpolation && horizontalInterpolation)
-    {
-    firstNeighbor = 0;
-    stepNeighbor = 1;
-    
-    IndexType uprightIndex(curRightPos);
-    uprightIndex[0]+= 1;
-    uprightIndex[1]+= (-1);
-    rightIt.SetLocation(uprightIndex);
-    neighborsMetric[1] = m_Functor(leftPatch,rightIt);
-    
-    IndexType downrightIndex(curRightPos);
-    downrightIndex[0]+= 1;
-    downrightIndex[1]+= 1;
-    rightIt.SetLocation(downrightIndex);
-    neighborsMetric[3] = m_Functor(leftPatch,rightIt);
-    
-    IndexType downleftIndex(curRightPos);
-    downleftIndex[0]+= (-1);
-    downleftIndex[1]+= 1;
-    rightIt.SetLocation(downleftIndex);
-    neighborsMetric[5] = m_Functor(leftPatch,rightIt);
-    
-    IndexType upleftIndex(curRightPos);
-    upleftIndex[0]+= (-1);
-    upleftIndex[1]+= (-1);
-    rightIt.SetLocation(upleftIndex);
-    neighborsMetric[7] = m_Functor(leftPatch,rightIt);
-    }
-  
-  // check if the position is a minimum (or maximum if !m_Minimize)
-  double curMetric = metricIt.Get();
-  for (unsigned int i=firstNeighbor; i<8; i+=stepNeighbor)
-    {
-    if (m_Minimize)
-      {
-      if (curMetric > neighborsMetric[i])
-        {
-        return false;
-        }
-      }
-    else
-      {
-      if (curMetric < neighborsMetric[i])
-        {
-        return false;
-        }
-      }
-    }
-
-  
-  // Interpolate position : parabola fit
-  if (verticalInterpolation && !horizontalInterpolation)
-    {
-    //vertical only
-    double deltaV = 0.5 - (1.0 / (1.0 + (neighborsMetric[0]-curMetric) / (neighborsMetric[4]-curMetric)));
-    if (deltaV > (-0.5) && deltaV < 0.5)
-      {
-      vDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
-      }
-    else
-      {
-      return false;
-      }
-    }
-  else if (!verticalInterpolation && horizontalInterpolation)
-    {
-    // horizontal only
-    double deltaH = 0.5 - (1.0 / (1.0 + (neighborsMetric[6]-curMetric) / (neighborsMetric[2]-curMetric)));
-    if (deltaH > (-0.5) && deltaH < 0.5)
-      {
-      hDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
-      }
-    else
-      {
-      return false;
-      }
-    }
-  else
-    {
-    //both horizontal and vertical
-    double dx = 0.5 * (neighborsMetric[2] - neighborsMetric[6]);
-    double dy = 0.5 * (neighborsMetric[4] - neighborsMetric[0]);
-    double dxx = neighborsMetric[2] + neighborsMetric[6] - 2.0 * curMetric;
-    double dyy = neighborsMetric[4] + neighborsMetric[0] - 2.0 * curMetric;
-    double dxy = 0.25 * (neighborsMetric[3] + neighborsMetric[7] - neighborsMetric[1] - neighborsMetric[5]);
-    double det = dxx*dyy - dxy*dxy;
-    if (vcl_abs(det) < (1e-10))
-      {
-      return false;
-      }
-    else
-      {
-      double deltaH = (-dx * dyy + dy * dxy )/det;
-      double deltaV = ( dx * dxy - dy * dxx )/det;
-      if (deltaH > (-1.0) && deltaH < 1.0 && deltaV > (-1.0) && deltaV < 1.0)
-        {
-        hDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
-        vDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
-        }
-      else
-        {
-        return false;
-        }
-      }
-    }
-  
-  return true;
-}
+// template <class TInputImage, class TOutputMetricImage,
+// class TOutputDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
+// bool
+// PixelWiseBlockMatchingImageFilter<TInputImage,TOutputMetricImage,
+// TOutputDisparityImage,TMaskImage,TBlockMatchingFunctor>
+// ::InterpolateSubPixelPosition(ConstNeighborhoodIteratorType & leftPatch,
+//                               itk::ImageRegionIterator<OutputDisparityImageType> & hDispIt,
+//                               itk::ImageRegionIterator<OutputDisparityImageType> & vDispIt,
+//                               itk::ImageRegionIterator<OutputMetricImageType> & metricIt)
+// {
+//   IndexType curLeftPos = leftPatch.GetIndex();
+//   SizeType curRadius = leftPatch.GetRadius();
+//   
+//   const TInputImage *     inRightPtr   = this->GetRightInput();
+//   RegionType rightLargestRegion = inRightPtr->GetLargestPossibleRegion();
+//   
+//   float hDisp_f = static_cast<float>(hDispIt.Get());
+//   float vDisp_f = static_cast<float>(vDispIt.Get());
+//   
+//   int hDisp_i = static_cast<int>(vcl_floor(hDisp_f + 0.5));
+//   int vDisp_i = static_cast<int>(vcl_floor(vDisp_f + 0.5));
+//   
+//   IndexType curRightPos(curLeftPos);
+//   curRightPos[0]+=hDisp_i;
+//   curRightPos[1]+=vDisp_i;
+//   
+//   // check if the current right position is inside the right image
+//   if (!rightLargestRegion.IsInside(curRightPos))
+//     {
+//     return false;
+//     }
+//     
+//   // compute metric around current right position
+//   bool horizontalInterpolation = false;
+//   bool verticalInterpolation = false;
+//   
+//     // metrics for neighbors positions, sorted like this :
+//     //  [up,up-right,right,down-right,down,down-left,left,up-left]
+//   double neighborsMetric[8] = {0,0,0,0,0,0,0,0};
+//   int firstNeighbor = 0;
+//   int stepNeighbor = 4;
+//   
+//   RegionType smallRightRegion;
+//   smallRightRegion.SetIndex(0,curRightPos[0]-1);
+//   smallRightRegion.SetIndex(1,curRightPos[1]-1);
+//   smallRightRegion.SetSize(0,3);
+//   smallRightRegion.SetSize(1,3);
+//   
+//   itk::ConstNeighborhoodIterator<TInputImage>     rightIt(curRadius,inRightPtr,smallRightRegion);
+//   
+//   if (m_MinimumVerticalDisparity < vDisp_i && vDisp_i < m_MaximumVerticalDisparity)
+//     {
+//     IndexType upIndex(curRightPos);
+//     upIndex[1]+= (-1);
+//     IndexType downIndex(curRightPos);
+//     downIndex[1]+= 1;
+//     if ( rightLargestRegion.IsInside(upIndex) && rightLargestRegion.IsInside(downIndex) )
+//       {
+//       verticalInterpolation = true;
+//       
+//       rightIt.SetLocation(upIndex);
+//       neighborsMetric[0] = m_Functor(leftPatch,rightIt);
+//       
+//       rightIt.SetLocation(downIndex);
+//       neighborsMetric[4] = m_Functor(leftPatch,rightIt);
+//       
+//       }
+//     }
+//   
+//   if (m_MinimumHorizontalDisparity < hDisp_i && hDisp_i < m_MaximumHorizontalDisparity)
+//     {
+//     IndexType leftIndex(curRightPos);
+//     leftIndex[0]+= (-1);
+//     IndexType rightIndex(curRightPos);
+//     rightIndex[0]+= 1;
+//     if ( rightLargestRegion.IsInside(leftIndex) && rightLargestRegion.IsInside(rightIndex) )
+//       {
+//       horizontalInterpolation = true;
+//       firstNeighbor = 2;
+//       
+//       rightIt.SetLocation(rightIndex);
+//       neighborsMetric[2] = m_Functor(leftPatch,rightIt);
+//       
+//       rightIt.SetLocation(leftIndex);
+//       neighborsMetric[6] = m_Functor(leftPatch,rightIt);
+//       
+//       }
+//     }
+//   
+//   if ( !verticalInterpolation && !horizontalInterpolation)
+//     {
+//     return false;
+//     }
+//   
+//   // if both vertical and horizontal interpolation, compute metrics on corners
+//   if (verticalInterpolation && horizontalInterpolation)
+//     {
+//     firstNeighbor = 0;
+//     stepNeighbor = 1;
+//     
+//     IndexType uprightIndex(curRightPos);
+//     uprightIndex[0]+= 1;
+//     uprightIndex[1]+= (-1);
+//     rightIt.SetLocation(uprightIndex);
+//     neighborsMetric[1] = m_Functor(leftPatch,rightIt);
+//     
+//     IndexType downrightIndex(curRightPos);
+//     downrightIndex[0]+= 1;
+//     downrightIndex[1]+= 1;
+//     rightIt.SetLocation(downrightIndex);
+//     neighborsMetric[3] = m_Functor(leftPatch,rightIt);
+//     
+//     IndexType downleftIndex(curRightPos);
+//     downleftIndex[0]+= (-1);
+//     downleftIndex[1]+= 1;
+//     rightIt.SetLocation(downleftIndex);
+//     neighborsMetric[5] = m_Functor(leftPatch,rightIt);
+//     
+//     IndexType upleftIndex(curRightPos);
+//     upleftIndex[0]+= (-1);
+//     upleftIndex[1]+= (-1);
+//     rightIt.SetLocation(upleftIndex);
+//     neighborsMetric[7] = m_Functor(leftPatch,rightIt);
+//     }
+//   
+//   // check if the position is a minimum (or maximum if !m_Minimize)
+//   double curMetric = metricIt.Get();
+//   for (unsigned int i=firstNeighbor; i<8; i+=stepNeighbor)
+//     {
+//     if (m_Minimize)
+//       {
+//       if (curMetric > neighborsMetric[i])
+//         {
+//         return false;
+//         }
+//       }
+//     else
+//       {
+//       if (curMetric < neighborsMetric[i])
+//         {
+//         return false;
+//         }
+//       }
+//     }
+// 
+//   
+//   // Interpolate position : parabola fit
+//   if (verticalInterpolation && !horizontalInterpolation)
+//     {
+//     //vertical only
+//     double deltaV = 0.5 - (1.0 / (1.0 + (neighborsMetric[0]-curMetric) / (neighborsMetric[4]-curMetric)));
+//     if (deltaV > (-0.5) && deltaV < 0.5)
+//       {
+//       vDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
+//       }
+//     else
+//       {
+//       return false;
+//       }
+//     }
+//   else if (!verticalInterpolation && horizontalInterpolation)
+//     {
+//     // horizontal only
+//     double deltaH = 0.5 - (1.0 / (1.0 + (neighborsMetric[6]-curMetric) / (neighborsMetric[2]-curMetric)));
+//     if (deltaH > (-0.5) && deltaH < 0.5)
+//       {
+//       hDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
+//       }
+//     else
+//       {
+//       return false;
+//       }
+//     }
+//   else
+//     {
+//     //both horizontal and vertical
+//     double dx = 0.5 * (neighborsMetric[2] - neighborsMetric[6]);
+//     double dy = 0.5 * (neighborsMetric[4] - neighborsMetric[0]);
+//     double dxx = neighborsMetric[2] + neighborsMetric[6] - 2.0 * curMetric;
+//     double dyy = neighborsMetric[4] + neighborsMetric[0] - 2.0 * curMetric;
+//     double dxy = 0.25 * (neighborsMetric[3] + neighborsMetric[7] - neighborsMetric[1] - neighborsMetric[5]);
+//     double det = dxx*dyy - dxy*dxy;
+//     if (vcl_abs(det) < (1e-10))
+//       {
+//       return false;
+//       }
+//     else
+//       {
+//       double deltaH = (-dx * dyy + dy * dxy )/det;
+//       double deltaV = ( dx * dxy - dy * dxx )/det;
+//       if (deltaH > (-1.0) && deltaH < 1.0 && deltaV > (-1.0) && deltaV < 1.0)
+//         {
+//         hDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
+//         vDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
+//         }
+//       else
+//         {
+//         return false;
+//         }
+//       }
+//     }
+//   
+//   return true;
+// }
 
 } // End namespace otb
 
diff --git a/Code/DisparityMap/otbSubPixelDisparityImageFilter.h b/Code/DisparityMap/otbSubPixelDisparityImageFilter.h
index 2fc49e7e7d308a4afa3365bded0adbdb2878c907..a65e80aef9a73c13132a61d675dd88f5dec8e174 100644
--- a/Code/DisparityMap/otbSubPixelDisparityImageFilter.h
+++ b/Code/DisparityMap/otbSubPixelDisparityImageFilter.h
@@ -20,13 +20,34 @@
 
 #include "otbPixelWiseBlockMatchingImageFilter.h"
 
+#include "itkResampleImageFilter.h"
+#include "itkTranslationTransform.h"
+
 namespace otb
 {
 
 /** \class SubPixelDisparityImageFilter
  *  \brief Perform sub-pixel disparity estimation from input integer disparities and the image pair that was used
  *
+ *  This filter is intended to be placed after a PixelWiseBlockMatchingImageFilter. Its role is to produce an estimate
+ *  of the disparities (both horizontal and vertical) with sub-pixel precision. The integer input disparities are used
+ *  as starting points for the disparity refinement. The refinement is done within a 3x3 neighborhood around this 
+ *  position (it is neighborhood in the 2D disparity space). If no input disparity is given, the shift between 
+ *  input images is assumed to be null along both directions.
+ *
+ *  Left and right masks can be used to skip the sub-pixel disparity refinement for couples of pixels carrying a 
+ *  non-positive mask value. 
+ *  
+ *  The exploration limits for horizontal and vertical disparities can be set like in PixelWiseBlockMatchingFilter.
+ *  If the 3x3 neighborhood around the initial estimate is not inside the exploration area, refinement is skipped for
+ *  the current pixel.
  *
+ *  Before trying to refine the integer disparity, the filter checks that the initial position is an extrema for the 
+ *  metric used. Depending on the 3x3 neighborhood, the refinement can be done along the horizontal axis only, along 
+ *  the vertical axis only, and also in 2D. Three refinement methods are proposed : parabolic, triangular and dichotomy.
+ *  The parabolic method tries to fit a parabola to the metric scores on the 3x3 neighborhood. The triangular 
+ *  method tries to fit local scores to a circular cone. The dichotomy method tries to find the local extrema by 
+ *  a dichotomic search (non-integer disparity positions are tested after a resampling of the right image).
  *
  *  \sa PixelWiseBlockMatchingImageFilter
  *  \sa FineRegistrationImageFilter
@@ -36,7 +57,8 @@ namespace otb
  *  \ingroup Threaded
  *
  */
-template <class TInputImage, class TOutputMetricImage, class TDisparityImage = TOutputMetricImage, class TMaskImage = otb::Image<unsigned char>,
+template <class TInputImage, class TOutputMetricImage, class TDisparityImage = TOutputMetricImage, 
+          class TMaskImage = otb::Image<unsigned char>,
           class TBlockMatchingFunctor = Functor::SSDBlockMatching<TInputImage,TOutputMetricImage> >
 class ITK_EXPORT SubPixelDisparityImageFilter :
     public itk::ImageToImageFilter<TInputImage,TDisparityImage>
@@ -58,7 +80,7 @@ public:
   /** Usefull typedefs */
   typedef TInputImage                                       InputImageType;
   typedef TOutputMetricImage                                OutputMetricImageType;
-  typedef TDisparityImage                             OutputDisparityImageType;
+  typedef TDisparityImage                                   OutputDisparityImageType;
   typedef TMaskImage                                        InputMaskImageType;
   typedef TBlockMatchingFunctor                             BlockMatchingFunctorType;
 
@@ -70,6 +92,15 @@ public:
   
   typedef itk::ConstNeighborhoodIterator<TInputImage>       ConstNeighborhoodIteratorType;
   
+  typedef itk::ResampleImageFilter<TInputImage,TInputImage,double>  ResamplerFilterType;
+  typedef itk::TranslationTransform<double,2> TransformationType;
+  typedef otb::PixelWiseBlockMatchingImageFilter
+          < InputImageType,
+            OutputMetricImageType,
+            OutputDisparityImageType,
+            InputMaskImageType,
+            BlockMatchingFunctorType> BlockMatchingFilterType;
+  
   itkStaticConstMacro(PARABOLIC,int,0);
   itkStaticConstMacro(TRIANGULAR,int,1);
   itkStaticConstMacro(DICHOTOMY,int,2);
@@ -159,6 +190,8 @@ public:
   /** Set/Get the refinement method (PARABOLIC, TRIANGULAR or DICHOTOMY) */
   itkSetMacro(RefineMethod,int);
   itkGetMacro(RefineMethod,int);
+  
+  void SetInputsFromBlockMatchingFilter(const BlockMatchingFilterType * filter);
 
 protected:
   /** Constructor */
@@ -177,7 +210,7 @@ protected:
   virtual void ThreadedGenerateData(const RegionType & outputRegionForThread, int threadId);
   
 private:
-  PixelWiseBlockMatchingImageFilter(const Self&); //purposely not implemented
+  SubPixelDisparityImageFilter(const Self&); //purposely not implemented
   void operator=(const Self&); //purposely not implemented
   
   /** parabolic refinement method */
diff --git a/Code/DisparityMap/otbSubPixelDisparityImageFilter.txx b/Code/DisparityMap/otbSubPixelDisparityImageFilter.txx
index b64eeeeb9768a8e42ed42369267b8177a32f5aac..c1fa6fb116c333ee9a9120b3960b949026f42f5e 100644
--- a/Code/DisparityMap/otbSubPixelDisparityImageFilter.txx
+++ b/Code/DisparityMap/otbSubPixelDisparityImageFilter.txx
@@ -18,6 +18,8 @@
 #ifndef __otbSubPixelDisparityImageFilter_txx
 #define __otbSubPixelDisparityImageFilter_txx
 
+
+
 namespace otb
 {
 template <class TInputImage, class TOutputMetricImage,
@@ -48,6 +50,7 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   m_MinimumVerticalDisparity = 0;
   m_MaximumVerticalDisparity = 0;
   
+  // Default refinement method : parabolic
   m_RefineMethod = 0;
 }
 
@@ -292,6 +295,45 @@ if (this->GetNumberOfOutputs()<3)
   return static_cast<TDisparityImage *>(this->itk::ProcessObject::GetOutput(2));
 }
 
+template <class TInputImage, class TOutputMetricImage,
+class TDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
+void
+SubPixelDisparityImageFilter<TInputImage,TOutputMetricImage,
+TDisparityImage,TMaskImage,TBlockMatchingFunctor>
+::SetInputsFromBlockMatchingFilter(const BlockMatchingFilterType * filter)
+{
+  this->SetLeftInput(filter->GetLeftInput());
+  this->SetRightInput(filter->GetRightInput());
+  
+  this->SetRadius(filter->GetRadius());
+  
+  this->SetMinimumHorizontalDisparity(filter->GetMinimumHorizontalDisparity());
+  this->SetMaximumHorizontalDisparity(filter->GetMaximumHorizontalDisparity());
+  
+  this->SetMinimumVerticalDisparity(filter->GetMinimumVerticalDisparity());
+  this->SetMaximumVerticalDisparity(filter->GetMaximumVerticalDisparity());
+  
+  this->SetMinimize(filter->GetMinimize());
+  
+  if (filter->GetHorizontalDisparityOutput())
+    {
+    this->SetHorizontalDisparityInput(filter->GetHorizontalDisparityOutput());
+    }
+  if (filter->GetVerticalDisparityOutput())
+    {
+    this->SetVerticalDisparityInput(filter->GetVerticalDisparityOutput());
+    }
+  if (filter->GetLeftMaskInput())
+    {
+    this->SetLeftMaskInput(filter->GetLeftMaskInput());
+    }
+  if (filter->GetRightMaskInput())
+    {
+    this->SetRightMaskInput(filter->GetRightMaskInput());
+    }
+  
+}
+
 template <class TInputImage, class TOutputMetricImage,
 class TDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
 void
@@ -509,8 +551,8 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   itk::ImageRegionIterator<TDisparityImage> outHDispIt(outHDispPtr,outputRegionForThread);
   itk::ImageRegionIterator<TDisparityImage> outVDispIt(outVDispPtr,outputRegionForThread);
   itk::ImageRegionIterator<TOutputMetricImage>    outMetricIt(outMetricPtr,outputRegionForThread);
-  itk::ImageRegionIterator<TDisparityImage> inHDispIt;
-  itk::ImageRegionIterator<TDisparityImage> inVDispIt;
+  itk::ImageRegionConstIterator<TDisparityImage>  inHDispIt;
+  itk::ImageRegionConstIterator<TDisparityImage>  inVDispIt;
   itk::ImageRegionConstIterator<TMaskImage>       inLeftMaskIt;
   itk::ImageRegionConstIterator<TMaskImage>       inRightMaskIt;
   
@@ -532,12 +574,13 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   
   if(inLeftMaskPtr)
     {
-    inLeftMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inLeftMaskPtr,inputLeftRegion);
+    inLeftMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inLeftMaskPtr,outputRegionForThread);
     inLeftMaskIt.GoToBegin();
     }
+  RegionType rightBufferedRegion = inRightPtr->GetBufferedRegion();
   if(inRightMaskPtr)
     {
-    inRightMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inRightMaskPtr,inputRightRegion);
+    inRightMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inRightMaskPtr,rightBufferedRegion);
     inRightMaskIt.GoToBegin();
     }
   
@@ -552,7 +595,7 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   /* Specific variables */
   IndexType curLeftPos;
   IndexType curRightPos;
-  RegionType rightBufferedRegion = inRightPtr->GetBufferedRegion();
+  
   float hDisp_f;
   float vDisp_f;
   int hDisp_i;
@@ -564,8 +607,6 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   
   // metrics for neighbors positions : first index is x, second is y
   double neighborsMetric[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
-  //int firstNeighbor = 0;
-  //int stepNeighbor = 4;
   
   while (!leftIt.IsAtEnd()
         || !outHDispIt.IsAtEnd()
@@ -580,7 +621,7 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
     
     if (useHorizontalDisparity)
       {
-      hDisp_f = static_cast<float>(hDispIt.Get());
+      hDisp_f = static_cast<float>(outHDispIt.Get());
       hDisp_i = static_cast<int>(vcl_floor(hDisp_f + 0.5));
       curRightPos[0] = curLeftPos[0] + hDisp_i;
       }
@@ -593,7 +634,7 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
     
     if (useVerticalDisparity)
       {
-      vDisp_f = static_cast<float>(vDispIt.Get());
+      vDisp_f = static_cast<float>(outVDispIt.Get());
       vDisp_i = static_cast<int>(vcl_floor(vDisp_f + 0.5));
       curRightPos[1] = curLeftPos[1] + vDisp_i;
       }
@@ -606,133 +647,145 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
     // check if the current right position is inside the right image
     if (rightBufferedRegion.IsInside(curRightPos))
       {
-      RegionType smallRightRegion;
-      smallRightRegion.SetIndex(0,curRightPos[0]-1);
-      smallRightRegion.SetIndex(1,curRightPos[1]-1);
-      smallRightRegion.SetSize(0,3);
-      smallRightRegion.SetSize(1,3);
-      
-      itk::ConstNeighborhoodIterator<TInputImage>     rightIt(m_Radius,inRightPtr,smallRightRegion);
-      
-      // compute metric at centre position
-      rightIt.SetLocation(curRightPos);
-      neighborsMetric[1][1] = m_Functor(leftIt,rightIt);
-      
-      if (m_MinimumVerticalDisparity < vDisp_i && vDisp_i < m_MaximumVerticalDisparity)
+      if (inRightMaskPtr)
         {
-        IndexType upIndex(curRightPos);
-        upIndex[1]+= (-1);
-        IndexType downIndex(curRightPos);
-        downIndex[1]+= 1;
-        if ( rightBufferedRegion.IsInside(upIndex) && rightBufferedRegion.IsInside(downIndex) )
+        // Set right mask iterator position
+        inRightMaskIt.SetIndex(curRightPos);
+        }
+      // check that the current positions are not masked
+      if(!inLeftMaskPtr || (inLeftMaskPtr && inLeftMaskIt.Get() > 0) )
+        {
+        if(!inRightMaskPtr || (inRightMaskPtr && inRightMaskIt.Get() > 0) )
           {
-          rightIt.SetLocation(upIndex);
-          neighborsMetric[1][0] = m_Functor(leftIt,rightIt);
+          RegionType smallRightRegion;
+          smallRightRegion.SetIndex(0,curRightPos[0]-1);
+          smallRightRegion.SetIndex(1,curRightPos[1]-1);
+          smallRightRegion.SetSize(0,3);
+          smallRightRegion.SetSize(1,3);
           
-          rightIt.SetLocation(downIndex);
-          neighborsMetric[1][2] = m_Functor(leftIt,rightIt);
+          itk::ConstNeighborhoodIterator<TInputImage>     rightIt(m_Radius,inRightPtr,smallRightRegion);
           
-          // check that current position is an extrema
-          if (m_Minimize)
+          // compute metric at centre position
+          rightIt.SetLocation(curRightPos);
+          neighborsMetric[1][1] = m_Functor(leftIt,rightIt);
+          
+          if (m_MinimumVerticalDisparity < vDisp_i && vDisp_i < m_MaximumVerticalDisparity)
             {
-            if (neighborsMetric[1][1] < neighborsMetric[1][0] && neighborsMetric[1][1] < neighborsMetric[1][2])
+            IndexType upIndex(curRightPos);
+            upIndex[1]+= (-1);
+            IndexType downIndex(curRightPos);
+            downIndex[1]+= 1;
+            if ( rightBufferedRegion.IsInside(upIndex) && rightBufferedRegion.IsInside(downIndex) )
               {
-              verticalInterpolation = true;
+              rightIt.SetLocation(upIndex);
+              neighborsMetric[1][0] = m_Functor(leftIt,rightIt);
+              
+              rightIt.SetLocation(downIndex);
+              neighborsMetric[1][2] = m_Functor(leftIt,rightIt);
+              
+          // check that current position is an extrema
+              if (m_Minimize)
+                {
+                if (neighborsMetric[1][1] < neighborsMetric[1][0] && neighborsMetric[1][1] < neighborsMetric[1][2])
+                  {
+                  verticalInterpolation = true;
+                  }
+                }
+              else
+                {
+                if (neighborsMetric[1][1] > neighborsMetric[1][0] && neighborsMetric[1][1] > neighborsMetric[1][2])
+                  {
+                  verticalInterpolation = true;
+                  }
+                }
               }
             }
-          else
+          
+          if (m_MinimumHorizontalDisparity < hDisp_i && hDisp_i < m_MaximumHorizontalDisparity)
             {
-            if (neighborsMetric[1][1] > neighborsMetric[1][0] && neighborsMetric[1][1] > neighborsMetric[1][2])
-              {
-              verticalInterpolation = true;
+            IndexType leftIndex(curRightPos);
+            leftIndex[0]+= (-1);
+            IndexType rightIndex(curRightPos);
+            rightIndex[0]+= 1;
+            if ( rightBufferedRegion.IsInside(leftIndex) && rightBufferedRegion.IsInside(rightIndex) )
+          {
+              rightIt.SetLocation(rightIndex);
+              neighborsMetric[2][1] = m_Functor(leftIt,rightIt);
+              
+              rightIt.SetLocation(leftIndex);
+              neighborsMetric[0][1] = m_Functor(leftIt,rightIt);
+              
+          // check that current position is an extrema
+              if (m_Minimize)
+                {
+                if (neighborsMetric[1][1] < neighborsMetric[0][1] && neighborsMetric[1][1] < neighborsMetric[2][1])
+                  {
+                  horizontalInterpolation = true;
+                  }
+                }
+              else
+                {
+                if (neighborsMetric[1][1] > neighborsMetric[0][1] && neighborsMetric[1][1] > neighborsMetric[2][1])
+                  {
+                  horizontalInterpolation = true;
+                  }
+                }
               }
             }
-          }
-        }
-      
-      if (m_MinimumHorizontalDisparity < hDisp_i && hDisp_i < m_MaximumHorizontalDisparity)
-        {
-        IndexType leftIndex(curRightPos);
-        leftIndex[0]+= (-1);
-        IndexType rightIndex(curRightPos);
-        rightIndex[0]+= 1;
-        if ( rightBufferedRegion.IsInside(leftIndex) && rightBufferedRegion.IsInside(rightIndex) )
-          {
-          rightIt.SetLocation(rightIndex);
-          neighborsMetric[2][1] = m_Functor(leftIt,rightIt);
-          
-          rightIt.SetLocation(leftIndex);
-          neighborsMetric[0][1] = m_Functor(leftIt,rightIt);
           
-          // check that current position is an extrema
-          if (m_Minimize)
+          // if both vertical and horizontal interpolation, compute metrics on corners
+          if (verticalInterpolation && horizontalInterpolation)
             {
-            if (neighborsMetric[1][1] < neighborsMetric[0][1] && neighborsMetric[1][1] < neighborsMetric[2][1])
+            IndexType uprightIndex(curRightPos);
+            uprightIndex[0]+= 1;
+            uprightIndex[1]+= (-1);
+            rightIt.SetLocation(uprightIndex);
+            neighborsMetric[2][0] = m_Functor(leftIt,rightIt);
+            
+            IndexType downrightIndex(curRightPos);
+            downrightIndex[0]+= 1;
+            downrightIndex[1]+= 1;
+            rightIt.SetLocation(downrightIndex);
+            neighborsMetric[2][2] = m_Functor(leftIt,rightIt);
+            
+            IndexType downleftIndex(curRightPos);
+            downleftIndex[0]+= (-1);
+            downleftIndex[1]+= 1;
+            rightIt.SetLocation(downleftIndex);
+            neighborsMetric[0][2] = m_Functor(leftIt,rightIt);
+            
+            IndexType upleftIndex(curRightPos);
+            upleftIndex[0]+= (-1);
+            upleftIndex[1]+= (-1);
+            rightIt.SetLocation(upleftIndex);
+            neighborsMetric[0][0] = m_Functor(leftIt,rightIt);
+            
+            //check that it is an extrema
+            if (m_Minimize)
               {
-              horizontalInterpolation = true;
+              if (neighborsMetric[1][1] > neighborsMetric[2][0] ||
+                  neighborsMetric[1][1] > neighborsMetric[2][2] ||
+                  neighborsMetric[1][1] > neighborsMetric[0][2] ||
+                  neighborsMetric[1][1] > neighborsMetric[0][0])
+                {
+                verticalInterpolation = false;
+                horizontalInterpolation = false;
+                }
               }
-            }
-          else
-            {
-            if (neighborsMetric[1][1] > neighborsMetric[0][1] && neighborsMetric[1][1] > neighborsMetric[2][1])
+            else
               {
-              horizontalInterpolation = true;
+              if (neighborsMetric[1][1] < neighborsMetric[2][0] ||
+                  neighborsMetric[1][1] < neighborsMetric[2][2] ||
+                  neighborsMetric[1][1] < neighborsMetric[0][2] ||
+                  neighborsMetric[1][1] < neighborsMetric[0][0])
+                {
+                verticalInterpolation = false;
+                horizontalInterpolation = false;
+                }
               }
             }
           }
         }
-      
-      // if both vertical and horizontal interpolation, compute metrics on corners
-      if (verticalInterpolation && horizontalInterpolation)
-        {
-        IndexType uprightIndex(curRightPos);
-        uprightIndex[0]+= 1;
-        uprightIndex[1]+= (-1);
-        rightIt.SetLocation(uprightIndex);
-        neighborsMetric[2][0] = m_Functor(leftIt,rightIt);
-        
-        IndexType downrightIndex(curRightPos);
-        downrightIndex[0]+= 1;
-        downrightIndex[1]+= 1;
-        rightIt.SetLocation(downrightIndex);
-        neighborsMetric[2][2] = m_Functor(leftIt,rightIt);
-        
-        IndexType downleftIndex(curRightPos);
-        downleftIndex[0]+= (-1);
-        downleftIndex[1]+= 1;
-        rightIt.SetLocation(downleftIndex);
-        neighborsMetric[0][2] = m_Functor(leftIt,rightIt);
-        
-        IndexType upleftIndex(curRightPos);
-        upleftIndex[0]+= (-1);
-        upleftIndex[1]+= (-1);
-        rightIt.SetLocation(upleftIndex);
-        neighborsMetric[0][0] = m_Functor(leftIt,rightIt);
-        
-        //check that it is an extrema
-        if (m_Minimize)
-          {
-          if (neighborsMetric[1][1] > neighborsMetric[2][0] ||
-              neighborsMetric[1][1] > neighborsMetric[2][2] ||
-              neighborsMetric[1][1] > neighborsMetric[0][2] ||
-              neighborsMetric[1][1] > neighborsMetric[0][0])
-            {
-            verticalInterpolation = false;
-            horizontalInterpolation = false;
-            }
-          }
-        else
-          {
-          if (neighborsMetric[1][1] < neighborsMetric[2][0] ||
-              neighborsMetric[1][1] < neighborsMetric[2][2] ||
-              neighborsMetric[1][1] < neighborsMetric[0][2] ||
-              neighborsMetric[1][1] < neighborsMetric[0][0])
-            {
-            verticalInterpolation = false;
-            horizontalInterpolation = false;
-            }
-          }
-        }
       }
     
     // Interpolate position : parabola fit
@@ -741,9 +794,12 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       //vertical only
       double deltaV = 0.5 - (1.0 /
         (1.0 + (neighborsMetric[1][0]-neighborsMetric[1][1]) / (neighborsMetric[1][2]-neighborsMetric[1][1])));
+      double interpMetric = neighborsMetric[1][1] - 
+        (0.5 * (neighborsMetric[1][0]+neighborsMetric[1][2]) - neighborsMetric[1][1]) * deltaV * deltaV;
       if (deltaV > (-0.5) && deltaV < 0.5)
         {
         outVDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
+        outMetricIt.Set(interpMetric);
         }
       else
         {
@@ -755,9 +811,12 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       // horizontal only
       double deltaH = 0.5 - (1.0 /
         (1.0 + (neighborsMetric[0][1]-neighborsMetric[1][1]) / (neighborsMetric[2][1]-neighborsMetric[1][1])));
+      double interpMetric = neighborsMetric[1][1] - 
+        (0.5 * (neighborsMetric[0][1]+neighborsMetric[2][1]) - neighborsMetric[1][1]) * deltaH * deltaH;
       if (deltaH > (-0.5) && deltaH < 0.5)
         {
         outHDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
+        outMetricIt.Set(interpMetric);
         }
       else
         {
@@ -782,10 +841,13 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
         {
         double deltaH = (-dx * dyy + dy * dxy )/det;
         double deltaV = ( dx * dxy - dy * dxx )/det;
+        double interpMetric = neighborsMetric[1][1] - 
+          ( dxx * deltaH * deltaH + 2.0 * dxy * deltaH * deltaV + dyy * deltaV * deltaV);
         if (deltaH > (-1.0) && deltaH < 1.0 && deltaV > (-1.0) && deltaV < 1.0)
           {
           outHDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
           outVDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
+          outMetricIt.Set(interpMetric);
           }
         else
           {
@@ -795,7 +857,6 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
         }
       }
     
-    
     if (!verticalInterpolation)
       {
       // No vertical interpolation done : simply copy the integer vertical disparity
@@ -808,6 +869,10 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       outHDispIt.Set( static_cast<double>(hDisp_i));
       }
     
+    if (!verticalInterpolation && !horizontalInterpolation)
+      {
+      outMetricIt.Set(static_cast<double>(neighborsMetric[1][1]));
+      }
     
     progress.CompletedPixel();
     
@@ -824,16 +889,10 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       {
       ++inVDispIt;
       }
-      
     if(inLeftMaskPtr)
       {
       ++inLeftMaskIt;
       }
-    
-    if(inRightMaskPtr)
-      {
-      ++inRightMaskIt;
-      }
     }
 }
 
@@ -844,16 +903,7 @@ SubPixelDisparityImageFilter<TInputImage,TOutputMetricImage,
 TDisparityImage,TMaskImage,TBlockMatchingFunctor>
 ::TriangularRefinement(const RegionType& outputRegionForThread, int threadId)
 {
-}
-
-template <class TInputImage, class TOutputMetricImage,
-class TDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
-void
-SubPixelDisparityImageFilter<TInputImage,TOutputMetricImage,
-TDisparityImage,TMaskImage,TBlockMatchingFunctor>
-::DichotomyRefinement(const RegionType& outputRegionForThread, int threadId)
-{
-// Retrieve pointers
+  // Retrieve pointers
   const TInputImage *     inLeftPtr    = this->GetLeftInput();
   const TInputImage *     inRightPtr   = this->GetRightInput();
   const TMaskImage  *     inLeftMaskPtr    = this->GetLeftMaskInput();
@@ -872,8 +922,8 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   itk::ImageRegionIterator<TDisparityImage> outHDispIt(outHDispPtr,outputRegionForThread);
   itk::ImageRegionIterator<TDisparityImage> outVDispIt(outVDispPtr,outputRegionForThread);
   itk::ImageRegionIterator<TOutputMetricImage>    outMetricIt(outMetricPtr,outputRegionForThread);
-  itk::ImageRegionIterator<TDisparityImage> inHDispIt;
-  itk::ImageRegionIterator<TDisparityImage> inVDispIt;
+  itk::ImageRegionConstIterator<TDisparityImage>  inHDispIt;
+  itk::ImageRegionConstIterator<TDisparityImage>  inVDispIt;
   itk::ImageRegionConstIterator<TMaskImage>       inLeftMaskIt;
   itk::ImageRegionConstIterator<TMaskImage>       inRightMaskIt;
   
@@ -895,12 +945,13 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   
   if(inLeftMaskPtr)
     {
-    inLeftMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inLeftMaskPtr,inputLeftRegion);
+    inLeftMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inLeftMaskPtr,outputRegionForThread);
     inLeftMaskIt.GoToBegin();
     }
+  RegionType rightBufferedRegion = inRightPtr->GetBufferedRegion();
   if(inRightMaskPtr)
     {
-    inRightMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inRightMaskPtr,inputRightRegion);
+    inRightMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inRightMaskPtr,rightBufferedRegion);
     inRightMaskIt.GoToBegin();
     }
   
@@ -915,7 +966,7 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   /* Specific variables */
   IndexType curLeftPos;
   IndexType curRightPos;
-  RegionType rightBufferedRegion = inRightPtr->GetBufferedRegion();
+  
   float hDisp_f;
   float vDisp_f;
   int hDisp_i;
@@ -925,10 +976,8 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
   bool horizontalInterpolation = false;
   bool verticalInterpolation = false;
   
-  // metrics for neighbors positions : first index is x, second is y
+  // metrics for neighbors positions : first index is x, second is y 
   double neighborsMetric[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
-  //int firstNeighbor = 0;
-  //int stepNeighbor = 4;
   
   while (!leftIt.IsAtEnd()
         || !outHDispIt.IsAtEnd()
@@ -943,7 +992,7 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
     
     if (useHorizontalDisparity)
       {
-      hDisp_f = static_cast<float>(hDispIt.Get());
+      hDisp_f = static_cast<float>(outHDispIt.Get());
       hDisp_i = static_cast<int>(vcl_floor(hDisp_f + 0.5));
       curRightPos[0] = curLeftPos[0] + hDisp_i;
       }
@@ -956,7 +1005,7 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
     
     if (useVerticalDisparity)
       {
-      vDisp_f = static_cast<float>(vDispIt.Get());
+      vDisp_f = static_cast<float>(outVDispIt.Get());
       vDisp_i = static_cast<int>(vcl_floor(vDisp_f + 0.5));
       curRightPos[1] = curLeftPos[1] + vDisp_i;
       }
@@ -969,130 +1018,572 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
     // check if the current right position is inside the right image
     if (rightBufferedRegion.IsInside(curRightPos))
       {
-      RegionType smallRightRegion;
-      smallRightRegion.SetIndex(0,curRightPos[0]-1);
-      smallRightRegion.SetIndex(1,curRightPos[1]-1);
-      smallRightRegion.SetSize(0,3);
-      smallRightRegion.SetSize(1,3);
-      
-      itk::ConstNeighborhoodIterator<TInputImage>     rightIt(m_Radius,inRightPtr,smallRightRegion);
-      
-      // compute metric at centre position
-      rightIt.SetLocation(curRightPos);
-      neighborsMetric[1][1] = m_Functor(leftIt,rightIt);
-      
-      if (m_MinimumVerticalDisparity < vDisp_i && vDisp_i < m_MaximumVerticalDisparity)
+      if (inRightMaskPtr)
+        {
+        // Set right mask iterator position
+        inRightMaskIt.SetIndex(curRightPos);
+        }
+      // check that the current positions are not masked
+      if(!inLeftMaskPtr || (inLeftMaskPtr && inLeftMaskIt.Get() > 0) )
         {
-        IndexType upIndex(curRightPos);
-        upIndex[1]+= (-1);
-        IndexType downIndex(curRightPos);
-        downIndex[1]+= 1;
-        if ( rightBufferedRegion.IsInside(upIndex) && rightBufferedRegion.IsInside(downIndex) )
+        if(!inRightMaskPtr || (inRightMaskPtr && inRightMaskIt.Get() > 0) )
           {
-          rightIt.SetLocation(upIndex);
-          neighborsMetric[1][0] = m_Functor(leftIt,rightIt);
+          RegionType smallRightRegion;
+          smallRightRegion.SetIndex(0,curRightPos[0]-1);
+          smallRightRegion.SetIndex(1,curRightPos[1]-1);
+          smallRightRegion.SetSize(0,3);
+          smallRightRegion.SetSize(1,3);
           
-          rightIt.SetLocation(downIndex);
-          neighborsMetric[1][2] = m_Functor(leftIt,rightIt);
+          itk::ConstNeighborhoodIterator<TInputImage>     rightIt(m_Radius,inRightPtr,smallRightRegion);
           
-          // check that current position is an extrema
-          if (m_Minimize)
+          // compute metric at centre position
+          rightIt.SetLocation(curRightPos);
+          neighborsMetric[1][1] = m_Functor(leftIt,rightIt);
+          
+          if (m_MinimumVerticalDisparity < vDisp_i && vDisp_i < m_MaximumVerticalDisparity)
             {
-            if (neighborsMetric[1][1] < neighborsMetric[1][0] && neighborsMetric[1][1] < neighborsMetric[1][2])
+            IndexType upIndex(curRightPos);
+            upIndex[1]+= (-1);
+            IndexType downIndex(curRightPos);
+            downIndex[1]+= 1;
+            if ( rightBufferedRegion.IsInside(upIndex) && rightBufferedRegion.IsInside(downIndex) )
               {
-              verticalInterpolation = true;
+              rightIt.SetLocation(upIndex);
+              neighborsMetric[1][0] = m_Functor(leftIt,rightIt);
+              
+              rightIt.SetLocation(downIndex);
+              neighborsMetric[1][2] = m_Functor(leftIt,rightIt);
+              
+              // check that current position is an extrema 
+              if (m_Minimize)
+                {
+                if (neighborsMetric[1][1] < neighborsMetric[1][0] && neighborsMetric[1][1] < neighborsMetric[1][2])
+                  {
+                  verticalInterpolation = true;
+                  }
+                }
+              else
+                {
+                if (neighborsMetric[1][1] > neighborsMetric[1][0] && neighborsMetric[1][1] > neighborsMetric[1][2])
+                  {
+                  verticalInterpolation = true;
+                  }
+                }
               }
             }
-          else
+          
+          if (m_MinimumHorizontalDisparity < hDisp_i && hDisp_i < m_MaximumHorizontalDisparity)
             {
-            if (neighborsMetric[1][1] > neighborsMetric[1][0] && neighborsMetric[1][1] > neighborsMetric[1][2])
-              {
-              verticalInterpolation = true;
+            IndexType leftIndex(curRightPos);
+            leftIndex[0]+= (-1);
+            IndexType rightIndex(curRightPos);
+            rightIndex[0]+= 1;
+            if ( rightBufferedRegion.IsInside(leftIndex) && rightBufferedRegion.IsInside(rightIndex) )
+              {          
+              rightIt.SetLocation(rightIndex);
+              neighborsMetric[2][1] = m_Functor(leftIt,rightIt);
+              
+              rightIt.SetLocation(leftIndex);
+              neighborsMetric[0][1] = m_Functor(leftIt,rightIt);
+              
+              // check that current position is an extrema 
+              if (m_Minimize)
+                {
+                if (neighborsMetric[1][1] < neighborsMetric[0][1] && neighborsMetric[1][1] < neighborsMetric[2][1])
+                  {
+                  horizontalInterpolation = true;
+                  }
+                }
+              else
+                {
+                if (neighborsMetric[1][1] > neighborsMetric[0][1] && neighborsMetric[1][1] > neighborsMetric[2][1])
+                  {
+                  horizontalInterpolation = true;
+                  }
+                }
               }
             }
-          }
-        }
-      
-      if (m_MinimumHorizontalDisparity < hDisp_i && hDisp_i < m_MaximumHorizontalDisparity)
-        {
-        IndexType leftIndex(curRightPos);
-        leftIndex[0]+= (-1);
-        IndexType rightIndex(curRightPos);
-        rightIndex[0]+= 1;
-        if ( rightBufferedRegion.IsInside(leftIndex) && rightBufferedRegion.IsInside(rightIndex) )
-          {
-          rightIt.SetLocation(rightIndex);
-          neighborsMetric[2][1] = m_Functor(leftIt,rightIt);
           
-          rightIt.SetLocation(leftIndex);
-          neighborsMetric[0][1] = m_Functor(leftIt,rightIt);
-          
-          // check that current position is an extrema
-          if (m_Minimize)
+          // if both vertical and horizontal interpolation, compute metrics on corners
+          if (verticalInterpolation && horizontalInterpolation)
             {
-            if (neighborsMetric[1][1] < neighborsMetric[0][1] && neighborsMetric[1][1] < neighborsMetric[2][1])
+            IndexType uprightIndex(curRightPos);
+            uprightIndex[0]+= 1;
+            uprightIndex[1]+= (-1);
+            rightIt.SetLocation(uprightIndex);
+            neighborsMetric[2][0] = m_Functor(leftIt,rightIt);
+            
+            IndexType downrightIndex(curRightPos);
+            downrightIndex[0]+= 1;
+            downrightIndex[1]+= 1;
+            rightIt.SetLocation(downrightIndex);
+            neighborsMetric[2][2] = m_Functor(leftIt,rightIt);
+            
+            IndexType downleftIndex(curRightPos);
+            downleftIndex[0]+= (-1);
+            downleftIndex[1]+= 1;
+            rightIt.SetLocation(downleftIndex);
+            neighborsMetric[0][2] = m_Functor(leftIt,rightIt);
+            
+            IndexType upleftIndex(curRightPos);
+            upleftIndex[0]+= (-1);
+            upleftIndex[1]+= (-1);
+            rightIt.SetLocation(upleftIndex);
+            neighborsMetric[0][0] = m_Functor(leftIt,rightIt);
+            
+            //check that it is an extrema
+            if (m_Minimize)
               {
-              horizontalInterpolation = true;
+              if (neighborsMetric[1][1] > neighborsMetric[2][0] ||
+                  neighborsMetric[1][1] > neighborsMetric[2][2] ||
+                  neighborsMetric[1][1] > neighborsMetric[0][2] ||
+                  neighborsMetric[1][1] > neighborsMetric[0][0])
+                {
+                verticalInterpolation = false;
+                horizontalInterpolation = false;
+                }
               }
-            }
-          else
-            {
-            if (neighborsMetric[1][1] > neighborsMetric[0][1] && neighborsMetric[1][1] > neighborsMetric[2][1])
+            else
               {
-              horizontalInterpolation = true;
+              if (neighborsMetric[1][1] < neighborsMetric[2][0] ||
+                  neighborsMetric[1][1] < neighborsMetric[2][2] ||
+                  neighborsMetric[1][1] < neighborsMetric[0][2] ||
+                  neighborsMetric[1][1] < neighborsMetric[0][0])
+                {
+                verticalInterpolation = false;
+                horizontalInterpolation = false;
+                }
               }
             }
           }
         }
-      
-      // if both vertical and horizontal interpolation, compute metrics on corners
-      if (verticalInterpolation && horizontalInterpolation)
+      }
+    
+    // Interpolate position : triangular fit
+    if (verticalInterpolation && !horizontalInterpolation)
+      {
+      //vertical only
+      double deltaV;
+      double interpMetric;
+      if (neighborsMetric[1][0] < neighborsMetric[1][2])
         {
-        IndexType uprightIndex(curRightPos);
-        uprightIndex[0]+= 1;
-        uprightIndex[1]+= (-1);
-        rightIt.SetLocation(uprightIndex);
-        neighborsMetric[2][0] = m_Functor(leftIt,rightIt);
-        
-        IndexType downrightIndex(curRightPos);
-        downrightIndex[0]+= 1;
-        downrightIndex[1]+= 1;
-        rightIt.SetLocation(downrightIndex);
-        neighborsMetric[2][2] = m_Functor(leftIt,rightIt);
-        
-        IndexType downleftIndex(curRightPos);
-        downleftIndex[0]+= (-1);
-        downleftIndex[1]+= 1;
-        rightIt.SetLocation(downleftIndex);
-        neighborsMetric[0][2] = m_Functor(leftIt,rightIt);
-        
-        IndexType upleftIndex(curRightPos);
-        upleftIndex[0]+= (-1);
-        upleftIndex[1]+= (-1);
-        rightIt.SetLocation(upleftIndex);
-        neighborsMetric[0][0] = m_Functor(leftIt,rightIt);
+        deltaV = 0.5 * ((neighborsMetric[1][0]-neighborsMetric[1][2])/(neighborsMetric[1][2]-neighborsMetric[1][1]));
+        interpMetric = neighborsMetric[1][1] + 0.5*(neighborsMetric[1][0]-neighborsMetric[1][2]);
+        }
+      else
+        {
+        deltaV = 0.5 * ((neighborsMetric[1][0]-neighborsMetric[1][2])/(neighborsMetric[1][0]-neighborsMetric[1][1]));
+        interpMetric = neighborsMetric[1][1] + 0.5*(neighborsMetric[1][2]-neighborsMetric[1][0]);
+        }
+      if (deltaV > (-0.5) && deltaV < 0.5)
+        {
+        outVDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
+        outMetricIt.Set(interpMetric);
+        }
+      else
+        {
+        verticalInterpolation = false;
+        }
+      }
+    else if (!verticalInterpolation && horizontalInterpolation)
+      {
+      // horizontal only
+      double deltaH;
+      double interpMetric;
+      if (neighborsMetric[0][1] < neighborsMetric[2][1])
+        {
+        deltaH = 0.5 * ((neighborsMetric[0][1]-neighborsMetric[2][1])/(neighborsMetric[2][1]-neighborsMetric[1][1]));
+        interpMetric = neighborsMetric[1][1] + 0.5*(neighborsMetric[0][1]-neighborsMetric[2][1]);
+        }
+      else
+        {
+        deltaH = 0.5 * ((neighborsMetric[0][1]-neighborsMetric[2][1])/(neighborsMetric[0][1]-neighborsMetric[1][1]));
+        interpMetric = neighborsMetric[1][1] + 0.5*(neighborsMetric[2][1]-neighborsMetric[0][1]);
+        }
+      if (deltaH > (-0.5) && deltaH < 0.5)
+        {
+        outHDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
+        outMetricIt.Set(interpMetric);
+        }
+      else
+        {
+        horizontalInterpolation = false;
+        }
+      }
+    else if (verticalInterpolation && horizontalInterpolation)
+      {
+      //both horizontal and vertical
+      double deltaH;
+      double deltaV;
+      double interpMetricH;
+      double interpMetricV;
+      if (neighborsMetric[1][0] < neighborsMetric[1][2])
+        {
+        deltaV = 0.5 * ((neighborsMetric[1][0]-neighborsMetric[1][2])/(neighborsMetric[1][2]-neighborsMetric[1][1]));
+        interpMetricV = neighborsMetric[1][1] + 0.5*(neighborsMetric[1][0]-neighborsMetric[1][2]);
+        }
+      else
+        {
+        deltaV = 0.5 * ((neighborsMetric[1][0]-neighborsMetric[1][2])/(neighborsMetric[1][0]-neighborsMetric[1][1]));
+        interpMetricV = neighborsMetric[1][1] + 0.5*(neighborsMetric[1][2]-neighborsMetric[1][0]);
+        }
         
-        //check that it is an extrema
-        if (m_Minimize)
+      if (neighborsMetric[0][1] < neighborsMetric[2][1])
+        {
+        deltaH = 0.5 * ((neighborsMetric[0][1]-neighborsMetric[2][1])/(neighborsMetric[2][1]-neighborsMetric[1][1]));
+        interpMetricH = neighborsMetric[1][1] + 0.5*(neighborsMetric[0][1]-neighborsMetric[2][1]);
+        }
+      else
+        {
+        deltaH = 0.5 * ((neighborsMetric[0][1]-neighborsMetric[2][1])/(neighborsMetric[0][1]-neighborsMetric[1][1]));
+        interpMetricH = neighborsMetric[1][1] + 0.5*(neighborsMetric[2][1]-neighborsMetric[0][1]);
+        }
+      
+      if (deltaV > (-1.0) && deltaV < 1.0 && deltaH > (-1.0) && deltaH < 1.0)
+        {
+        outVDispIt.Set( static_cast<double>(vDisp_i) + deltaV);
+        outHDispIt.Set( static_cast<double>(hDisp_i) + deltaH);
+        outMetricIt.Set( interpMetricH*(vcl_abs(deltaH)/(vcl_abs(deltaV)+vcl_abs(deltaH))) + 
+                         interpMetricV*(vcl_abs(deltaV)/(vcl_abs(deltaV)+vcl_abs(deltaH))));
+        }
+      else
+        {
+        verticalInterpolation = false;
+        horizontalInterpolation = false;
+        }
+      }
+    
+    if (!verticalInterpolation)
+      {
+      // No vertical interpolation done : simply copy the integer vertical disparity
+      outVDispIt.Set( static_cast<double>(vDisp_i));
+      }
+    
+    if (!horizontalInterpolation)
+      {
+      // No horizontal interpolation done : simply copy the integer horizontal disparity
+      outHDispIt.Set( static_cast<double>(hDisp_i));
+      }
+    
+    if (!verticalInterpolation && !horizontalInterpolation)
+      {
+      outMetricIt.Set(static_cast<double>(neighborsMetric[1][1]));
+      }
+    
+    progress.CompletedPixel();
+    
+    ++leftIt;
+    ++outHDispIt;
+    ++outVDispIt;
+    ++outMetricIt;
+    
+    if (useHorizontalDisparity)
+      {
+      ++inHDispIt;
+      }
+    if (useVerticalDisparity)
+      {
+      ++inVDispIt;
+      }
+    if(inLeftMaskPtr)
+      {
+      ++inLeftMaskIt;
+      }
+    }
+}
+
+template <class TInputImage, class TOutputMetricImage,
+class TDisparityImage, class TMaskImage, class TBlockMatchingFunctor>
+void
+SubPixelDisparityImageFilter<TInputImage,TOutputMetricImage,
+TDisparityImage,TMaskImage,TBlockMatchingFunctor>
+::DichotomyRefinement(const RegionType& outputRegionForThread, int threadId)
+{
+  // Retrieve pointers
+  const TInputImage *     inLeftPtr    = this->GetLeftInput();
+  const TInputImage *     inRightPtr   = this->GetRightInput();
+  const TMaskImage  *     inLeftMaskPtr    = this->GetLeftMaskInput();
+  const TMaskImage  *     inRightMaskPtr    = this->GetRightMaskInput();
+  const TDisparityImage * inHDispPtr = this->GetHorizontalDisparityInput();
+  const TDisparityImage * inVDispPtr = this->GetVerticalDisparityInput();
+  TOutputMetricImage    * outMetricPtr = this->GetMetricOutput();
+  TDisparityImage * outHDispPtr   = this->GetHorizontalDisparityOutput();
+  TDisparityImage * outVDispPtr   = this->GetVerticalDisparityOutput();
+
+  // Set-up progress reporting (this is not exact, since we do not
+  // account for pixels that won't be refined)
+  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels(),100);
+  
+  itk::ConstNeighborhoodIterator<TInputImage>     leftIt(m_Radius,inLeftPtr,outputRegionForThread);
+  itk::ImageRegionIterator<TDisparityImage> outHDispIt(outHDispPtr,outputRegionForThread);
+  itk::ImageRegionIterator<TDisparityImage> outVDispIt(outVDispPtr,outputRegionForThread);
+  itk::ImageRegionIterator<TOutputMetricImage>    outMetricIt(outMetricPtr,outputRegionForThread);
+  itk::ImageRegionConstIterator<TDisparityImage>  inHDispIt;
+  itk::ImageRegionConstIterator<TDisparityImage>  inVDispIt;
+  itk::ImageRegionConstIterator<TMaskImage>       inLeftMaskIt;
+  itk::ImageRegionConstIterator<TMaskImage>       inRightMaskIt;
+  
+  bool useHorizontalDisparity = false;
+  bool useVerticalDisparity = false;
+  
+  if (inHDispPtr)
+    {
+    useHorizontalDisparity = true;
+    inHDispIt = itk::ImageRegionConstIterator<TDisparityImage>(inHDispPtr,outputRegionForThread);
+    inHDispIt.GoToBegin();
+    }
+  if (inVDispPtr)
+    {
+    useVerticalDisparity = true;
+    inVDispIt = itk::ImageRegionConstIterator<TDisparityImage>(inVDispPtr,outputRegionForThread);
+    inVDispIt.GoToBegin();
+    }
+  
+  if(inLeftMaskPtr)
+    {
+    inLeftMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inLeftMaskPtr,outputRegionForThread);
+    inLeftMaskIt.GoToBegin();
+    }
+  RegionType rightBufferedRegion = inRightPtr->GetBufferedRegion();
+  if(inRightMaskPtr)
+    {
+    inRightMaskIt = itk::ImageRegionConstIterator<TMaskImage>(inRightMaskPtr,rightBufferedRegion);
+    inRightMaskIt.GoToBegin();
+    }
+  
+  itk::ConstantBoundaryCondition<TInputImage> nbc1;
+  leftIt.OverrideBoundaryCondition(&nbc1);
+  
+  leftIt.GoToBegin();
+  outHDispIt.GoToBegin();
+  outVDispIt.GoToBegin();
+  outMetricIt.GoToBegin();
+  
+  /* Specific variables */
+  IndexType curLeftPos;
+  IndexType curRightPos;
+  
+  float hDisp_f;
+  float vDisp_f;
+  int hDisp_i;
+  int vDisp_i;
+  
+  // compute metric around current right position
+  bool horizontalInterpolation = false;
+  bool verticalInterpolation = false;
+  
+  // metrics for neighbors positions : first index is x, second is y
+  double neighborsMetric[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+  unsigned int nbIterMax = 8;
+  
+  // resampler
+  typename ResamplerFilterType::Pointer resampler = ResamplerFilterType::New();
+  resampler->SetInput(inRightPtr);
+  // set the output size and start index to the center position
+  // then set the smaller shift in the transform
+  IndexType upleftCorner;
+  SizeType windowSize;
+  windowSize[0] = 2 * m_Radius[0] + 1;
+  windowSize[1] = 2 * m_Radius[1] + 1;
+  resampler->SetSize(windowSize);
+  
+  TransformationType::Pointer transfo = TransformationType::New();
+  TransformationType::ParametersType offsetTransfo;
+  offsetTransfo[0] = 0.0;
+  offsetTransfo[1] = 0.0;
+  resampler->SetTransform(transfo);
+  
+  RegionType tinyShiftedRegion;
+  tinyShiftedRegion.SetIndex(0, m_Radius[0]);
+  tinyShiftedRegion.SetIndex(1, m_Radius[1]);
+  tinyShiftedRegion.SetSize(0, 1);
+  tinyShiftedRegion.SetSize(1, 1);
+  
+  // iterators on right image
+  itk::ConstNeighborhoodIterator<TInputImage>     rightIt;
+  itk::ConstNeighborhoodIterator<TInputImage>     shiftedIt;
+  bool centreHasMoved;
+  
+  while (!leftIt.IsAtEnd()
+        || !outHDispIt.IsAtEnd()
+        || !outVDispIt.IsAtEnd()
+        || !outMetricIt.IsAtEnd())
+    {
+    horizontalInterpolation = false;
+    verticalInterpolation = false;
+    
+    /* compute estimated right position */
+    curLeftPos = leftIt.GetIndex();
+    
+    if (useHorizontalDisparity)
+      {
+      hDisp_f = static_cast<float>(outHDispIt.Get());
+      hDisp_i = static_cast<int>(vcl_floor(hDisp_f + 0.5));
+      curRightPos[0] = curLeftPos[0] + hDisp_i;
+      }
+    else
+      {
+      hDisp_i = 0;
+      curRightPos[0] = curLeftPos[0];
+      }
+    
+    
+    if (useVerticalDisparity)
+      {
+      vDisp_f = static_cast<float>(outVDispIt.Get());
+      vDisp_i = static_cast<int>(vcl_floor(vDisp_f + 0.5));
+      curRightPos[1] = curLeftPos[1] + vDisp_i;
+      }
+    else
+      {
+      vDisp_i = 0;
+      curRightPos[1] = curLeftPos[1];
+      }
+    
+    // update resampler input position
+    upleftCorner[0] = curRightPos[0] - m_Radius[0];
+    upleftCorner[1] = curRightPos[1] - m_Radius[1];
+    resampler->SetOutputStartIndex(upleftCorner);
+    
+    // check if the current right position is inside the right image
+    if (rightBufferedRegion.IsInside(curRightPos))
+      {
+      if (inRightMaskPtr)
+        {
+        // Set right mask iterator position
+        inRightMaskIt.SetIndex(curRightPos);
+        }
+      // check that the current positions are not masked
+      if(!inLeftMaskPtr || (inLeftMaskPtr && inLeftMaskIt.Get() > 0) )
+        {
+        if(!inRightMaskPtr || (inRightMaskPtr && inRightMaskIt.Get() > 0) )
           {
-          if (neighborsMetric[1][1] > neighborsMetric[2][0] ||
-              neighborsMetric[1][1] > neighborsMetric[2][2] ||
-              neighborsMetric[1][1] > neighborsMetric[0][2] ||
-              neighborsMetric[1][1] > neighborsMetric[0][0])
+          RegionType smallRightRegion;
+          smallRightRegion.SetIndex(0,curRightPos[0]-1);
+          smallRightRegion.SetIndex(1,curRightPos[1]-1);
+          smallRightRegion.SetSize(0,3);
+          smallRightRegion.SetSize(1,3);
+          
+          rightIt.Initialize(m_Radius,inRightPtr,smallRightRegion);
+          
+          // compute metric at centre position
+          rightIt.SetLocation(curRightPos);
+          neighborsMetric[1][1] = m_Functor(leftIt,rightIt);
+          
+          if (m_MinimumVerticalDisparity < vDisp_i && vDisp_i < m_MaximumVerticalDisparity)
             {
-            verticalInterpolation = false;
-            horizontalInterpolation = false;
+            IndexType upIndex(curRightPos);
+            upIndex[1]+= (-1);
+            IndexType downIndex(curRightPos);
+            downIndex[1]+= 1;
+            if ( rightBufferedRegion.IsInside(upIndex) && rightBufferedRegion.IsInside(downIndex) )
+              {
+              rightIt.SetLocation(upIndex);
+              neighborsMetric[1][0] = m_Functor(leftIt,rightIt);
+              
+              rightIt.SetLocation(downIndex);
+              neighborsMetric[1][2] = m_Functor(leftIt,rightIt);
+              
+          // check that current position is an extrema
+              if (m_Minimize)
+                {
+                if (neighborsMetric[1][1] < neighborsMetric[1][0] && neighborsMetric[1][1] < neighborsMetric[1][2])
+                  {
+                  verticalInterpolation = true;
+                  }
+                }
+              else
+                {
+                if (neighborsMetric[1][1] > neighborsMetric[1][0] && neighborsMetric[1][1] > neighborsMetric[1][2])
+                  {
+                  verticalInterpolation = true;
+                  }
+                }
+              }
             }
-          }
-        else
+          
+          if (m_MinimumHorizontalDisparity < hDisp_i && hDisp_i < m_MaximumHorizontalDisparity)
+            {
+            IndexType leftIndex(curRightPos);
+            leftIndex[0]+= (-1);
+            IndexType rightIndex(curRightPos);
+            rightIndex[0]+= 1;
+            if ( rightBufferedRegion.IsInside(leftIndex) && rightBufferedRegion.IsInside(rightIndex) )
           {
-          if (neighborsMetric[1][1] < neighborsMetric[2][0] ||
-              neighborsMetric[1][1] < neighborsMetric[2][2] ||
-              neighborsMetric[1][1] < neighborsMetric[0][2] ||
-              neighborsMetric[1][1] < neighborsMetric[0][0])
+              rightIt.SetLocation(rightIndex);
+              neighborsMetric[2][1] = m_Functor(leftIt,rightIt);
+              
+              rightIt.SetLocation(leftIndex);
+              neighborsMetric[0][1] = m_Functor(leftIt,rightIt);
+              
+          // check that current position is an extrema
+              if (m_Minimize)
+                {
+                if (neighborsMetric[1][1] < neighborsMetric[0][1] && neighborsMetric[1][1] < neighborsMetric[2][1])
+                  {
+                  horizontalInterpolation = true;
+                  }
+                }
+              else
+                {
+                if (neighborsMetric[1][1] > neighborsMetric[0][1] && neighborsMetric[1][1] > neighborsMetric[2][1])
+                  {
+                  horizontalInterpolation = true;
+                  }
+                }
+              }
+            }
+          
+          // if both vertical and horizontal interpolation, compute metrics on corners
+          if (verticalInterpolation && horizontalInterpolation)
             {
-            verticalInterpolation = false;
-            horizontalInterpolation = false;
+            IndexType uprightIndex(curRightPos);
+            uprightIndex[0]+= 1;
+            uprightIndex[1]+= (-1);
+            rightIt.SetLocation(uprightIndex);
+            neighborsMetric[2][0] = m_Functor(leftIt,rightIt);
+            
+            IndexType downrightIndex(curRightPos);
+            downrightIndex[0]+= 1;
+            downrightIndex[1]+= 1;
+            rightIt.SetLocation(downrightIndex);
+            neighborsMetric[2][2] = m_Functor(leftIt,rightIt);
+            
+            IndexType downleftIndex(curRightPos);
+            downleftIndex[0]+= (-1);
+            downleftIndex[1]+= 1;
+            rightIt.SetLocation(downleftIndex);
+            neighborsMetric[0][2] = m_Functor(leftIt,rightIt);
+            
+            IndexType upleftIndex(curRightPos);
+            upleftIndex[0]+= (-1);
+            upleftIndex[1]+= (-1);
+            rightIt.SetLocation(upleftIndex);
+            neighborsMetric[0][0] = m_Functor(leftIt,rightIt);
+            
+            //check that it is an extrema
+            if (m_Minimize)
+              {
+              if (neighborsMetric[1][1] > neighborsMetric[2][0] ||
+                  neighborsMetric[1][1] > neighborsMetric[2][2] ||
+                  neighborsMetric[1][1] > neighborsMetric[0][2] ||
+                  neighborsMetric[1][1] > neighborsMetric[0][0])
+                {
+                verticalInterpolation = false;
+                horizontalInterpolation = false;
+                }
+              }
+            else
+              {
+              if (neighborsMetric[1][1] < neighborsMetric[2][0] ||
+                  neighborsMetric[1][1] < neighborsMetric[2][2] ||
+                  neighborsMetric[1][1] < neighborsMetric[0][2] ||
+                  neighborsMetric[1][1] < neighborsMetric[0][0])
+                {
+                verticalInterpolation = false;
+                horizontalInterpolation = false;
+                }
+              }
             }
           }
         }
@@ -1101,7 +1592,6 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
     // Interpolate position : dichotomy
     if (verticalInterpolation && !horizontalInterpolation)
       {
-      unsigned int nbIterMax = 8;
       double ya = static_cast<double>(vDisp_i -1);
       double yb = static_cast<double>(vDisp_i);
       double yc = static_cast<double>(vDisp_i +1);
@@ -1112,41 +1602,17 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       double yd;
       double s_yd;
       
-      typedef itk::ResampleImageFilter<TInputImage,TInputImage,double> ResamplerType;
-      ResamplerType::Pointer resampler = ResamplerType::New();
-      resampler->SetInput(inRightPtr);
-      // set the output size and start index to the center position
-      // then set the smaller shift in the transform
-      IndexType upleftCorner(curRightPos);
-      upleftCorner[0] += (-curRadius[0]);
-      upleftCorner[1] += (-curRadius[1]);
-      SizeType windowSize;
-      windowSize[0] = 2 * curRadius[0] + 1;
-      windowSize[1] = 2 * curRadius[1] + 1;
-      resampler->SetOutputStartIndex(upleftCorner);
-      resampler->SetSize(windowSize);
-      typedef itk::TranslationTransform<double,2> TransformationType;
-      TransformationType::Pointer transfo = TransformationType::New();
-      double offsetTransfo[2];
       offsetTransfo[0] = 0.0;
-      offsetTransfo[1] = 0.0;
-      resampler->SetTransform(transfo);
-      
-      RegionType tinyShiftedRegion;
-      tinyShiftedRegion.SetIndex(0, curRadius[0]);
-      tinyShiftedRegion.SetIndex(1, curRadius[1]);
-      tinyShiftedRegion.SetSize(0, 1);
-      tinyShiftedRegion.SetSize(1, 1);
       
       for (unsigned int k=0; k<nbIterMax; k++)
         {
         if ( (yb-ya) < (yc-yb) )
           {
           yd = 0.5 * (yc+yb);
-          offsetTransfo[1] = yd - yb;
+          offsetTransfo[1] = yd - static_cast<double>(vDisp_i);
           transfo->SetParameters(offsetTransfo);
           resampler->Update();
-          itk::ConstNeighborhoodIterator<TInputImage>     shiftedIt(curRadius,resampler->GetOutput(),tinyShiftedRegion);
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
           s_yd = m_Functor(leftIt,shiftedIt);
           
           if (s_yd<s_yb)
@@ -1166,10 +1632,10 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
         else
           {
           yd = 0.5 * (ya+yb);
-          offsetTransfo[1] = yd - yb;
+          offsetTransfo[1] = yd - static_cast<double>(vDisp_i);
           transfo->SetParameters(offsetTransfo);
           resampler->Update();
-          itk::ConstNeighborhoodIterator<TInputImage>     shiftedIt(curRadius,resampler->GetOutput(),tinyShiftedRegion);
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
           s_yd = m_Functor(leftIt,shiftedIt);
           
           if (s_yd<s_yb)
@@ -1189,11 +1655,11 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
         }
       
       outVDispIt.Set( yb );
+      outMetricIt.Set( s_yb );
       
       }
     else if (!verticalInterpolation && horizontalInterpolation)
       {
-      unsigned int nbIterMax = 8;
       double xa = static_cast<double>(hDisp_i -1);
       double xb = static_cast<double>(hDisp_i);
       double xc = static_cast<double>(hDisp_i +1);
@@ -1204,63 +1670,247 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       double xd;
       double s_xd;
       
-      typedef itk::ResampleImageFilter<TInputImage,TInputImage,double> ResamplerType;
-      ResamplerType::Pointer resampler = ResamplerType::New();
-      resampler->SetInput(inRightPtr);
-      // set the output size and start index to the center position
-      // then set the smaller shift in the transform
+      offsetTransfo[1] = 0.0;
+      
+      for (unsigned int k=0 ; k<nbIterMax ; k++)
+        {
+        if ( (xb-xa) < (xc-xb) )
+          {
+          xd = 0.5 * (xc+xb);
+          offsetTransfo[0] = xd - static_cast<double>(hDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_xd = m_Functor(leftIt,shiftedIt);
+          
+          if (s_xd<s_xb)
+            {
+            xa = xb;
+            s_xa = s_xb;
+            
+            xb = xd;
+            s_xb = s_xd;
+            }
+          else
+            {
+            xc = xd;
+            s_xc = s_xd;
+            }
+          }
+        else
+          {
+          xd = 0.5 * (xa+xb);
+          offsetTransfo[0] = xd - static_cast<double>(hDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_xd = m_Functor(leftIt,shiftedIt);
+          
+          if (s_xd<s_xb)
+            {
+            xc = xb;
+            s_xc = s_xb;
+            
+            xb = xd;
+            s_xb = s_xd;
+            }
+          else
+            {
+            xa = xd;
+            s_xa = s_xd;
+            }
+          }
+        }
+      
+      outHDispIt.Set( xb );
+      outMetricIt.Set( s_xb );
+      
+      }
+    else
+      {
+      double xa = static_cast<double>(hDisp_i);
+      double ya = static_cast<double>(vDisp_i - 1);
+      double xb = static_cast<double>(hDisp_i);
+      double yb = static_cast<double>(vDisp_i);
+      double xc = static_cast<double>(hDisp_i);
+      double yc = static_cast<double>(vDisp_i + 1);
+      double xe = static_cast<double>(hDisp_i - 1);
+      double ye = static_cast<double>(vDisp_i);
+      double xf = static_cast<double>(hDisp_i + 1);
+      double yf = static_cast<double>(vDisp_i);
+      
+      double s_a = neighborsMetric[1][0];
+      double s_b = neighborsMetric[1][1];
+      double s_c = neighborsMetric[1][2];
+      double s_e = neighborsMetric[0][1];
+      double s_f = neighborsMetric[2][1];
+      
+      
+      double xd;
+      double yd;
+      double s_d;
+      
+      offsetTransfo[0] = 0.0;
       
       for (unsigned int k=0; k<nbIterMax; k++)
         {
+        centreHasMoved = false;
+        // Vertical step
         if ( (yb-ya) < (yc-yb) )
           {
           yd = 0.5 * (yc+yb);
-          // s_yd = metric(yd);
-          if (s_yd<s_yb)
+          offsetTransfo[0] = xd - static_cast<double>(hDisp_i);
+          offsetTransfo[1] = yd - static_cast<double>(vDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_d = m_Functor(leftIt,shiftedIt);
+          
+          if (s_d<s_b)
             {
+            centreHasMoved = true;
+            
             ya = yb;
-            s_ya = s_yb;
+            s_a = s_b;
             
             yb = yd;
-            s_yb = s_yd;
+            s_b = s_d;
             }
           else
             {
             yc = yd;
-            s_yc = s_yd;
+            s_c = s_d;
             }
           }
         else
           {
           yd = 0.5 * (ya+yb);
-          // s_yd = metric(yd);
-          if (s_yd<s_yb)
+          offsetTransfo[0] = xd - static_cast<double>(hDisp_i);
+          offsetTransfo[1] = yd - static_cast<double>(vDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_d = m_Functor(leftIt,shiftedIt);
+          
+          if (s_d<s_b)
             {
+            centreHasMoved = true;
+            
             yc = yb;
-            s_yc = s_yb;
+            s_c = s_b;
             
             yb = yd;
-            s_yb = s_yd;
+            s_b = s_d;
             }
           else
             {
             ya = yd;
-            s_ya = s_yd;
+            s_a = s_d;
             }
           }
-        }
+        if (centreHasMoved)
+          {
+          // update points e and f
+          ye = yb;
+          yf = yb;
+          
+          offsetTransfo[1] = ye - static_cast<double>(vDisp_i);
+          
+          offsetTransfo[0] = xe - static_cast<double>(hDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_e = m_Functor(leftIt,shiftedIt);
+          
+          offsetTransfo[0] = xf - static_cast<double>(hDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_f = m_Functor(leftIt,shiftedIt);
+          }
         
-      outHDispIt.Set( xb );
+        centreHasMoved = false;
+        // Horizontal step
+        if ( (xb-xe) < (xf-xb) )
+          {
+          xd = 0.5 * (xf+xb);
+          offsetTransfo[0] = xd - static_cast<double>(hDisp_i);
+          offsetTransfo[1] = yd - static_cast<double>(vDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_d = m_Functor(leftIt,shiftedIt);
+          
+          if (s_d<s_b)
+            {
+            centreHasMoved = true;
+            
+            xe = xb;
+            s_e = s_b;
+            
+            xb = xd;
+            s_b = s_d;
+            }
+          else
+            {
+            xf = xd;
+            s_f = s_d;
+            }
+          }
+        else
+          {
+          xd = 0.5 * (xe+xb);
+          offsetTransfo[0] = xd - static_cast<double>(hDisp_i);
+          offsetTransfo[1] = yd - static_cast<double>(vDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_d = m_Functor(leftIt,shiftedIt);
+          
+          if (s_d<s_b)
+            {
+            centreHasMoved = true;
+            
+            xf = xb;
+            s_f = s_b;
+            
+            xb = xd;
+            s_b = s_d;
+            }
+          else
+            {
+            xe = xd;
+            s_e = s_d;
+            }
+          }
+        if (centreHasMoved)
+          {
+          // update a and c
+          xa = xb;
+          xc = xb;
+          
+          offsetTransfo[0] = xa - static_cast<double>(hDisp_i);
+          
+          offsetTransfo[1] = ya - static_cast<double>(vDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_a = m_Functor(leftIt,shiftedIt);
+          
+          offsetTransfo[1] = yc - static_cast<double>(vDisp_i);
+          transfo->SetParameters(offsetTransfo);
+          resampler->Update();
+          shiftedIt.Initialize(m_Radius,resampler->GetOutput(),tinyShiftedRegion);
+          s_c = m_Functor(leftIt,shiftedIt);
+          }
+        
+        }
       
-      // TODO
-      }
-    else
-      {
-      // TODO
+      outHDispIt.Set( xb );
+      outVDispIt.Set( yb );
+      outMetricIt.Set( s_b );
       }
     
-    
-    
     if (!verticalInterpolation)
       {
       // No vertical interpolation done : simply copy the integer vertical disparity
@@ -1273,6 +1923,10 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       outHDispIt.Set( static_cast<double>(hDisp_i));
       }
     
+    if (!verticalInterpolation && !horizontalInterpolation)
+      {
+      outMetricIt.Set(static_cast<double>(neighborsMetric[1][1]));
+      }
     
     progress.CompletedPixel();
     
@@ -1289,16 +1943,10 @@ TDisparityImage,TMaskImage,TBlockMatchingFunctor>
       {
       ++inVDispIt;
       }
-      
     if(inLeftMaskPtr)
       {
       ++inLeftMaskIt;
       }
-    
-    if(inRightMaskPtr)
-      {
-      ++inRightMaskIt;
-      }
     }
 }