From ed64f52bff5e0b1c423e82b9f2f0d280307911ab Mon Sep 17 00:00:00 2001
From: Julien Michel <julien.michel@c-s.fr>
Date: Wed, 7 May 2008 13:58:22 +0000
Subject: [PATCH] Code Formation

---
 .../otbKMeansImageClassificationFilter.h      | 132 ++++++++++++++
 .../otbKMeansImageClassificationFilter.txx    | 168 +++++++++++++++++
 .../otbSOMImageClassificationFilter.h         | 128 +++++++++++++
 .../otbSOMImageClassificationFilter.txx       | 171 ++++++++++++++++++
 .../otbSVMImageClassificationFilter.h         |  35 +++-
 .../otbSVMImageClassificationFilter.txx       | 129 +++++++++----
 Testing/Code/Learning/CMakeLists.txt          |  37 ++++
 .../otbKMeansImageClassificationFilter.cxx    |  71 ++++++++
 .../otbKMeansImageClassificationFilterNew.cxx |  37 ++++
 Testing/Code/Learning/otbLearningTests3.cxx   |   4 +
 .../otbSOMImageClassificationFilter.cxx       |  63 +++++++
 .../otbSOMImageClassificationFilterNew.cxx    |  38 ++++
 12 files changed, 971 insertions(+), 42 deletions(-)
 create mode 100644 Code/Learning/otbKMeansImageClassificationFilter.h
 create mode 100644 Code/Learning/otbKMeansImageClassificationFilter.txx
 create mode 100644 Code/Learning/otbSOMImageClassificationFilter.h
 create mode 100644 Code/Learning/otbSOMImageClassificationFilter.txx
 create mode 100644 Testing/Code/Learning/otbKMeansImageClassificationFilter.cxx
 create mode 100644 Testing/Code/Learning/otbKMeansImageClassificationFilterNew.cxx
 create mode 100644 Testing/Code/Learning/otbSOMImageClassificationFilter.cxx
 create mode 100644 Testing/Code/Learning/otbSOMImageClassificationFilterNew.cxx

diff --git a/Code/Learning/otbKMeansImageClassificationFilter.h b/Code/Learning/otbKMeansImageClassificationFilter.h
new file mode 100644
index 0000000000..46215652ae
--- /dev/null
+++ b/Code/Learning/otbKMeansImageClassificationFilter.h
@@ -0,0 +1,132 @@
+/*=========================================================================
+
+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 _otbKMeansImageClassificationFilter_h
+#define _otbKMeansImageClassificationFilter_h
+
+#include "itkInPlaceImageFilter.h"
+#include "itkFixedArray.h"
+#include "itkListSample.h"
+#include "itkFixedArray.h"
+#include "itkEuclideanDistance.h"
+
+namespace otb
+{
+  /** \class KMeansImageClassificationFilter
+   *  \brief This filter performs the classification of a VectorImage using a KMeans estimation result.
+   *
+   *  This filter is streamed and threaded, allowing to classify huge images. Because the
+   *  internal sample type has to be an itk::FixedArray, one must specify at compilation time
+   *  the maximum sample dimension. It is up to the user to specify a MaxSampleDimension sufficiently
+   *  high to integrate all its features. This filter internally use one SVMClassifier per thread.
+   *
+   * \sa SVMClassifier
+   * \ingroup Streamed
+   * \ingroup Threaded
+   */
+  template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension = 10, class TMaskImage = TOutputImage>
+  class ITK_EXPORT KMeansImageClassificationFilter
+  : public itk::InPlaceImageFilter<TInputImage,TOutputImage>
+  {
+    public:
+    /** Standard typedefs */
+    typedef KMeansImageClassificationFilter                      Self;
+    typedef itk::InPlaceImageFilter<TInputImage,TOutputImage> Superclass;
+    typedef itk::SmartPointer<Self>                           Pointer;
+    typedef itk::SmartPointer<const Self>                     ConstPointer;
+    
+    /** Type macro */
+    itkNewMacro(Self);
+    
+    /** Creation through object factory macro */
+    itkTypeMacro(KMeansImageClassificationFilter,InPlaceImageFilter);
+
+    /** The max dimension of the sample to classify.
+     *  This filter internally uses itk::FixedArray as input for the classifier,
+     *  so the max sample size has to be fixed at compilation time.
+     */
+    itkStaticConstMacro(MaxSampleDimension,unsigned int,VMaxSampleDimension);
+
+    typedef TInputImage                                InputImageType;
+    typedef typename InputImageType::ConstPointer      InputImageConstPointerType;
+    typedef typename InputImageType::InternalPixelType ValueType;
+
+    typedef TMaskImage                                 MaskImageType;
+    typedef typename MaskImageType::ConstPointer       MaskImageConstPointerType;
+    typedef typename MaskImageType::Pointer            MaskImagePointerType;
+
+    typedef TOutputImage                               OutputImageType;
+    typedef typename OutputImageType::Pointer          OutputImagePointerType;
+    typedef typename OutputImageType::RegionType       OutputImageRegionType;
+    typedef typename OutputImageType::PixelType        LabelType;
+
+
+    typedef itk::FixedArray<ValueType,MaxSampleDimension> SampleType;
+    typedef itk::Array<double>                            KMeansParametersType;
+    typedef std::map<LabelType,SampleType>                CentroidsMapType;
+    typedef itk::Statistics::EuclideanDistance<SampleType> DistanceType;
+    
+    /** Set/Get the centroids */
+    itkSetMacro(Centroids,KMeansParametersType);
+    itkGetConstReferenceMacro(Centroids,KMeansParametersType);
+
+    /** Set/Get the default label */
+    itkSetMacro(DefaultLabel,LabelType);
+    itkGetMacro(DefaultLabel,LabelType);
+
+    /**
+     * If set, only pixels within the mask will be classified.
+     * \param mask The input mask.
+     */
+    void SetInputMask(const MaskImageType * mask);
+
+    /**
+     * Get the input mask.
+     * \return The mask.
+     */
+    const MaskImageType * GetInputMask(void);
+
+    protected:
+    /** Constructor */
+    KMeansImageClassificationFilter();
+    /** Destructor */
+    virtual ~KMeansImageClassificationFilter() {};
+
+    /** Threaded generate data */
+    virtual void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread,int threadId);
+    /** Before threaded generate data */
+    virtual void BeforeThreadedGenerateData();
+    /**PrintSelf method */
+    virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
+    
+    private:
+    KMeansImageClassificationFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+
+    /** Centroids used for classification */
+    KMeansParametersType m_Centroids;
+    /** Default label for invalid pixels (when using a mask) */
+    LabelType m_DefaultLabel;
+    /** Centroids - labels map */
+    CentroidsMapType m_CentroidsMap;
+  };
+}// End namespace otb
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbKMeansImageClassificationFilter.txx"
+#endif
+
+#endif
diff --git a/Code/Learning/otbKMeansImageClassificationFilter.txx b/Code/Learning/otbKMeansImageClassificationFilter.txx
new file mode 100644
index 0000000000..94afd618cb
--- /dev/null
+++ b/Code/Learning/otbKMeansImageClassificationFilter.txx
@@ -0,0 +1,168 @@
+/*=========================================================================
+
+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 _otbKMeansImageClassificationFilter_txx
+#define _otbKMeansImageClassificationFilter_txx
+
+#include "otbKMeansImageClassificationFilter.h"
+#include "itkImageRegionIterator.h"
+#include "itkNumericTraits.h"
+
+namespace otb
+{
+/**
+ * Constructor
+ */
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+KMeansImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::KMeansImageClassificationFilter()
+{
+  this->SetNumberOfInputs(2);
+  this->SetNumberOfRequiredInputs(1);
+  m_DefaultLabel = itk::NumericTraits<LabelType>::ZeroValue();
+}
+
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+void
+KMeansImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::SetInputMask(const MaskImageType * mask)
+{
+  this->itk::ProcessObject::SetNthInput(1,const_cast<MaskImageType *>(mask));
+}
+
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+const typename KMeansImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::MaskImageType *
+KMeansImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::GetInputMask()
+{
+  if(this->GetNumberOfInputs()<2)
+    {
+      return 0;
+    }
+  return  static_cast<const MaskImageType *>(this->itk::ProcessObject::GetInput(1));
+}
+
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+void
+KMeansImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::BeforeThreadedGenerateData()
+{
+  unsigned int sample_size = MaxSampleDimension;
+  unsigned int nb_classes = m_Centroids.Size()/sample_size;
+
+  for(LabelType label = 1;label<=static_cast<LabelType>(nb_classes);++label)
+    {
+      SampleType new_centroid;
+      new_centroid.Fill(0);
+      m_CentroidsMap[label]=new_centroid;
+
+      for(unsigned int i=0;i<MaxSampleDimension;++i)
+	{
+	  m_CentroidsMap[label][i]=m_Centroids[MaxSampleDimension*(label-1)+i];
+	}
+    }
+}
+
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+void
+KMeansImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, int threadId)
+{
+  InputImageConstPointerType inputPtr     = this->GetInput();
+  MaskImageConstPointerType inputMaskPtr  = this->GetInputMask();
+  OutputImagePointerType     outputPtr    = this->GetOutput();
+
+  typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
+  typedef itk::ImageRegionConstIterator<MaskImageType> MaskIteratorType;
+  typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType;
+   
+  InputIteratorType inIt(inputPtr,outputRegionForThread);
+  OutputIteratorType outIt(outputPtr,outputRegionForThread);
+
+  MaskIteratorType maskIt;
+  if(inputMaskPtr)
+    {
+      maskIt = MaskIteratorType(inputMaskPtr,outputRegionForThread);
+      maskIt.GoToBegin();
+    }
+  unsigned int maxDimension = SampleType::Dimension;
+  unsigned int sampleSize = std::min(inputPtr->GetNumberOfComponentsPerPixel(),
+				    maxDimension);
+
+  bool validPoint = true;
+
+  while(!outIt.IsAtEnd())
+    {
+      outIt.Set(m_DefaultLabel);
+       ++outIt;
+    }
+
+  outIt.GoToBegin();
+
+   validPoint = true;
+
+   typename DistanceType::Pointer distance = DistanceType::New();
+
+   while(!outIt.IsAtEnd()&&(!inIt.IsAtEnd()))
+     {
+       if(inputMaskPtr)
+	 {
+	   validPoint = maskIt.Get()>0;
+	   ++maskIt;
+	 }
+       if(validPoint)
+	 {
+	   LabelType label =1;
+	   LabelType current_label =1;
+	   SampleType pixel;
+	   pixel.Fill(0);
+	   for(unsigned int i=0;i<sampleSize;++i)
+	     {
+	       pixel[i]=inIt.Get()[i];
+	     }
+	   
+	   double current_distance = distance->Evaluate(pixel,m_CentroidsMap[label]);
+
+	   for(label=2;label<=static_cast<LabelType>(m_CentroidsMap.size());++label)
+	     {
+	       double tmp_dist = distance->Evaluate(pixel,m_CentroidsMap[label]);
+	       if(tmp_dist<current_distance)
+		 {
+		   current_label = label;
+		   current_distance = tmp_dist;
+		 }
+	     }
+	   std::cout<<"Pixel: "<<pixel<<" label: "<<current_label<<" centroid: "<<m_CentroidsMap[current_label]<<std::endl;
+	   outIt.Set(current_label);
+	 }
+       ++outIt;
+       ++inIt; 
+     }
+}
+/**
+ * PrintSelf Method
+ */
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+void
+KMeansImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+}
+} // End namespace otb
+#endif
diff --git a/Code/Learning/otbSOMImageClassificationFilter.h b/Code/Learning/otbSOMImageClassificationFilter.h
new file mode 100644
index 0000000000..db9cb1d074
--- /dev/null
+++ b/Code/Learning/otbSOMImageClassificationFilter.h
@@ -0,0 +1,128 @@
+/*=========================================================================
+
+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 _otbSOMImageClassificationFilter_h
+#define _otbSOMImageClassificationFilter_h
+
+#include "otbSOMClassifier.h"
+#include "itkInPlaceImageFilter.h"
+#include "itkFixedArray.h"
+#include "itkListSample.h"
+
+namespace otb
+{
+  /** \class SOMImageClassificationFilter
+   *  \brief This filter performs the classification of a VectorImage using a given SOM map.
+   *
+   *  This filter is streamed and threaded, allowing to classify huge images. Because the
+   *  internal sample type has to be an itk::FixedArray, one must specify at compilation time
+   *  the maximum sample dimension. It is up to the user to specify a MaxSampleDimension sufficiently
+   *  high to integrate all its features. This filter internally use one SVMClassifier per thread.
+   *
+   * \sa SVMClassifier
+   * \ingroup Streamed
+   * \ingroup Threaded
+   */
+  template <class TInputImage, class TOutputImage,class TSOMMap, class TMaskImage = TOutputImage>
+  class ITK_EXPORT SOMImageClassificationFilter
+  : public itk::InPlaceImageFilter<TInputImage,TOutputImage>
+  {
+    public:
+    /** Standard typedefs */
+    typedef SOMImageClassificationFilter                      Self;
+    typedef itk::InPlaceImageFilter<TInputImage,TOutputImage> Superclass;
+    typedef itk::SmartPointer<Self>                           Pointer;
+    typedef itk::SmartPointer<const Self>                     ConstPointer;
+    
+    /** Type macro */
+    itkNewMacro(Self);
+    
+    /** Creation through object factory macro */
+    itkTypeMacro(SOMImageClassificationFilter,InPlaceImageFilter);
+
+    typedef TInputImage                                InputImageType;
+    typedef typename InputImageType::ConstPointer      InputImageConstPointerType;
+    typedef typename InputImageType::InternalPixelType ValueType;
+
+    typedef TMaskImage                                 MaskImageType;
+    typedef typename MaskImageType::ConstPointer       MaskImageConstPointerType;
+    typedef typename MaskImageType::Pointer            MaskImagePointerType;
+
+    typedef TOutputImage                               OutputImageType;
+    typedef typename OutputImageType::Pointer          OutputImagePointerType;
+    typedef typename OutputImageType::RegionType       OutputImageRegionType;
+    typedef typename OutputImageType::PixelType        LabelType;
+
+    typedef TSOMMap                                    SOMMapType;
+    typedef typename SOMMapType::Pointer               SOMMapPointerType;
+    typedef typename SOMMapType::PixelType             SampleType;
+
+    typedef itk::Statistics::ListSample<SampleType>                      ListSampleType;
+    typedef typename ListSampleType::Pointer                             ListSamplePointerType;
+    typedef otb::SOMClassifier<ListSampleType,SOMMapType,LabelType>      ClassifierType;
+    typedef typename ClassifierType::Pointer                             ClassifierPointerType;
+    
+    /** Set/Get the svm model */
+    itkSetObjectMacro(Map,SOMMapType);
+    itkGetObjectMacro(Map,SOMMapType);
+
+    /** Set/Get the default label */
+    itkSetMacro(DefaultLabel,LabelType);
+    itkGetMacro(DefaultLabel,LabelType);
+
+    /**
+     * If set, only pixels within the mask will be classified.
+     * \param mask The input mask.
+     */
+    void SetInputMask(const MaskImageType * mask);
+
+    /**
+     * Get the input mask.
+     * \return The mask.
+     */
+    const MaskImageType * GetInputMask(void);
+
+    protected:
+    /** Constructor */
+    SOMImageClassificationFilter();
+    /** Destructor */
+    virtual ~SOMImageClassificationFilter() {};
+
+    /** Threaded generate data */
+    virtual void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread,int threadId);
+    /** Before threaded generate data */
+    virtual void BeforeThreadedGenerateData();
+    /**PrintSelf method */
+    virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
+    
+    private:
+    SOMImageClassificationFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+
+    /** The SOM model used for classification */
+    SOMMapPointerType m_Map;
+    /** Default label for invalid pixels (when using a mask) */
+    LabelType m_DefaultLabel;
+
+
+  };
+}// End namespace otb
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSOMImageClassificationFilter.txx"
+#endif
+
+#endif
diff --git a/Code/Learning/otbSOMImageClassificationFilter.txx b/Code/Learning/otbSOMImageClassificationFilter.txx
new file mode 100644
index 0000000000..cc43b02fe5
--- /dev/null
+++ b/Code/Learning/otbSOMImageClassificationFilter.txx
@@ -0,0 +1,171 @@
+/*=========================================================================
+
+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 _otbSOMImageClassificationFilter_txx
+#define _otbSOMImageClassificationFilter_txx
+
+#include "otbSOMImageClassificationFilter.h"
+#include "itkImageRegionIterator.h"
+#include "itkNumericTraits.h"
+
+namespace otb
+{
+/**
+ * Constructor
+ */
+template <class TInputImage, class TOutputImage, class TSOMMap, class TMaskImage>
+SOMImageClassificationFilter<TInputImage,TOutputImage,TSOMMap,TMaskImage>
+::SOMImageClassificationFilter()
+{
+  this->SetNumberOfInputs(2);
+  this->SetNumberOfRequiredInputs(1);
+  m_DefaultLabel = itk::NumericTraits<LabelType>::ZeroValue();
+}
+
+template <class TInputImage, class TOutputImage, class TSOMMap, class TMaskImage>
+void
+SOMImageClassificationFilter<TInputImage,TOutputImage,TSOMMap,TMaskImage>
+::SetInputMask(const MaskImageType * mask)
+{
+  this->itk::ProcessObject::SetNthInput(1,const_cast<MaskImageType *>(mask));
+}
+
+template <class TInputImage, class TOutputImage, class TSOMMap, class TMaskImage>
+const typename SOMImageClassificationFilter<TInputImage,TOutputImage,TSOMMap,TMaskImage>
+::MaskImageType *
+SOMImageClassificationFilter<TInputImage,TOutputImage,TSOMMap,TMaskImage>
+::GetInputMask()
+{
+  if(this->GetNumberOfInputs()<2)
+    {
+      return 0;
+    }
+  return  static_cast<const MaskImageType *>(this->itk::ProcessObject::GetInput(1));
+}
+
+template <class TInputImage, class TOutputImage, class TSOMMap, class TMaskImage>
+void
+SOMImageClassificationFilter<TInputImage,TOutputImage,TSOMMap,TMaskImage>
+::BeforeThreadedGenerateData()
+{
+  if(!m_Map)
+    {
+      itkGenericExceptionMacro(<<"No model for classification");
+    }
+}
+
+template <class TInputImage, class TOutputImage, class TSOMMap, class TMaskImage>
+void
+SOMImageClassificationFilter<TInputImage,TOutputImage,TSOMMap,TMaskImage>
+::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, int threadId)
+{
+  InputImageConstPointerType inputPtr     = this->GetInput();
+  MaskImageConstPointerType inputMaskPtr  = this->GetInputMask();
+  OutputImagePointerType     outputPtr    = this->GetOutput();
+
+  typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
+  typedef itk::ImageRegionConstIterator<MaskImageType> MaskIteratorType;
+  typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType;
+  
+  ListSamplePointerType listSample = ListSampleType::New();
+  
+  InputIteratorType inIt(inputPtr,outputRegionForThread);
+
+  MaskIteratorType maskIt;
+  if(inputMaskPtr)
+    {
+      maskIt = MaskIteratorType(inputMaskPtr,outputRegionForThread);
+      maskIt.GoToBegin();
+    }
+  unsigned int maxDimension = m_Map->GetNumberOfComponentsPerPixel();
+  unsigned int sampleSize = std::min(inputPtr->GetNumberOfComponentsPerPixel(),
+				     maxDimension);
+  bool validPoint = true;
+
+  for(inIt.GoToBegin();!inIt.IsAtEnd();++inIt)
+    {
+      if(inputMaskPtr)
+	{
+	  validPoint = maskIt.Get()>0;
+	  ++maskIt;
+	}
+      if(validPoint)
+	{
+	  SampleType sample;
+	  sample.SetSize(sampleSize);
+	  sample.Fill(itk::NumericTraits<ValueType>::ZeroValue());
+	  for(unsigned int i=0;i<sampleSize;i++)
+	    {
+	      sample[i]=inIt.Get()[i];
+	    }
+	  listSample->PushBack(sample);
+	}
+    }
+  ClassifierPointerType classifier =ClassifierType::New();
+  classifier->SetMap(m_Map);
+  classifier->SetSample(listSample);
+  classifier->Update();
+  
+  typename ClassifierType::OutputType::Pointer membershipSample = classifier->GetOutput();
+  typename ClassifierType::OutputType::ConstIterator sampleIter = membershipSample->Begin();
+  typename ClassifierType::OutputType::ConstIterator sampleLast = membershipSample->End();
+  
+  OutputIteratorType outIt(outputPtr,outputRegionForThread);
+  
+  outIt.GoToBegin();
+
+  while(!outIt.IsAtEnd()&&(sampleIter!=sampleLast))
+    {
+      outIt.Set(m_DefaultLabel);
+       ++outIt;
+    }
+
+  outIt.GoToBegin();
+
+   if(inputMaskPtr)
+    {
+      maskIt.GoToBegin();
+    }
+   validPoint = true;
+
+   while(!outIt.IsAtEnd()&&(sampleIter!=sampleLast))
+     {
+       if(inputMaskPtr)
+	 {
+	   validPoint = maskIt.Get()>0;
+	   ++maskIt;
+	 }
+       if(validPoint)
+	 {
+	   outIt.Set(sampleIter.GetClassLabel());
+	   ++sampleIter;
+	 }
+       ++outIt;
+     }
+}
+/**
+ * PrintSelf Method
+ */
+template <class TInputImage, class TOutputImage, class TSOMMap, class TMaskImage>
+void
+SOMImageClassificationFilter<TInputImage,TOutputImage,TSOMMap,TMaskImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+}
+} // End namespace otb
+#endif
diff --git a/Code/Learning/otbSVMImageClassificationFilter.h b/Code/Learning/otbSVMImageClassificationFilter.h
index f5e1d0ca59..db1cdfb919 100644
--- a/Code/Learning/otbSVMImageClassificationFilter.h
+++ b/Code/Learning/otbSVMImageClassificationFilter.h
@@ -15,8 +15,8 @@ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.
 
 =========================================================================*/
-#ifndef _otbImageClassificationFilter_h
-#define _otbImageClassificationFilter_h
+#ifndef _otbSVMImageClassificationFilter_h
+#define _otbSVMImageClassificationFilter_h
 
 #include "otbSVMClassifier.h"
 #include "itkInPlaceImageFilter.h"
@@ -26,7 +26,7 @@ PURPOSE.  See the above copyright notices for more information.
 
 namespace otb
 {
-  /** \class ImageClassificationFilter
+  /** \class SVMImageClassificationFilter
    *  \brief This filter performs the classification of a VectorImage using a SVM Model.
    *
    *  This filter is streamed and threaded, allowing to classify huge images. Because the
@@ -38,7 +38,7 @@ namespace otb
    * \ingroup Streamed
    * \ingroup Threaded
    */
-template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension = 10>
+  template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension = 10, class TMaskImage = TOutputImage>
   class ITK_EXPORT SVMImageClassificationFilter
   : public itk::InPlaceImageFilter<TInputImage,TOutputImage>
   {
@@ -65,6 +65,10 @@ template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimensio
     typedef typename InputImageType::ConstPointer      InputImageConstPointerType;
     typedef typename InputImageType::InternalPixelType ValueType;
 
+    typedef TMaskImage                                 MaskImageType;
+    typedef typename MaskImageType::ConstPointer       MaskImageConstPointerType;
+    typedef typename MaskImageType::Pointer            MaskImagePointerType;
+
     typedef TOutputImage                               OutputImageType;
     typedef typename OutputImageType::Pointer          OutputImagePointerType;
     typedef typename OutputImageType::RegionType       OutputImageRegionType;
@@ -77,12 +81,27 @@ template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimensio
     typedef typename ClassifierType::Pointer                   ClassifierPointerType;
     typedef SVMModel< ValueType, LabelType >                   ModelType;
     typedef typename ModelType::Pointer                        ModelPointerType;
-    typedef std::vector<ClassifierPointerType>                 ClassifierPointerVectorType;
     
     /** Set/Get the svm model */
     itkSetObjectMacro(Model,ModelType);
     itkGetObjectMacro(Model,ModelType);
 
+    /** Set/Get the default label */
+    itkSetMacro(DefaultLabel,LabelType);
+    itkGetMacro(DefaultLabel,LabelType);
+
+    /**
+     * If set, only pixels within the mask will be classified.
+     * \param mask The input mask.
+     */
+    void SetInputMask(const MaskImageType * mask);
+
+    /**
+     * Get the input mask.
+     * \return The mask.
+     */
+    const MaskImageType * GetInputMask(void);
+
     protected:
     /** Constructor */
     SVMImageClassificationFilter();
@@ -102,8 +121,10 @@ template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimensio
 
     /** The SVM model used for classification */
     ModelPointerType m_Model;
-    /** Vector of classifier (one classifier per thread) */
-    ClassifierPointerVectorType m_ClassifierVector;
+    /** Default label for invalid pixels (when using a mask) */
+    LabelType m_DefaultLabel;
+
+
   };
 }// End namespace otb
 #ifndef OTB_MANUAL_INSTANTIATION
diff --git a/Code/Learning/otbSVMImageClassificationFilter.txx b/Code/Learning/otbSVMImageClassificationFilter.txx
index 55d8cb0057..ac5ecb98e1 100644
--- a/Code/Learning/otbSVMImageClassificationFilter.txx
+++ b/Code/Learning/otbSVMImageClassificationFilter.txx
@@ -27,84 +27,143 @@ namespace otb
 /**
  * Constructor
  */
-template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension>
-SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension>
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
 ::SVMImageClassificationFilter()
 {
-  for(unsigned int i = 0;i<static_cast<unsigned int>(this->GetNumberOfThreads());++i)
+  this->SetNumberOfInputs(2);
+  this->SetNumberOfRequiredInputs(1);
+  m_DefaultLabel = itk::NumericTraits<LabelType>::ZeroValue();
+}
+
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+void
+SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::SetInputMask(const MaskImageType * mask)
+{
+  this->itk::ProcessObject::SetNthInput(1,const_cast<MaskImageType *>(mask));
+}
+
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
+const typename SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::MaskImageType *
+SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
+::GetInputMask()
+{
+  if(this->GetNumberOfInputs()<2)
     {
-      m_ClassifierVector.push_back(ClassifierType::New());
+      return 0;
     }
+  return  static_cast<const MaskImageType *>(this->itk::ProcessObject::GetInput(1));
 }
 
-template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension>
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
 void
-SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension>
+SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
 ::BeforeThreadedGenerateData()
 {
   if(!m_Model)
     {
       itkGenericExceptionMacro(<<"No model for classification");
     }
-  for(unsigned int i = 0;i<static_cast<unsigned int>(this->GetNumberOfThreads());++i)
-    {
-      m_ClassifierVector[i]->SetModel(m_Model);
-      m_ClassifierVector[i]->SetNumberOfClasses(m_Model->GetNumberOfClasses());
-    }
 }
 
-template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension>
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
 void
-SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension>
+SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
 ::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, int threadId)
 {
-  InputImageConstPointerType inputPtr = this->GetInput();
-  OutputImagePointerType     outputPtr = this->GetOutput();
+  InputImageConstPointerType inputPtr     = this->GetInput();
+  MaskImageConstPointerType inputMaskPtr  = this->GetInputMask();
+  OutputImagePointerType     outputPtr    = this->GetOutput();
 
   typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
+  typedef itk::ImageRegionConstIterator<MaskImageType> MaskIteratorType;
   typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType;
   
   ListSamplePointerType listSample = ListSampleType::New();
   
   InputIteratorType inIt(inputPtr,outputRegionForThread);
+
+  MaskIteratorType maskIt;
+  if(inputMaskPtr)
+    {
+      maskIt = MaskIteratorType(inputMaskPtr,outputRegionForThread);
+      maskIt.GoToBegin();
+    }
     
   unsigned int sampleSize = std::min(inputPtr->GetNumberOfComponentsPerPixel(),
 				     VMaxSampleDimension);
+
+  bool validPoint = true;
+
   for(inIt.GoToBegin();!inIt.IsAtEnd();++inIt)
     {
-      MeasurementVectorType sample;
-      sample.Fill(itk::NumericTraits<ValueType>::ZeroValue());
-      for(unsigned int i=0;i<sampleSize;i++)
+      if(inputMaskPtr)
 	{
-	  sample[i]=inIt.Get()[i];
+	  validPoint = maskIt.Get()>0;
+	  ++maskIt;
+	}
+      if(validPoint)
+	{
+	  MeasurementVectorType sample;
+	  sample.Fill(itk::NumericTraits<ValueType>::ZeroValue());
+	  for(unsigned int i=0;i<sampleSize;i++)
+	    {
+	      sample[i]=inIt.Get()[i];
+	    }
+	  listSample->PushBack(sample);
 	}
-      listSample->PushBack(sample);
     }
+  ClassifierPointerType classifier =ClassifierType::New();
+  classifier->SetModel(m_Model);
+  classifier->SetNumberOfClasses(m_Model->GetNumberOfClasses());
+  classifier->SetSample(listSample);
+  classifier->Update();
+  
+  typename ClassifierType::OutputType::Pointer membershipSample = classifier->GetOutput();
+  typename ClassifierType::OutputType::ConstIterator sampleIter = membershipSample->Begin();
+  typename ClassifierType::OutputType::ConstIterator sampleLast = membershipSample->End();
   
-  m_ClassifierVector[threadId]->SetSample(listSample);
-  m_ClassifierVector[threadId]->Update();
-
-  typename ClassifierType::OutputType::Pointer membershipSample = m_ClassifierVector[threadId]->GetOutput() ;
-  typename ClassifierType::OutputType::ConstIterator sampleIter = membershipSample->Begin() ;
-  typename ClassifierType::OutputType::ConstIterator sampleLast = membershipSample->End() ;
-
   OutputIteratorType outIt(outputPtr,outputRegionForThread);
-
+  
   outIt.GoToBegin();
 
   while(!outIt.IsAtEnd()&&(sampleIter!=sampleLast))
-  {
-    outIt.Set(sampleIter.GetClassLabel());
-    ++outIt;
-    ++sampleIter;
-  }
+    {
+      outIt.Set(m_DefaultLabel);
+       ++outIt;
+    }
+
+  outIt.GoToBegin();
+
+   if(inputMaskPtr)
+    {
+      maskIt.GoToBegin();
+    }
+   validPoint = true;
+
+   while(!outIt.IsAtEnd()&&(sampleIter!=sampleLast))
+     {
+       if(inputMaskPtr)
+	 {
+	   validPoint = maskIt.Get()>0;
+	   ++maskIt;
+	 }
+       if(validPoint)
+	 {
+	   outIt.Set(sampleIter.GetClassLabel());
+	   ++sampleIter;
+	 }
+       ++outIt;
+     }
 }
 /**
  * PrintSelf Method
  */
-template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension>
+template <class TInputImage, class TOutputImage, unsigned int VMaxSampleDimension, class TMaskImage>
 void
-SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension>
+SVMImageClassificationFilter<TInputImage,TOutputImage,VMaxSampleDimension,TMaskImage>
 ::PrintSelf(std::ostream& os, itk::Indent indent) const
 {
   Superclass::PrintSelf(os, indent);
diff --git a/Testing/Code/Learning/CMakeLists.txt b/Testing/Code/Learning/CMakeLists.txt
index 1730b07384..0af51f5029 100644
--- a/Testing/Code/Learning/CMakeLists.txt
+++ b/Testing/Code/Learning/CMakeLists.txt
@@ -209,6 +209,39 @@ ADD_TEST(leTvSOMClassifier ${LEARNING_TESTS3}
 	${TEMP}/leSOMPoupeesClassified.hdr
 	)
 
+# -------            otb::SOMImageClassificationFilter   -----------------------------	
+
+ADD_TEST(leTuSOMImageClassificationFilterNew ${LEARNING_TESTS3}  
+        otbSOMImageClassificationFilterNew)
+
+ADD_TEST(leTvSOMImageClassificationFilter ${LEARNING_TESTS3}  
+        --compare-image ${TOL}
+	${BASELINE}/leSOMPoupeesClassified.hdr
+	${TEMP}/leSOMImageClassificationFilterOuptut.hdr
+	otbSOMImageClassificationFilter
+	${INPUTDATA}/poupees_sub.png
+	${BASELINE}/leSOMPoupeesSubOutputMap1.hdr
+	${TEMP}/leSOMImageClassificationFilterOuptut.hdr
+	)
+
+
+# -------            otb::KMeansImageClassificationFilter   -----------------------------	
+
+ADD_TEST(leTuKMeansImageClassificationFilterNew ${LEARNING_TESTS3}  
+        otbKMeansImageClassificationFilterNew)
+
+ADD_TEST(leTvKMeansImageClassificationFilter ${LEARNING_TESTS3}  
+        --compare-image ${TOL}
+	${BASELINE}/leKMeansImageClassificationFilterOuptut.hdr
+	${TEMP}/leKMeansImageClassificationFilterOuptut.hdr
+	otbKMeansImageClassificationFilter
+	${INPUTDATA}/poupees_sub.png
+	${TEMP}/leKMeansImageClassificationFilterOuptut.hdr
+	2
+	0 0 0 0
+	255 255 255 255
+	)
+
 # -------            otb::SEMClassifier   -----------------------------	
 
 ADD_TEST(leTuSEMClassifierNew ${LEARNING_TESTS3}  
@@ -289,6 +322,10 @@ otbSOMActivationBuilder.cxx
 SET(BasicLearning_SRCS3
 otbSOMClassifierNew.cxx
 otbSOMClassifier.cxx
+otbSOMImageClassificationFilterNew.cxx
+otbSOMImageClassificationFilter.cxx
+otbKMeansImageClassificationFilterNew.cxx
+otbKMeansImageClassificationFilter.cxx
 otbSEMClassifierNew.cxx
 otbSVMImageClassificationFilterNew.cxx
 otbSVMImageClassificationFilter.cxx
diff --git a/Testing/Code/Learning/otbKMeansImageClassificationFilter.cxx b/Testing/Code/Learning/otbKMeansImageClassificationFilter.cxx
new file mode 100644
index 0000000000..ccd6707709
--- /dev/null
+++ b/Testing/Code/Learning/otbKMeansImageClassificationFilter.cxx
@@ -0,0 +1,71 @@
+/*=========================================================================
+
+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 "otbKMeansImageClassificationFilter.h"
+#include "otbVectorImage.h"
+#include "otbImage.h"
+#include "otbImageFileReader.h"
+#include "otbStreamingImageFileWriter.h"
+
+int otbKMeansImageClassificationFilter(int argc, char * argv[])
+{
+  const char * infname = argv[1];
+  const char * outfname = argv[2];
+  const unsigned int nbClasses = atoi(argv[3]);
+
+  const unsigned int     Dimension = 2;
+  typedef double         PixelType;
+  typedef unsigned short LabeledPixelType;
+
+  typedef otb::VectorImage<PixelType,Dimension> ImageType;
+  typedef otb::Image<LabeledPixelType,Dimension> LabeledImageType;
+  typedef otb::KMeansImageClassificationFilter<ImageType,LabeledImageType> ClassificationFilterType;
+  typedef ClassificationFilterType::KMeansParametersType KMeansParametersType;
+  typedef otb::ImageFileReader<ImageType> ReaderType;
+  typedef otb::StreamingImageFileWriter<LabeledImageType> WriterType;
+ 
+ 
+  // Instantiating object
+  ClassificationFilterType::Pointer filter = ClassificationFilterType::New();
+
+  ReaderType::Pointer reader = ReaderType::New();
+  reader->SetFileName(infname);
+  reader->GenerateOutputInformation();
+
+  unsigned int parameterSize = nbClasses * reader->GetOutput()->GetNumberOfComponentsPerPixel();
+   KMeansParametersType parameters;
+
+   parameters.SetSize(parameterSize);
+   parameters.Fill(0);
+
+   for(unsigned int i = 0; i < parameterSize;++i)
+     {
+       parameters[i]=atof(argv[4+i]);
+     }
+     
+   std::cout<<"Parameters: "<<parameters<<std::endl;
+
+  filter->SetCentroids(parameters);
+  filter->SetInput(reader->GetOutput());
+  
+  WriterType::Pointer writer = WriterType::New();
+  writer->SetInput(filter->GetOutput());
+  writer->SetFileName(outfname);
+  writer->Update();
+
+  return EXIT_SUCCESS;
+}
diff --git a/Testing/Code/Learning/otbKMeansImageClassificationFilterNew.cxx b/Testing/Code/Learning/otbKMeansImageClassificationFilterNew.cxx
new file mode 100644
index 0000000000..8c4a4d9cae
--- /dev/null
+++ b/Testing/Code/Learning/otbKMeansImageClassificationFilterNew.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.
+
+=========================================================================*/
+#include "otbKMeansImageClassificationFilter.h"
+#include "otbVectorImage.h"
+#include "otbImage.h"
+
+int otbKMeansImageClassificationFilterNew(int argc, char * argv[])
+{
+  const unsigned int     Dimension = 2;
+  typedef double         PixelType;
+  typedef unsigned short LabeledPixelType;
+
+  typedef otb::VectorImage<PixelType,Dimension> ImageType;
+  typedef otb::Image<LabeledPixelType,Dimension> LabeledImageType;
+
+  typedef otb::KMeansImageClassificationFilter<ImageType,LabeledImageType> ClassificationFilterType;
+  
+  // Instantiating object
+  ClassificationFilterType::Pointer object = ClassificationFilterType::New();
+
+  return EXIT_SUCCESS;
+}
diff --git a/Testing/Code/Learning/otbLearningTests3.cxx b/Testing/Code/Learning/otbLearningTests3.cxx
index 5ad0ccba58..20f5506ed3 100644
--- a/Testing/Code/Learning/otbLearningTests3.cxx
+++ b/Testing/Code/Learning/otbLearningTests3.cxx
@@ -30,6 +30,8 @@ void RegisterTests()
 {
 REGISTER_TEST(otbSOMClassifierNew);
 REGISTER_TEST(otbSOMClassifier);
+REGISTER_TEST(otbSOMImageClassificationFilterNew);
+REGISTER_TEST(otbSOMImageClassificationFilter);
 REGISTER_TEST(otbSEMClassifierNew);
 REGISTER_TEST(otbSVMImageClassificationFilterNew);
 REGISTER_TEST(otbSVMImageClassificationFilter);
@@ -37,4 +39,6 @@ REGISTER_TEST(otbSVMModelGenericKernelsTest);
 REGISTER_TEST(otbSVMModelCopyTest);
 REGISTER_TEST(otbSVMModelCopyGenericKernelTest);
 REGISTER_TEST(otbSVMModelCopyComposedKernelTest);
+REGISTER_TEST(otbKMeansImageClassificationFilterNew);
+REGISTER_TEST(otbKMeansImageClassificationFilter);
 }
diff --git a/Testing/Code/Learning/otbSOMImageClassificationFilter.cxx b/Testing/Code/Learning/otbSOMImageClassificationFilter.cxx
new file mode 100644
index 0000000000..6aa4aa2eaa
--- /dev/null
+++ b/Testing/Code/Learning/otbSOMImageClassificationFilter.cxx
@@ -0,0 +1,63 @@
+/*=========================================================================
+
+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 "otbSOMImageClassificationFilter.h"
+#include "otbVectorImage.h"
+#include "otbImage.h"
+#include "otbSOMMap.h"
+#include "otbImageFileReader.h"
+#include "otbStreamingImageFileWriter.h"
+
+int otbSOMImageClassificationFilter(int argc, char * argv[])
+{
+  const char * infname = argv[1];
+  const char * somfname = argv[2];
+  const char * outfname = argv[3];
+
+  const unsigned int     Dimension = 2;
+  typedef double         PixelType;
+  typedef unsigned short LabeledPixelType;
+
+  typedef otb::VectorImage<PixelType,Dimension> ImageType;
+  typedef otb::Image<LabeledPixelType,Dimension> LabeledImageType;
+  typedef otb::SOMMap<ImageType::PixelType> SOMMapType;
+  typedef otb::SOMImageClassificationFilter<ImageType,LabeledImageType,SOMMapType> ClassificationFilterType;
+  typedef otb::ImageFileReader<ImageType> ReaderType;
+  typedef otb::ImageFileReader<SOMMapType> SOMReaderType;
+  typedef otb::StreamingImageFileWriter<LabeledImageType> WriterType;
+
+ 
+  // Instantiating object
+  ClassificationFilterType::Pointer filter = ClassificationFilterType::New();
+
+  ReaderType::Pointer reader = ReaderType::New();
+  reader->SetFileName(infname);
+
+  SOMReaderType::Pointer somreader = SOMReaderType::New();
+  somreader->SetFileName(somfname);
+  somreader->Update();
+  
+  filter->SetMap(somreader->GetOutput());
+  filter->SetInput(reader->GetOutput());
+  
+  WriterType::Pointer writer = WriterType::New();
+  writer->SetInput(filter->GetOutput());
+  writer->SetFileName(outfname);
+  writer->Update();
+
+  return EXIT_SUCCESS;
+}
diff --git a/Testing/Code/Learning/otbSOMImageClassificationFilterNew.cxx b/Testing/Code/Learning/otbSOMImageClassificationFilterNew.cxx
new file mode 100644
index 0000000000..da5d6031f4
--- /dev/null
+++ b/Testing/Code/Learning/otbSOMImageClassificationFilterNew.cxx
@@ -0,0 +1,38 @@
+/*=========================================================================
+
+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 "otbSOMImageClassificationFilter.h"
+#include "otbVectorImage.h"
+#include "otbImage.h"
+#include "otbSOMMap.h"
+
+int otbSOMImageClassificationFilterNew(int argc, char * argv[])
+{
+  const unsigned int     Dimension = 2;
+  typedef double         PixelType;
+  typedef unsigned short LabeledPixelType;
+
+  typedef otb::VectorImage<PixelType,Dimension> ImageType;
+  typedef otb::Image<LabeledPixelType,Dimension> LabeledImageType;
+  typedef otb::SOMMap<ImageType::PixelType> SOMMapType;
+  typedef otb::SOMImageClassificationFilter<ImageType,LabeledImageType,SOMMapType> ClassificationFilterType;
+ 
+  // Instantiating object
+  ClassificationFilterType::Pointer filter = ClassificationFilterType::New();
+
+  return EXIT_SUCCESS;
+}
-- 
GitLab