From 0acad079dbbe1316e9d38faef0f89a584299bec2 Mon Sep 17 00:00:00 2001
From: Otmane Lahlou <otmane.lahlou@c-s.fr>
Date: Tue, 13 Jan 2009 19:15:27 +0100
Subject: [PATCH] ADD : Matching Filter and tests

---
 .../otbKeyPointSetsMatchingFilter.h           | 135 ++++++++++
 .../otbKeyPointSetsMatchingFilter.txx         | 233 ++++++++++++++++++
 Code/FeatureExtraction/otbLandmark.h          |  94 +++++++
 Testing/Code/FeatureExtraction/CMakeLists.txt |  22 +-
 .../otbFeatureExtractionTests9.cxx            |   3 +
 .../otbKeyPointSetsMatchingFilter.cxx         | 107 ++++++++
 .../otbKeyPointSetsMatchingFilterNew.cxx      |  35 +++
 .../Code/FeatureExtraction/otbLandmarkNew.cxx |  37 +++
 8 files changed, 665 insertions(+), 1 deletion(-)
 create mode 100755 Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.h
 create mode 100755 Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.txx
 create mode 100755 Code/FeatureExtraction/otbLandmark.h
 create mode 100755 Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.cxx
 create mode 100644 Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilterNew.cxx
 create mode 100755 Testing/Code/FeatureExtraction/otbLandmarkNew.cxx

diff --git a/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.h b/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.h
new file mode 100755
index 0000000000..449d8a4c72
--- /dev/null
+++ b/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.h
@@ -0,0 +1,135 @@
+/*=========================================================================
+
+Program:   ORFEO Toolbox
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+
+Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+See OTBCopyright.txt for details.
+
+
+This software is distributed WITHOUT ANY WARRANTY; without even 
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __otbKeyPointSetsMatchingFilter_h
+#define __otbKeyPointSetsMatchingFilter_h
+
+#include "otbObjectList.h"
+#include "otbObjectListSource.h"
+#include "otbLandmark.h"
+#include "itkEuclideanDistance.h"
+
+namespace otb
+{
+  /** \class KeyPointSetsMatchingFilter
+   *  \brief This class matches two point sets according to their associated data.
+   *
+   *   The matching criteria is that the ratio between the distance to the first nearest neighbor and the 
+   *   second nearest neighbor is lower than the distance threshold. The distance used can be set via the TDistance
+   *   template parameters. It has to implement the Evaluate() method (see \doxygen{EuclideanDistance} for more details).
+   *
+   *   By default, the algorithm tries to match points from pointset 1 to points from pointset 2. If back matching is activated,
+   *   it will aslo try to match points from pointset 2 to points from pointset 2, and discard matches that do not appear both in
+   *   forward and backward matching. 
+   *
+   *   Matches are stored in a landmark object containing both matched points and point data. The landmark data will hold the distance value
+   *   between the data.
+   *
+   *   \sa Landmark
+   *   \sa PointSet
+   *   \sa EuclideanDistance
+   */
+template < class TPointSet, class TDistance = itk::Statistics::EuclideanDistance< typename TPointSet::PixelType > >
+class ITK_EXPORT KeyPointSetsMatchingFilter
+: public ObjectListSource<  ObjectList< Landmark< typename TPointSet::PointType, typename TPointSet::PixelType,double> > >
+  {
+    public:
+    /// standard class typedefs
+    typedef KeyPointSetsMatchingFilter             Self;
+    typedef ObjectListSource<  ObjectList< 
+    Landmark< typename TPointSet::PointType, 
+    typename TPointSet::PixelType,double> > >      Superclass;
+    typedef itk::SmartPointer<Self>                Pointer;
+    typedef itk::SmartPointer<const Self>          ConstPointer;
+
+    /// template typedefs
+    typedef TPointSet                                      PointSetType;
+    typedef typename PointSetType::Pointer                 PointSetPointerType;
+    typedef typename PointSetType::PointType               PointType;
+    typedef typename PointSetType::PixelType               PointDataType;
+    typedef typename PointSetType::PointsContainer         PointsContainerType;
+    typedef typename PointsContainerType::ConstIterator    PointsIteratorType;
+    typedef typename PointSetType::PointDataContainer      PointDataContainerType;
+    typedef typename PointDataContainerType::ConstIterator PointDataIteratorType;
+    typedef TDistance                                      DistanceType;
+    typedef typename DistanceType::Pointer                 DistancePointerType;
+    typedef Landmark< typename TPointSet::PointType, 
+    typename TPointSet::PixelType,double>                  LandmarkType;
+    typedef typename LandmarkType::Pointer                 LandmarkPointerType;
+    typedef ObjectList<LandmarkType>                       LandmarkListType;
+    typedef typename LandmarkListType::Pointer             LandmarkListPointerType;
+    typedef std::pair<unsigned int,double>                 NeighborSearchResultType;
+
+    /// standard macros
+    itkNewMacro(Self);
+    itkTypeMacro(KeyPointSetsMatchingFilter,ObjectListSource);
+
+    /// Accessors
+    itkBooleanMacro(UseBackMatching);
+    itkSetMacro(UseBackMatching,bool);
+    itkGetMacro(UseBackMatching,bool);
+    itkSetMacro(DistanceThreshold,double);
+    itkGetMacro(DistanceThreshold,double);
+    
+    /// Set the first pointset
+    void SetInput1(const PointSetType * pointset);    
+    /// Get the first pointset
+    const PointSetType * GetInput1();
+    /// Set the second pointset
+    void SetInput2(const PointSetType * pointset);    
+    /// Get the second pointset
+    const PointSetType * GetInput2();
+
+    protected:
+    /// Constructor
+    KeyPointSetsMatchingFilter();
+    /// Destructor
+    ~KeyPointSetsMatchingFilter(){};
+    /// PrintSelf method
+    virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+    /// Generate Data
+    virtual void GenerateData();
+
+    /**
+     * Find the nearest neighbor of data1 in pointset.
+     * \return a pair of (index,distance).
+     */
+    NeighborSearchResultType NearestNeighbor(const PointDataType& data1, const PointSetType * pointset);
+
+
+    private:
+    KeyPointSetsMatchingFilter(const Self&); // purposely not implemented
+    void operator=(const Self&);             // purposely not implemented
+
+    // Find back matches from 2 to 1 to validate them
+    bool m_UseBackMatching;
+
+    // Distance threshold to decide matching
+    double m_DistanceThreshold;
+
+    // Distance calculator
+    DistancePointerType m_DistanceCalculator;
+  };
+
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbKeyPointSetsMatchingFilter.txx"
+#endif
+#endif 
+
diff --git a/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.txx b/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.txx
new file mode 100755
index 0000000000..eaca7c29db
--- /dev/null
+++ b/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.txx
@@ -0,0 +1,233 @@
+/*=========================================================================
+
+Program:   ORFEO Toolbox
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+
+Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+See OTBCopyright.txt for details.
+
+
+This software is distributed WITHOUT ANY WARRANTY; without even 
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __otbKeyPointSetsMatchingFilter_txx
+#define __otbKeyPointSetsMatchingFilter_txx
+
+#include "otbKeyPointSetsMatchingFilter.h"
+
+namespace otb
+{
+
+template <class TPointSet, class TDistance>
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::KeyPointSetsMatchingFilter()
+{
+  this->SetNumberOfRequiredInputs(2);
+  m_UseBackMatching   = false;
+  m_DistanceThreshold = 0.6;
+  // Object used to measure distance
+  m_DistanceCalculator = DistanceType::New();
+}
+
+template <class TPointSet, class TDistance>
+const typename KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::PointSetType *
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::GetInput1()
+{
+  return static_cast<const PointSetType *>(this->itk::ProcessObject::GetInput(0));
+}
+
+template <class TPointSet, class TDistance>
+void
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::SetInput1(const PointSetType * pointset)
+{
+  this->itk::ProcessObject::SetNthInput(0,const_cast<PointSetType *>(pointset));
+}
+
+template <class TPointSet, class TDistance>
+const typename KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::PointSetType *
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::GetInput2()
+{
+  return static_cast<const PointSetType *>(this->itk::ProcessObject::GetInput(1));
+}
+
+template <class TPointSet, class TDistance>
+void
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::SetInput2(const PointSetType * pointset)
+{
+  this->itk::ProcessObject::SetNthInput(1,const_cast<PointSetType *>(pointset));
+}
+
+template <class TPointSet, class TDistance>
+void
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::GenerateData()
+{
+//   std::cout<<"GenerateData()"<<std::endl;
+
+  // Get the input pointers
+  const PointSetType * ps1 =  this->GetInput1();
+  const PointSetType * ps2 =  this->GetInput2();
+
+  // Check if one of the pointsets is empty
+  if( ps1->GetNumberOfPoints() == 0 || ps2->GetNumberOfPoints() == 0 )
+    {
+      itkExceptionMacro(<<"Empty input pointset !");
+    }
+
+  // Get the output pointer
+  LandmarkListPointerType landmarks = this->GetOutput();
+
+  // Define iterators on points and point data.
+  PointsIteratorType     pIt  = ps1->GetPoints()->Begin();
+  PointDataIteratorType pdIt = ps1->GetPointData()->Begin();
+  
+  // iterate on pointset 1
+  while(pdIt!=ps1->GetPointData()->End()
+	&&pIt!=ps1->GetPoints()->End())
+    {
+      // Get point and point data at current location
+      bool matchFound = false;
+      unsigned int currentIndex = pIt.Index();
+      PointDataType data = pdIt.Value();
+      PointType     point = pIt.Value();
+
+      // These variables will hold the matched point and point data
+      PointDataType dataMatch;
+      PointType pointMatch;
+
+      // call to the matching routine
+      NeighborSearchResultType searchResult1 = NearestNeighbor(data,ps2);
+
+     // Check if the neighbor distance is lower than the threshold
+     if(searchResult1.second < m_DistanceThreshold)
+       {
+	 // Get the matched point and point data
+	 dataMatch = ps2->GetPointData()->GetElement(searchResult1.first);
+	 pointMatch = ps2->GetPoints()->GetElement(searchResult1.first);
+
+	 // If the back matching option is on
+	 if(m_UseBackMatching)
+	   {
+	     // Peform the back search
+	     NeighborSearchResultType searchResult2 = NearestNeighbor(dataMatch,ps1);
+	     
+	     // Test if back search finds the same match
+	     if(currentIndex == searchResult2.first)
+	       {
+		 matchFound = true;
+	       }	     
+	   } 
+	 else // else back matching
+	   {
+	     matchFound = true;
+	   }
+       }
+     
+     // If we found a match, add the proper landmark
+     if(matchFound)
+       {
+	 LandmarkPointerType landmark = LandmarkType::New();
+	 landmark->SetPoint1(point);
+	 landmark->SetPointData1(data);
+	 landmark->SetPoint2(pointMatch);
+	 landmark->SetPointData2(dataMatch);
+	 landmark->SetLandmarkData(searchResult1.second);
+	 
+	 // Add the new landmark to the landmark list
+	 landmarks->PushBack(landmark);
+       }
+     ++pdIt;
+     ++pIt;
+    }
+}
+
+template <class TPointSet, class TDistance>
+typename KeyPointSetsMatchingFilter<TPointSet,TDistance>::NeighborSearchResultType 
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::NearestNeighbor(const PointDataType& data1, const PointSetType * pointset)
+{
+//   std::cout<<"Call to NearestNeighbor()"<<std::endl;
+  // Declare the result
+  NeighborSearchResultType result;
+
+  // Define iterators on points and point data.
+  PointDataIteratorType pdIt = pointset->GetPointData()->Begin();
+
+  // local variables
+  unsigned int nearestIndex = 0;
+  double d1 = m_DistanceCalculator->Evaluate(data1,pdIt.Value());
+  ++pdIt;
+  double d2 = m_DistanceCalculator->Evaluate(data1,pdIt.Value());
+  ++pdIt;
+
+  if(d1>d2)
+    {
+      nearestIndex = 1;
+    }
+  // Initialize distances
+  double nearestDistance = std::min(d1,d2);
+  double secondNearestDistance = std::max(d1,d2);
+  double distanceValue;
+
+  // iterate on the pointset
+  while( pdIt != pointset->GetPointData()->End() )
+    {
+      // Evaluate the distance
+      distanceValue = m_DistanceCalculator->Evaluate(data1,pdIt.Value());
+
+//       std::cout<<nearestIndex<<" "<<nearestDistance<<" "<<secondNearestDistance<<std::endl;
+
+      // Check if this point is the nearest neighbor
+      if(distanceValue < nearestDistance)
+	{
+	  secondNearestDistance = nearestDistance;
+	  nearestDistance = distanceValue;
+	  nearestIndex = pdIt.Index();
+	  
+	}
+      // Else check if it is the second nearest neighbor
+      else if(distanceValue < secondNearestDistance)
+	{
+	  secondNearestDistance = distanceValue;
+	}
+      ++pdIt;
+    }
+
+  // Fill results
+  result.first = nearestIndex;
+  if(secondNearestDistance == 0)
+    {
+      result.second = 1;
+    }
+  else
+    {
+      result.second = nearestDistance/secondNearestDistance;
+    }
+
+  // return the result
+  return result;
+
+}
+ 
+template <class TPointSet, class TDistance>
+void
+KeyPointSetsMatchingFilter<TPointSet,TDistance>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+}
+
+} // end namespace otb
+
+#endif 
diff --git a/Code/FeatureExtraction/otbLandmark.h b/Code/FeatureExtraction/otbLandmark.h
new file mode 100755
index 0000000000..2d447da6e1
--- /dev/null
+++ b/Code/FeatureExtraction/otbLandmark.h
@@ -0,0 +1,94 @@
+/*=========================================================================
+
+Program:   ORFEO Toolbox
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+
+Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+See OTBCopyright.txt for details.
+
+
+This software is distributed WITHOUT ANY WARRANTY; without even 
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef __otbLandmark_h
+#define __otbLandmark_h
+
+#include "itkDataObject.h"
+#include "otbMacro.h"
+#include "itkObjectFactory.h"
+
+namespace otb
+{
+  /** \class Landmark
+   *  \brief This class represent point and point data binary matching.
+   *
+   * It is used to represent match between keypoint like SIFT keypoint for instance.
+   *
+   * The class TLandmarkData can be used to store any information on the matching.
+   */
+  template <class TPoint, class TPointData, class TLandmarkData=TPointData>
+    class ITK_EXPORT Landmark 
+    : public itk::DataObject
+    {
+      public:
+      /// standard class typedefs
+      typedef Landmark                      Self;
+      typedef itk::DataObject               Superclass;
+      typedef itk::SmartPointer<Self>       Pointer;
+      typedef itk::SmartPointer<const Self> ConstPointer;
+
+      /// Standard macros
+      itkNewMacro(Self);
+      itkTypeMacro(Landmark,DataObject);
+    
+      /// template typedefs 
+      typedef TPoint        PointType;
+      typedef TPointData    PointDataType;
+      typedef TLandmarkData LandmarkDataType;
+      
+      /// Accessors
+      itkSetMacro(Point1,PointType);
+      itkGetConstReferenceMacro(Point1,PointType);
+      itkSetMacro(PointData1,PointDataType);
+      itkGetConstReferenceMacro(PointData1,PointDataType);
+      itkSetMacro(Point2,PointType);
+      itkGetConstReferenceMacro(Point2,PointType);
+      itkSetMacro(PointData2,PointDataType);
+      itkGetConstReferenceMacro(PointData2,PointDataType);
+      itkSetMacro(LandmarkData,LandmarkDataType);
+      itkGetConstReferenceMacro(LandmarkData,LandmarkDataType);
+
+      protected:
+      /// Constructor 
+      Landmark(){}
+      /// Destructor 
+      ~Landmark(){}
+      /// PrintSelf method 
+      virtual void PrintSelf(std::ostream& os, itk::Indent indent) const
+      {
+	Superclass::PrintSelf(os,indent);
+	os<<indent<<"Landmark: P1= "<<m_Point1<<" P2= "<<m_Point2<<std::endl;
+      }
+
+      private:
+      Landmark(const Self&); //purposely not implemented
+      void operator=(const Self&); //purposely not implemented
+      
+      /// First landmark point
+      PointType        m_Point1;
+      /// Second landmark point
+      PointType        m_Point2;
+      /// First landmark point data
+      PointDataType    m_PointData1;
+      /// Second landmark point data
+      PointDataType    m_PointData2;
+      /// Landmark data
+      LandmarkDataType m_LandmarkData;
+    };
+} // end namespace otb
+#endif
diff --git a/Testing/Code/FeatureExtraction/CMakeLists.txt b/Testing/Code/FeatureExtraction/CMakeLists.txt
index 8539f9b24e..2868e9a5c5 100644
--- a/Testing/Code/FeatureExtraction/CMakeLists.txt
+++ b/Testing/Code/FeatureExtraction/CMakeLists.txt
@@ -906,7 +906,24 @@ ADD_TEST(feTvImageToFastSIFTKeyPointSetFilterSceneOutputAscii ${FEATUREEXTRACTIO
 		6  
 )
 
-				     
+
+
+# --------- MatchingFilter ----------------
+ADD_TEST(KeyPointSetsMatchingFilterNew ${FEATUREEXTRACTION_TESTS9} 
+	otbKeyPointSetsMatchingFilterNew)
+
+ADD_TEST(KeyPointSetsMatchingFilter ${FEATUREEXTRACTION_TESTS9}
+--compare-ascii ${EPS}				   
+	${BASELINE}/feTvKeyPointSetsMatchingFilterOutputAscii.txt
+	${TEMP}/feTvKeyPointSetsMatchingFilterOutputAscii.txt	
+    otbKeyPointSetsMatchingFilter
+	${TEMP}/feTvKeyPointSetsMatchingFilterOutputAscii.txt
+	0.6 0
+)
+	
+#--------- LandMark
+ADD_TEST(LandmarkNew ${FEATUREEXTRACTION_TESTS9} 
+	otbLandmarkNew)			     
 
 # A enrichir
 SET(BasicFeatureExtraction_SRCS1
@@ -1020,6 +1037,9 @@ otbImageToSURFKeyPointSetFilterOutputAscii.cxx
 otbImageToFastSIFTKeyPointSetFilterNew.cxx
 otbImageToFastSIFTKeyPointSetFilterOutputImage.cxx
 otbImageToFastSIFTKeyPointSetFilterOutputAscii.cxx
+otbKeyPointSetsMatchingFilterNew.cxx
+otbKeyPointSetsMatchingFilter.cxx
+otbLandmarkNew.cxx
 )
 
 INCLUDE_DIRECTORIES("${OTBTesting_BINARY_DIR}")
diff --git a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx
index dca475bf97..158296d9ac 100644
--- a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx
+++ b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx
@@ -43,4 +43,7 @@ REGISTER_TEST(otbImageToSURFKeyPointSetFilterOutputAscii);
 REGISTER_TEST(otbImageToFastSIFTKeyPointSetFilterNew);
 REGISTER_TEST(otbImageToFastSIFTKeyPointSetFilterOutputImage);
 REGISTER_TEST(otbImageToFastSIFTKeyPointSetFilterOutputAscii);
+REGISTER_TEST(otbKeyPointSetsMatchingFilterNew);
+REGISTER_TEST(otbKeyPointSetsMatchingFilter);
+REGISTER_TEST(otbLandmarkNew);
 }
diff --git a/Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.cxx b/Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.cxx
new file mode 100755
index 0000000000..57ed0cc12c
--- /dev/null
+++ b/Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilter.cxx
@@ -0,0 +1,107 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+  This software is distributed WITHOUT ANY WARRANTY; without even 
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#if defined(_MSC_VER)
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "otbKeyPointSetsMatchingFilter.h"
+
+#include "itkVariableLengthVector.h"
+#include "itkPointSet.h"
+
+#include <iostream>
+#include <fstream>
+
+int otbKeyPointSetsMatchingFilter(int argc, char* argv[])
+{
+
+  const char * outfname = argv[1];
+  const double thresh        = atof(argv[2]);
+  const bool useBackMatching = atoi(argv[3]);
+  
+  typedef itk::VariableLengthVector<double> PointDataType;
+  typedef itk::PointSet<PointDataType,2>    PointSetType;
+  typedef PointSetType::PointType           PointType;
+  typedef otb::KeyPointSetsMatchingFilter<PointSetType> MatchingFilterType;
+  typedef MatchingFilterType::LandmarkListType LandmarkListType;
+
+
+  // instantiation
+  MatchingFilterType::Pointer filter = MatchingFilterType::New();
+
+  filter->SetUseBackMatching(useBackMatching);
+  filter->SetDistanceThreshold(thresh);
+
+  // Building two pointsets
+  PointSetType::Pointer ps1 = PointSetType::New();
+  PointSetType::Pointer ps2 = PointSetType::New();
+  
+  PointType p1,p2,p3;
+  
+  p1.Fill(1);
+  p2.Fill(2);
+  p3.Fill(3);
+
+  PointDataType d1(3),d2(3),d3(3),d1b(3),d2b(3),d3b(3);
+
+  d1.Fill(1);
+  d1b.Fill(1);
+
+  d2.Fill(0);
+  d2[0]=10;
+  d2b.Fill(0);
+  d2b[1]=10;
+
+  d3.Fill(2);
+  d3b.Fill(10);
+
+  ps1->SetPoint(0,p1);
+  ps1->SetPoint(1,p2);
+  ps1->SetPoint(2,p3);
+
+  ps2->SetPoint(0,p1);
+  ps2->SetPoint(1,p2);
+  ps2->SetPoint(2,p3);
+  
+  ps1->SetPointData(0,d1);
+  ps1->SetPointData(1,d2);
+  ps1->SetPointData(2,d3);
+
+  ps2->SetPointData(0,d1b);
+  ps2->SetPointData(1,d2b);
+  ps2->SetPointData(2,d3b);
+
+  filter->SetInput1(ps1);
+  filter->SetInput2(ps2);
+  
+  filter->Update();
+
+  LandmarkListType * matching = filter->GetOutput();
+  
+  std::ofstream outfile(outfname);
+  outfile <<"Matches: "<<std::endl;
+  
+  for(LandmarkListType::Iterator it = matching->Begin(); it != matching->End();++it)
+    {
+      outfile<<"Matching: "<<it.Get()->GetPoint1()<< " " << it.Get()->GetPointData1()<< " <- "<<it.Get()->GetLandmarkData() << " -> "<<it.Get()->GetPoint2()<< " " << it.Get()->GetPointData2() << std::endl;
+    }
+  
+  outfile.close();
+
+  return EXIT_SUCCESS;
+}
diff --git a/Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilterNew.cxx b/Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilterNew.cxx
new file mode 100644
index 0000000000..2377d866cf
--- /dev/null
+++ b/Testing/Code/FeatureExtraction/otbKeyPointSetsMatchingFilterNew.cxx
@@ -0,0 +1,35 @@
+/*=========================================================================
+
+Program:   ORFEO Toolbox
+Language:  C++
+Date:      $Date$
+Version:   $Revision$
+
+
+Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+See OTBCopyright.txt for details.
+
+
+This software is distributed WITHOUT ANY WARRANTY; without even
+the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "itkPointSet.h"
+#include "itkVariableLengthVector.h"
+#include "otbKeyPointSetsMatchingFilter.h"
+
+int otbKeyPointSetsMatchingFilterNew(int argc, char * argv[])
+{
+  typedef float RealType;
+  const unsigned int Dimension =2;
+
+  typedef itk::VariableLengthVector<RealType> RealVectorType;
+  typedef itk::PointSet<RealVectorType,Dimension> PointSetType;
+  typedef otb::KeyPointSetsMatchingFilter<PointSetType> EuclideanDistanceMatchingFilterType;
+
+  // Instantiating object
+   EuclideanDistanceMatchingFilterType::Pointer object = EuclideanDistanceMatchingFilterType::New();
+  
+  return EXIT_SUCCESS;
+}
diff --git a/Testing/Code/FeatureExtraction/otbLandmarkNew.cxx b/Testing/Code/FeatureExtraction/otbLandmarkNew.cxx
new file mode 100755
index 0000000000..835213f667
--- /dev/null
+++ b/Testing/Code/FeatureExtraction/otbLandmarkNew.cxx
@@ -0,0 +1,37 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+  This software is distributed WITHOUT ANY WARRANTY; without even 
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#if defined(_MSC_VER)
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "otbLandmark.h"
+
+#include "itkVariableLengthVector.h"
+#include "itkPoint.h"
+
+int otbLandmarkNew(int argc, char* argv[])
+{
+  typedef itk::Point<double,2> PointType;
+  typedef itk::VariableLengthVector<double> PointDataType;
+  typedef otb::Landmark<PointType,PointDataType,double> LandmarkType;
+
+  // instantiation
+  LandmarkType::Pointer landmark = LandmarkType::New();
+
+  return EXIT_SUCCESS;
+}
-- 
GitLab