From 910711f1da1a25169ae0e5abeaabe2d3cc59de07 Mon Sep 17 00:00:00 2001
From: Julien Michel <julien.michel@c-s.fr>
Date: Wed, 18 Apr 2007 13:37:12 +0000
Subject: [PATCH] Ajout du filtre Spectral Angle.

---
 .../otbSpectralAngleDistanceImageFilter.h     | 110 +++++++++++++++++
 .../otbSpectralAngleDistanceImageFilter.txx   | 112 ++++++++++++++++++
 Testing/Code/BasicFilters/CMakeLists.txt      |  18 +++
 .../BasicFilters/otbBasicFiltersTests.cxx     |   2 +
 .../otbSpectralAngleDistanceImageFilter.cxx   |  71 +++++++++++
 ...otbSpectralAngleDistanceImageFilterNew.cxx |  50 ++++++++
 6 files changed, 363 insertions(+)
 create mode 100644 Code/BasicFilters/otbSpectralAngleDistanceImageFilter.h
 create mode 100644 Code/BasicFilters/otbSpectralAngleDistanceImageFilter.txx
 create mode 100644 Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.cxx
 create mode 100644 Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilterNew.cxx

diff --git a/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.h b/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.h
new file mode 100644
index 0000000000..dd6a86899a
--- /dev/null
+++ b/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.h
@@ -0,0 +1,110 @@
+/*=========================================================================
+
+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 _otbSpectralAngleDistanceImageFilter_h
+#define _otbSpectralAngleDistanceImageFilter_h
+
+#include "itkImageToImageFilter.h"
+
+namespace otb
+{
+/** \class SpectralAngleDistanceImageFilter
+ *  \brief This filter implements the computation of the spectral angle
+ * distance with respect to a reference pixel.
+ * 
+ * Spectral angle distance is an efficient way to convert spectral information to
+ * scalar data with respect to a reference pixel. The spectral angle distance 
+ * is defined as:
+ * 
+ * \f[SA = cos^{-1}\Big(\frac{{\sum_{b=1}^{n_{b}}}r(b)\cdot p(b)}{\sqrt{{\sum_{b=1}^{n_{b}}}r(b)^{2}{\sum_{b=1}^{n_{b}}p(b)^{2}}}}\Big) \f]
+ * with \f$b\f$ being the spectral band, \f$r\f$ the reference pixel and \f$p\f$ 
+ * the current pixel.
+ *
+ * Since the spectral angle deals with multi-bands image, the InputImage pixels are suposed to
+ * support the [] operator, and the input image to support the GetNumberOfComponentsPerPixel() method.
+ *
+ * \sa VectorImage
+ *
+ * This filter is implemented as a multithreaded filter.
+ *
+ * \ingroup IntensityImageFilters
+ * \ingroup Threading
+ * \ingroup Streamed
+ */
+template <class TInputImage,class TOutputImage>
+class ITK_EXPORT SpectralAngleDistanceImageFilter
+  : public itk::ImageToImageFilter<TInputImage,TOutputImage>
+{
+ public:
+  /** Standard typedefs */
+  typedef SpectralAngleDistanceImageFilter            Self;
+  typedef itk::ImageToImageFilter<TInputImage,TOutputImage> Superclass;
+  typedef itk::SmartPointer<Self>           Pointer;
+  typedef itk::SmartPointer<const Self>     ConstPointer;
+  
+  /** Type macro */
+  itkNewMacro(Self);
+  
+  /** Creation through object factory macro */
+  itkTypeMacro(SpectralAngleDistanceImageFilter,itk::ImageToImageFilter);
+  
+  /** Template parameters typedefs */
+  typedef TInputImage InputImageType;
+  typedef typename InputImageType::ConstPointer InputImageConstPointerType;
+  typedef typename InputImageType::RegionType InputImageRegionType;
+  typedef typename InputImageType::PixelType InputPixelType;
+  typedef TOutputImage OutputImageType;
+  typedef typename OutputImageType::Pointer OutputImagePointerType;
+  typedef typename OutputImageType::RegionType OutputImageRegionType;
+  typedef typename OutputImageType::PixelType OutputPixelType;
+  /** Get/Set the reference pixel */
+  itkGetConstReferenceMacro(ReferencePixel,InputPixelType);
+  itkSetMacro(ReferencePixel,InputPixelType);
+
+protected:
+  /** Constructor */
+  SpectralAngleDistanceImageFilter();
+  /** Destructor */
+  virtual ~SpectralAngleDistanceImageFilter() {};
+ /**PrintSelf method */
+  virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
+  /** SpectralAngleDistanceImageFilter can be implemented as a multithreaded filter.
+   * Therefore, this implementation provides a ThreadedGenerateData() routine
+   * which is called for each processing thread. The output image data is
+   * allocated automatically by the superclass prior to calling
+   * ThreadedGenerateData().  ThreadedGenerateData can only write to the
+   * portion of the output image specified by the parameter
+   * "outputRegionForThread"
+   *
+   * \sa ImageToImageFilter::ThreadedGenerateData(),
+   *     ImageToImageFilter::GenerateData()  */
+  void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                            int threadId );
+
+private:
+  SpectralAngleDistanceImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  /** The reference pixel */
+  InputPixelType m_ReferencePixel;
+};
+}// End namespace otb
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSpectralAngleDistanceImageFilter.txx"
+#endif
+
+#endif
diff --git a/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.txx b/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.txx
new file mode 100644
index 0000000000..1acc68aeac
--- /dev/null
+++ b/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.txx
@@ -0,0 +1,112 @@
+/*=========================================================================
+
+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 _otbSpectralAngleDistanceImageFilter_txx
+#define _otbSpectralAngleDistanceImageFilter_txx
+
+#include "otbSpectralAngleDistanceImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkProgressReporter.h"
+#include "otbMacro.h"
+
+namespace otb
+{
+/**
+ * Constructor
+ */
+template <class TInputImage, class TOutputImage>
+SpectralAngleDistanceImageFilter<TInputImage,TOutputImage>
+::SpectralAngleDistanceImageFilter()
+{
+  m_ReferencePixel=0;
+}
+template <class TInputImage, class TOutputImage>
+void
+SpectralAngleDistanceImageFilter<TInputImage,TOutputImage>
+::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,int threadId)
+{
+  
+  if (m_ReferencePixel == 0)
+    {
+      itkExceptionMacro(<<"Reference pixel is not set!");
+    }
+
+  InputImageConstPointerType  inputPtr = this->GetInput();
+  OutputImagePointerType outputPtr = this->GetOutput();
+
+  
+  // Define the portion of the input to walk for this thread, using
+  // the CallCopyOutputRegionToInputRegion method allows for the input
+  // and output images to be different dimensions
+  InputImageRegionType inputRegionForThread;
+  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
+
+  // Define the iterators
+  itk::ImageRegionConstIterator<InputImageType>  inputIt(inputPtr, inputRegionForThread);
+  itk::ImageRegionIterator<OutputImageType> outputIt(outputPtr, outputRegionForThread);
+  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+
+  inputIt.GoToBegin();
+  outputIt.GoToBegin();
+
+  while(!inputIt.IsAtEnd() && !outputIt.IsAtEnd()) 
+    {
+      double dist=0.0;
+      double scalarProd=0.0;
+      double normProd=0.0;
+      double normProd1=0.0;
+      double normProd2=0.0;
+      InputPixelType pixel = inputIt.Get();
+      for (int i=0; i<pixel.Size(); i++)
+	{
+	  scalarProd += pixel[i]*m_ReferencePixel[i];
+	  normProd1 += pixel[i]*pixel[i];
+	  normProd2 += m_ReferencePixel[i]*m_ReferencePixel[i];
+	}
+      normProd = normProd1 * normProd2;
+
+      if ( normProd == 0.0)
+	{
+	  dist = 0.0;
+	}
+      else
+	{
+	  dist = vcl_acos(scalarProd/vcl_sqrt(normProd));
+	}
+      // Spectral angle normalisation
+      dist = dist/(M_PI/2);
+   //ponderation par un carre
+   dist = sqrt(dist)*255;
+   outputIt.Set(static_cast<OutputPixelType>(dist));
+    ++inputIt;
+    ++outputIt;
+    progress.CompletedPixel();  // potential exception thrown here
+    }
+}
+/**
+ * PrintSelf Method
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpectralAngleDistanceImageFilter<TInputImage,TOutputImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+}
+} // End namespace otb
+#endif
diff --git a/Testing/Code/BasicFilters/CMakeLists.txt b/Testing/Code/BasicFilters/CMakeLists.txt
index 2515b6d46c..bb2a347c01 100755
--- a/Testing/Code/BasicFilters/CMakeLists.txt
+++ b/Testing/Code/BasicFilters/CMakeLists.txt
@@ -198,6 +198,22 @@ ADD_TEST(bfTvStreamingShrinkImageFilterQBMUL ${BASICFILTERS_TESTS}
 	            ${TEMP}/bfTvImportGeoInformationOutput.img
 )
 
+# -------            otb::SpectralAngleDistanceImageFilter   ----------------------------
+
+  ADD_TEST(bfTuSpectralAngleDistanceImageFilterNew ${BASICFILTERS_TESTS}  
+         otbSpectralAngleDistanceImageFilterNew)
+
+
+ ADD_TEST(bfTvSpectralAngleDistanceImageFilter ${BASICFILTERS_TESTS} 
+		--compare-image ${TOL}
+		    ${BASELINE}/bfTvSpectralAngleDistanceOutput.hdr
+		    ${TEMP}/bfTvSpectralAngleDistanceOutput.hdr
+		    otbSpectralAngleDistanceImageFilter
+		    ${INPUTDATA}/poupees.jpg
+	            ${TEMP}/bfTvSpectralAngleDistanceOutput.hdr
+		    210 432
+)
+
 # A enrichir
 SET(BasicFilters_SRCS
 otbLeeFilter.cxx
@@ -223,6 +239,8 @@ otbSpatialObjectToImageDrawingFilterNew.cxx
 otbSpatialObjectToImageDrawingFilter.cxx
 otbImportGeoInformationImageFilterNew.cxx
 otbImportGeoInformationImageFilter.cxx
+otbSpectralAngleDistanceImageFilterNew.cxx
+otbSpectralAngleDistanceImageFilter.cxx
 )
 
 
diff --git a/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx b/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx
index ad491acd74..3e6495c129 100755
--- a/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx
+++ b/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx
@@ -50,4 +50,6 @@ REGISTER_TEST(otbSpatialObjectToImageDrawingFilterNew);
 REGISTER_TEST(otbSpatialObjectToImageDrawingFilter);
 REGISTER_TEST(otbImportGeoInformationImageFilterNew);
 REGISTER_TEST(otbImportGeoInformationImageFilter);
+REGISTER_TEST(otbSpectralAngleDistanceImageFilterNew);
+REGISTER_TEST(otbSpectralAngleDistanceImageFilter);
 }
diff --git a/Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.cxx b/Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.cxx
new file mode 100644
index 0000000000..fdc5d90e1a
--- /dev/null
+++ b/Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilter.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 "itkExceptionObject.h"
+#include "otbImage.h"
+#include "otbVectorImage.h"
+#include "otbImageFileReader.h"
+#include "otbImageFileWriter.h"
+#include "otbSpectralAngleDistanceImageFilter.h"
+
+int otbSpectralAngleDistanceImageFilter(int argc, char * argv[])
+{
+  try
+    {
+      const unsigned int Dimension = 2;
+      typedef double PixelType;
+      typedef otb::VectorImage<PixelType,Dimension> InputImageType;
+      typedef otb::Image<PixelType,Dimension> OutputImageType;
+      typedef otb::ImageFileReader<InputImageType> ReaderType;
+      typedef otb::ImageFileWriter<OutputImageType> WriterType;
+      typedef otb::SpectralAngleDistanceImageFilter<InputImageType,OutputImageType> DistanceFilterType;
+
+      // Instantiating object
+      DistanceFilterType::Pointer filter = DistanceFilterType::New();
+      ReaderType::Pointer reader = ReaderType::New();
+      WriterType::Pointer writer = WriterType::New();
+      
+      reader->SetFileName(argv[1]);
+      writer->SetFileName(argv[2]);
+      
+      InputImageType::IndexType refPixelIndex;
+      refPixelIndex[0]=atoi(argv[3]);
+      refPixelIndex[1]=atoi(argv[4]);
+      
+      reader->Update();
+      filter->SetInput(reader->GetOutput());
+      filter->SetReferencePixel(reader->GetOutput()->GetPixel(refPixelIndex));
+
+      writer->SetInput(filter->GetOutput());
+
+      writer->Update();
+    }
+
+  catch( itk::ExceptionObject & err ) 
+    { 
+    std::cout << "Exception itk::ExceptionObject thrown !" << std::endl; 
+    std::cout << err << std::endl; 
+    return EXIT_FAILURE;
+    } 
+
+  catch( ... ) 
+    { 
+    std::cout << "Unknown exception thrown !" << std::endl; 
+    return EXIT_FAILURE;
+    } 
+  return EXIT_SUCCESS;
+}
diff --git a/Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilterNew.cxx b/Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilterNew.cxx
new file mode 100644
index 0000000000..02a9da54c6
--- /dev/null
+++ b/Testing/Code/BasicFilters/otbSpectralAngleDistanceImageFilterNew.cxx
@@ -0,0 +1,50 @@
+/*=========================================================================
+
+  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 "itkExceptionObject.h"
+#include "otbImage.h"
+#include "otbVectorImage.h"
+#include "otbSpectralAngleDistanceImageFilter.h"
+
+int otbSpectralAngleDistanceImageFilterNew(int argc, char * argv[])
+{
+  try
+    {
+      const unsigned int Dimension = 2;
+      typedef double PixelType;
+      typedef otb::VectorImage<PixelType,Dimension> InputImageType;
+      typedef otb::Image<PixelType,Dimension> OutputImageType;
+      typedef otb::SpectralAngleDistanceImageFilter<InputImageType,OutputImageType> DistanceFilterType;
+
+      // Instantiating object
+      DistanceFilterType::Pointer object = DistanceFilterType::New();
+    }
+
+  catch( itk::ExceptionObject & err ) 
+    { 
+    std::cout << "Exception itk::ExceptionObject thrown !" << std::endl; 
+    std::cout << err << std::endl; 
+    return EXIT_FAILURE;
+    } 
+
+  catch( ... ) 
+    { 
+    std::cout << "Unknown exception thrown !" << std::endl; 
+    return EXIT_FAILURE;
+    } 
+  return EXIT_SUCCESS;
+}
-- 
GitLab