diff --git a/Code/FeatureExtraction/otbLineRatioDetectorImageFilter.h b/Code/FeatureExtraction/otbLineRatioDetectorImageFilter.h
new file mode 100755
index 0000000000000000000000000000000000000000..c4e4194401b9f1cdb72dce4f15ffbd4c7f43e4e8
--- /dev/null
+++ b/Code/FeatureExtraction/otbLineRatioDetectorImageFilter.h
@@ -0,0 +1,180 @@
+/*=========================================================================
+
+  Programme :   OTB (ORFEO ToolBox)
+  Auteurs   :   CS - C.Ruffel
+  Language  :   C++
+  Date      :   14 mars 2006
+  Role      :   Filter of detection of linear features 
+  $Id$ 
+
+=========================================================================*/
+#ifndef __otbLineRatioDetectorImageFilter_h
+#define __otbLineRatioDetectorImageFilter_h
+
+#include "itkBSplineInterpolateImageFunction.h"
+#include "itkImageToImageFilter.h"
+#include "itkImage.h"
+#include "itkNumericTraits.h"
+
+#define MIN(_A,_B) ((_A) < (_B) ? (_A) : (_B))
+#define MAX(_A,_B) ((_A) > (_B) ? (_A) : (_B))  
+#define ROTATION(_x,_y,_theta,_xout,_yout) \
+    (_xout) = (_x)*cos(_theta) - (_y)*sin(_theta); \
+    (_yout) = (_x)*sin(_theta) + (_y)*cos(_theta)
+
+
+namespace otb
+{
+
+/** \class LineRatioDetectorImageFilter
+ * \brief Application of the filter of detection of linear features 
+ *
+ * This class implements the Tupin's detector D1 used to detect 
+ * two parallel lines. This detector is derived from the coupling of two
+ * ratio edge detectors (Touzi detector) on both side of a region.
+ *
+ * The region is devided in three zones to delimite two parallel lines. 
+ * The size of one zone is defined by the product of the width 
+ * of the linear feature by its length.
+ *
+ * For each vertical line, we calculate the intensity of detection 
+ * R_{12}(\theta_{0}) between zones 1 and 2 and R_{13}(\theta_{0}) between  
+ * zones 1 and 3 according to the principle of the Touzi's filter.
+ *
+ * The response of the edge detector between two zones i and j is:
+ *	\[R_{ij}=1-\min (\fract{\mu_{i}}{\mu_{j}};\fract{\mu_{j}}{\mu_{i}}) \]
+ *
+ * The intensity of detection in the three other directions R(\theta_{i})
+ * is determined by rotation of the pixels of each zone around the 
+ * central pixel of the region considered. By default, the pixel location after
+ * rotation is determined by the Spline interpolator.
+ * 
+ * Finally, the intensity of detection formed by the two parallel lines 
+ * is determined by the minimum response of a ration edge detector on both sides
+ * of the linear structure:
+ *	\[R = \min (R_{12};R_{13}) \]
+ * where R_{12} and R_{13} are the maximum response of the ratio edge 
+ * detector of R(\theta_{i}). The intensity of detection lies in
+ * the interval [0, 1].
+ * 
+ * The output is an image of intensity of detection. 
+ * 
+ */
+
+template <class TInputImage, 
+	  class TOutputImage,
+	  class InterpolatorType = itk::BSplineInterpolateImageFunction<TInputImage> >
+class ITK_EXPORT LineRatioDetectorImageFilter :  public itk::ImageToImageFilter< TInputImage, TOutputImage >
+{
+public:
+  /** 	Extract dimensions as well of the images of entry of exit. */
+  itkStaticConstMacro(		InputImageDimension,
+  				unsigned int,
+                      		TInputImage::ImageDimension);
+  itkStaticConstMacro(		OutputImageDimension, 
+  				unsigned int,
+                      		TOutputImage::ImageDimension);
+
+  typedef TInputImage InputImageType;
+  typedef TOutputImage OutputImageType;
+
+  /** typedef for the classes standards. */
+  typedef LineRatioDetectorImageFilter Self;
+  typedef itk::ImageToImageFilter< InputImageType, OutputImageType> Superclass;
+  typedef itk::SmartPointer<Self> Pointer;
+  typedef itk::SmartPointer<const Self>  ConstPointer;
+
+  /** Method for management of the "object factory". */
+  itkNewMacro(Self);
+
+  /** Return the name of the class. */
+  itkTypeMacro(LineRatioDetectorImageFilter, itk::ImageToImageFilter);
+
+  /** Typedefs to describe and access Interpolator */
+  typedef typename InterpolatorType::Pointer InterpolatorPointer;
+  typedef typename InterpolatorType::CoordRepType CoordRepType;
+  
+  typedef typename InputImageType::PointType TPoint;
+
+
+  /** Definition of the input and output images */
+  typedef typename InputImageType::PixelType InputPixelType;
+  typedef typename OutputImageType::PixelType OutputPixelType;
+
+  
+  typedef typename InputImageType::RegionType InputImageRegionType;
+  typedef typename OutputImageType::RegionType OutputImageRegionType;
+
+  /** Definition of the size of the images. */
+  typedef typename InputImageType::SizeType SizeType;
+  
+  /** Set the length of the linear feature. */
+  itkSetMacro(LengthLine, unsigned int);
+
+  /** Get the length of the linear feature. */
+  itkGetConstReferenceMacro(LengthLine, unsigned int);
+
+  /** Set the width of the linear feature. */
+  itkSetMacro(WidthLine, unsigned int);
+
+  /** Get the length of the linear feature. */
+  itkGetConstReferenceMacro(WidthLine, unsigned int);
+  
+  /** Set the radius of one zone. */
+  itkSetMacro(Radius, SizeType);
+
+  /** Get the radius of one zone. */
+  itkGetConstReferenceMacro(Radius, SizeType);
+ 
+
+  virtual void GenerateInputRequestedRegion() throw(itk::InvalidRequestedRegionError);
+  
+  const OutputImageType * GetOutputDirection();
+
+protected:
+  LineRatioDetectorImageFilter();
+  virtual ~LineRatioDetectorImageFilter() {};
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+  void BeforeThreadedGenerateData();
+
+  /** LineRatioDetectorImageFilter can be implemented for a treatment of filter multithreaded. 
+   * Thus, the ThreadedGenerateData() method is called for each thread process. 
+   * The data image are allocated automatically by the mother class by calling the 
+   * ThreadedGenerateData() method. ThreadedGenerateData can only write the portion 
+   * of the image specified by the parameter "outputRegionForThread" 
+   *
+   * \sa ImageToImageFilter::ThreadedGenerateData(),
+   *     ImageToImageFilter::GenerateData() */
+  void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                            int threadId );
+
+private:
+  LineRatioDetectorImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+ 
+  /** Length of the linear feature = 2*m_LengthLine+1 */ 
+  unsigned int m_LengthLine;
+ 
+  /** Width of the linear feature = 2*m_WidthLine+1 */ 
+  unsigned int m_WidthLine;
+     
+  /** Radius of the region*/
+  SizeType m_Radius;
+  
+  /** Size of the facelist*/
+  SizeType m_FaceList;
+  
+  InterpolatorPointer      m_Interpolator;
+
+  typename OutputImageType::Pointer m_DirectionOuputImage;
+
+};
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbLineRatioDetectorImageFilter.txx"
+#endif
+
+  
+#endif
diff --git a/Code/FeatureExtraction/otbLineRatioDetectorImageFilter.txx b/Code/FeatureExtraction/otbLineRatioDetectorImageFilter.txx
new file mode 100755
index 0000000000000000000000000000000000000000..c938aefeab825b98bd5ec1cfb4df4529cbd00bc9
--- /dev/null
+++ b/Code/FeatureExtraction/otbLineRatioDetectorImageFilter.txx
@@ -0,0 +1,380 @@
+/*=========================================================================
+
+  Programme :   OTB (ORFEO ToolBox)
+  Auteurs   :   CS - C.Ruffel
+  Language  :   C++
+  Date      :   14 mars 2006
+  Role      :   Filter of detection of linear features 
+  $Id$ 
+
+=========================================================================*/
+#ifndef __otbLineRatioDetectorImageFilter_txx
+#define __otbLineRatioDetectorImageFilter_txx
+
+#include "otbLineRatioDetectorImageFilter.h"
+
+#include "itkDataObject.h"
+#include "itkExceptionObject.h"
+#include "itkConstNeighborhoodIterator.h"
+#include "itkNeighborhoodInnerProduct.h"
+#include "itkImageRegionIterator.h"
+#include "itkNeighborhoodAlgorithm.h"
+#include "itkZeroFluxNeumannBoundaryCondition.h"
+#include "itkProgressReporter.h"
+#include <math.h>
+
+#define M_PI 3.14159265358979323846
+
+namespace otb
+{
+
+/**
+ *
+ */
+template <class TInputImage, class TOutputImage, class InterpolatorType >
+LineRatioDetectorImageFilter<TInputImage, TOutputImage, InterpolatorType>::LineRatioDetectorImageFilter()
+{
+  m_Radius.Fill(1);
+  m_LengthLine = 1;
+  m_WidthLine = 0;
+  m_FaceList.Fill(0);
+  m_Interpolator = InterpolatorType::New(); 
+}
+
+template <class TInputImage, class TOutputImage, class InterpolatorType>
+void LineRatioDetectorImageFilter<TInputImage, TOutputImage, InterpolatorType>::GenerateInputRequestedRegion() throw (itk::InvalidRequestedRegionError)
+{
+  // call the superclass' implementation of this method
+  Superclass::GenerateInputRequestedRegion();
+  
+  // get pointers to the input and output
+  typename Superclass::InputImagePointer inputPtr   =  const_cast< TInputImage * >( this->GetInput() );
+  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
+  
+  if ( !inputPtr || !outputPtr )
+    {
+    return;
+    }
+
+  // get a copy of the input requested region (should equal the output
+  // requested region)
+  typename TInputImage::RegionType inputRequestedRegion;
+  inputRequestedRegion = inputPtr->GetRequestedRegion();
+
+  // Define the size of the region by the radius
+  m_Radius[0] = static_cast<unsigned int>(3*m_WidthLine + 2); 
+  m_Radius[1] = m_LengthLine ;
+  
+  // Define the size of the facelist by taking into account the rotation of the region
+  m_FaceList[0] = static_cast<unsigned int>( sqrt( (m_Radius[0]*m_Radius[0]) + (m_Radius[1]*m_Radius[1]) ) + 1 );
+  m_FaceList[1] = m_FaceList[0];
+
+  // pad the input requested region by the operator radius
+  inputRequestedRegion.PadByRadius( m_Radius );
+
+  // crop the input requested region at the input's largest possible region
+  if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) )
+    {
+    inputPtr->SetRequestedRegion( inputRequestedRegion );
+    return;
+    }
+  else
+    {
+    // Couldn't crop the region (requested region is outside the largest
+    // possible region).  Throw an exception.
+
+    // store what we tried to request (prior to trying to crop)
+    inputPtr->SetRequestedRegion( inputRequestedRegion );
+    
+    // build an exception
+    itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
+    itk::OStringStream msg;
+    msg << static_cast<const char *>(this->GetNameOfClass())
+        << "::GenerateInputRequestedRegion()";
+    e.SetLocation(msg.str().c_str());
+    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
+    e.SetDataObject(inputPtr);
+    throw e;
+    }
+}
+
+/**
+ * Set up state of filter before multi-threading.
+ * InterpolatorType::SetInputImage is not thread-safe and hence
+ * has to be set up before ThreadedGenerateData
+ */
+template <class TInputImage, class TOutputImage, class InterpolatorType>
+void 
+LineRatioDetectorImageFilter< TInputImage, TOutputImage, InterpolatorType>
+::BeforeThreadedGenerateData()
+{
+
+  typename OutputImageType::RegionType  region;    
+  typename OutputImageType::Pointer     output = this->GetOutput();
+
+  m_DirectionOuputImage = OutputImageType::New();
+
+  region.SetSize(output->GetLargestPossibleRegion().GetSize());
+  region.SetIndex(output->GetLargestPossibleRegion().GetIndex());
+  m_DirectionOuputImage->SetRegions( region );
+  m_DirectionOuputImage->SetOrigin(output->GetOrigin());
+  m_DirectionOuputImage->SetSpacing(output->GetSpacing());
+  m_DirectionOuputImage->Allocate();
+
+}
+
+template <class TInputImage, class TOutputImage, class InterpolatorType>
+const typename LineRatioDetectorImageFilter< TInputImage, TOutputImage, InterpolatorType>::OutputImageType *
+LineRatioDetectorImageFilter< TInputImage, TOutputImage, InterpolatorType>
+::GetOutputDirection()
+{
+	this->Update();
+	return 	static_cast< const OutputImageType *> (m_DirectionOuputImage);
+}
+
+template< class TInputImage, class TOutputImage, class InterpolatorType>
+void LineRatioDetectorImageFilter< TInputImage, TOutputImage, InterpolatorType>
+::ThreadedGenerateData(	
+			const 	OutputImageRegionType& 		outputRegionForThread,
+                       	int 	threadId
+		       )
+{
+  unsigned int i;
+  itk::ZeroFluxNeumannBoundaryCondition<InputImageType> 	nbc;
+  itk::ConstNeighborhoodIterator<InputImageType> 		bit;
+  typename itk::ConstNeighborhoodIterator<InputImageType>::OffsetType	off;
+  itk::ImageRegionIterator<OutputImageType> 			it;
+  itk::ImageRegionIterator<OutputImageType> 			itdir;
+  
+  // Allocate output
+  typename InputImageType::ConstPointer input  = this->GetInput();
+  typename OutputImageType::Pointer     output = this->GetOutput();  
+  typename OutputImageType::Pointer     outputDir = m_DirectionOuputImage;
+  
+  m_Interpolator->SetInputImage(input);
+   
+  // Find the data-set boundary "faces"
+  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType 		faceList;
+  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType::iterator 	fit;
+
+
+  itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> bC;
+  faceList = bC(input, outputRegionForThread, m_FaceList);
+
+
+  // support progress methods/callbacks
+  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+  
+  typename TInputImage::IndexType     bitIndex;
+  typename InterpolatorType::ContinuousIndexType Index;
+
+
+  // --------------------------------------------------------------------------
+  
+  // Number of direction
+  const int NB_DIR = 4;
+  // Number of zone	  
+  const int NB_ZONE = 3;  
+  // Definition of the 4 directions
+  double Theta[NB_DIR];
+  
+  Theta[0] = 0.;
+  Theta[1] = M_PI / 4. ;
+  Theta[2] = M_PI / 2. ;
+  Theta[3] = 3*M_PI / 4. ;
+
+  // Number of the zone 
+  unsigned int zone;
+  
+  // Pixel number in each zone
+  const int NbPixelZone = (2*m_WidthLine+1)*(2*m_LengthLine+1);
+  
+  double InvNbPixelZone = static_cast<double>(1. / NbPixelZone); 
+   
+  // Contains for the 4 directions the sum of the pixels belonging to each zone
+  double Sum[NB_DIR][NB_ZONE];
+  // Mean of zone 1, 2 and 3
+  double M1, M2, M3;
+  
+  // Result of the filter for each direction
+  double R12_theta[NB_DIR];
+  double R13_theta[NB_DIR];
+  // Result for each direction
+  double R_theta[NB_DIR];
+  double Sum_R_theta = 0.;
+  // Intensity of the linear feature
+  double R;
+  
+  // Direction of detection
+  double Direction = 0.; 
+
+  // Pixel location in the input image
+  int X, Y;
+  
+  // Pixel location after rotation in the system axis of the region  
+  double xout, yout;
+  
+   // Pixel location in the input image after rotation
+  TPoint point;
+   
+  // location of the central pixel in the input image
+  int Xc, Yc;
+
+  // location of the central pixel between zone 1 and 2 and between zone 1 and 3
+  int Xc12, Xc13;
+  
+  //---------------------------------------------------------------------------
+ 
+  // Process each of the boundary faces.  These are N-d regions which border
+  // the edge of the buffer.
+  for (fit=faceList.begin(); fit != faceList.end(); ++fit)
+    { 
+    bit = itk::ConstNeighborhoodIterator<InputImageType>(m_Radius, input, *fit);
+    unsigned int neighborhoodSize = bit.Size();
+      
+    it = itk::ImageRegionIterator<OutputImageType>(output, *fit);
+    itdir = itk::ImageRegionIterator<OutputImageType>(outputDir, *fit);
+    
+    bit.OverrideBoundaryCondition(&nbc);
+    bit.GoToBegin();
+
+
+    while ( ! bit.IsAtEnd() )
+      {
+//std::cout << "Xc,Yc " << bit.GetIndex() << std::endl;
+
+      // Initializations
+      for (unsigned int dir=0; dir<NB_DIR; dir++)
+        {
+        for (unsigned int z=0; z<NB_ZONE; z++) 
+          Sum[dir][z] = 0.;
+        }
+        
+     
+      // Location of the central pixel of the region
+      bitIndex = bit.GetIndex();
+      
+      Xc = bitIndex[0];
+      Yc = bitIndex[1];
+      
+      // Location of the central pixel between zone 1 and zone 2
+      Xc12 = Xc - m_WidthLine - 1;
+      
+      // Location of the central pixel between zone 1 and zone 3
+      Xc13 = Xc + m_WidthLine + 1;
+          
+      // Loop on the region 
+      for (i = 0; i < neighborhoodSize; ++i)
+        {
+//std::cout << "---"<< i <<" "<< bit.GetIndex(i)<< std::endl;
+//std::cout << "val(X,Y) "<< static_cast<double>(bit.GetPixel(i)) << " " << std::endl;
+
+        bitIndex = bit.GetIndex(i);
+        X = bitIndex[0];
+        Y = bitIndex[1];
+
+      
+        // We determine in the vertical direction with which zone the pixel belongs. 
+         
+        if ( X < Xc12 )
+      	  zone = 1;
+        else if ( ( Xc12 < X ) && ( X < Xc13 ) )
+          zone = 0;
+        else if ( X < Xc13 )
+          zone = 2;
+        else
+          continue;
+    
+        Sum[0][zone] += static_cast<double>(bit.GetPixel(i));
+         
+        // Loop on the 3 other directions
+        for (unsigned int dir=1; dir<NB_DIR; dir++ )
+          {      
+            ROTATION( (X-Xc), (Y-Yc), Theta[dir], xout, yout);
+            
+            Index[0] = static_cast<CoordRepType>(xout + Xc);
+            Index[1] = static_cast<CoordRepType>(yout + Yc);
+                        
+//std::cout << "X' Y' "<< (xout + Xc) << " " << (yout + Yc) << std::endl;
+//std::cout << "val(X',Y') "<< static_cast<double>(m_Interpolator->EvaluateAtContinuousIndex( Index )) << std::endl;
+           
+            Sum[dir][zone] += static_cast<double>(m_Interpolator->EvaluateAtContinuousIndex( Index ));
+          
+          }      
+
+        } // end of the loop on the pixels of the region 
+          
+      R = -1.;
+      Direction = 0.;
+      Sum_R_theta = 0.;
+           
+      // Loop on the 4 directions
+      for (unsigned int dir=0; dir<NB_DIR; dir++ )
+        {
+        		
+        // Calculation of the mean for the 3 zones	
+        M1 = Sum[dir][0] * InvNbPixelZone;
+        M2 = Sum[dir][1] * InvNbPixelZone;
+        M3 = Sum[dir][2] * InvNbPixelZone;
+     	
+        // Calculation of the intensity of detection
+        if (( M1 != 0. ) && (M2 != 0. )) 
+          R12_theta[dir] = static_cast<double>( 1 - MIN( (M1/M2), (M2/M1) ) );
+        else
+	  R12_theta[dir] = 0.;
+	  
+	if (( M1 != 0. ) && (M3 != 0. )) 
+          R13_theta[dir] = static_cast<double>( 1 - MIN( (M1/M3), (M3/M1) ) );
+        else
+	  R13_theta[dir] = 0.;
+	  
+	// Determination of the minimum intensity of detection between R12 et R13
+	R_theta[dir] = static_cast<double>( MIN( R12_theta[dir], R13_theta[dir] ) );
+	
+	R = static_cast<double>( MAX ( R, R_theta[dir] ) );
+                
+        // Calculation of the directions
+        Direction += Theta[dir] * R_theta[dir];        
+        Sum_R_theta += R_theta[dir];
+	  
+      		
+        } // end of the loop on the directions
+      
+      // Determination of the direction of the contour
+      if ( Sum_R_theta != 0. )	
+        Direction = Direction / Sum_R_theta;
+
+      // Assignment of this value to the output pixel
+      it.Set( static_cast<OutputPixelType>(R) );
+      
+      // Assignment of this value to the "outputdir" pixel
+      itdir.Set( static_cast<OutputPixelType>(Direction) );  
+
+      ++bit;
+      ++it;
+      ++itdir;
+      progress.CompletedPixel();  
+      
+      }
+      
+    }
+}
+
+/**
+ * Standard "PrintSelf" method
+ */
+template <class TInputImage, class TOutput, class InterpolatorType>
+void 
+LineRatioDetectorImageFilter<TInputImage, TOutput, InterpolatorType>::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf( os, indent );
+  os << indent << "Length: " << m_LengthLine << std::endl;
+  os << indent << "Width: " << m_WidthLine << std::endl;
+  
+}
+
+
+} // end namespace otb
+
+
+#endif