From 592b8a3e455b6670a4c39102baa5117f74f1ec15 Mon Sep 17 00:00:00 2001
From: Cyrille Valladeau <cyrille.valladeau@c-s.fr>
Date: Tue, 10 Mar 2009 13:32:31 +0100
Subject: [PATCH] ENH : change in edge detection

---
 .../otbBinaryImageDensityFunction.h           |  46 +++---
 .../otbBinaryImageDensityFunction.txx         |   9 +-
 .../otbBinaryImageToDensityImageFilter.h      |  21 ++-
 .../otbBinaryImageToDensityImageFilter.txx    | 133 ++++++++++++++----
 Code/BasicFilters/otbEdgeDensityImageFilter.h |  14 +-
 .../otbEdgeDensityImageFilter.txx             |  54 ++-----
 6 files changed, 168 insertions(+), 109 deletions(-)

diff --git a/Code/BasicFilters/otbBinaryImageDensityFunction.h b/Code/BasicFilters/otbBinaryImageDensityFunction.h
index bff63bbaa8..9dd890d564 100644
--- a/Code/BasicFilters/otbBinaryImageDensityFunction.h
+++ b/Code/BasicFilters/otbBinaryImageDensityFunction.h
@@ -45,38 +45,29 @@ template <class TInputImage, class TCoordRep = float >
 class ITK_EXPORT BinaryImageDensityFunction :
   public itk::ImageFunction< TInputImage, typename itk::NumericTraits<typename TInputImage::PixelType>::RealType,TCoordRep >
 {
-public:
+  public:
   /** Standard class typedefs. */
   typedef BinaryImageDensityFunction                   Self;
   typedef itk::ImageFunction<TInputImage,typename itk::NumericTraits<typename TInputImage::PixelType>::RealType,
-    TCoordRep >                                        Superclass;
-  typedef itk::SmartPointer<Self>                       Pointer;
-  typedef itk::SmartPointer<const Self>                 ConstPointer;
+  TCoordRep >                                          Superclass;
+  typedef itk::SmartPointer<Self>                      Pointer;
+  typedef itk::SmartPointer<const Self>                ConstPointer;
   
   /** Run-time type information (and related methods). */
   itkTypeMacro(BinaryImageDensityFunction, itk::ImageFunction);
-
+  
   /** Method for creation through the object factory. */
   itkNewMacro(Self);
-
-  /** InputImageType typedef support. */
-  typedef TInputImage InputImageType;
-
-  /** OutputType typdef support. */
-  typedef typename Superclass::OutputType OutputType;
-
-  /** Index typedef support. */
-  typedef typename Superclass::IndexType IndexType;
   
-  /** ContinuousIndex typedef support. */
+  /** InputImageType typedef support. */
+  typedef TInputImage                              InputImageType;
+  typedef typename InputImageType::SizeType        RadiusType;
+  typedef typename Superclass::OutputType          OutputType;
+  typedef typename Superclass::IndexType           IndexType;
   typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
-
-  /** Point typedef support. */
-  typedef typename Superclass::PointType PointType;
-
-  /** Dimension of the underlying image. */
-itkStaticConstMacro(ImageDimension, unsigned int,
-		     InputImageType::ImageDimension);
+  typedef typename Superclass::PointType           PointType;
+  
+  itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension);
 
   /** Datatype used for the density */
   typedef typename itk::NumericTraits<typename InputImageType::PixelType>::RealType
@@ -102,8 +93,13 @@ itkStaticConstMacro(ImageDimension, unsigned int,
 
   /** Get/Set the radius of the neighborhood over which the
       statistics are evaluated */
-  itkSetMacro( NeighborhoodRadius, unsigned int );
-  itkGetConstReferenceMacro( NeighborhoodRadius, unsigned int );
+  itkSetMacro( NeighborhoodRadius, RadiusType );
+  itkGetConstReferenceMacro( NeighborhoodRadius, RadiusType );
+  void SetNeighborhoodRadius(unsigned int rad)
+  {
+    m_NeighborhoodRadius.Fill( rad );
+    this->Modified();
+  }
 
  
 protected:
@@ -115,7 +111,7 @@ private:
   BinaryImageDensityFunction( const Self& ); //purposely not implemented
   void operator=( const Self& ); //purposely not implemented
 
-  unsigned int m_NeighborhoodRadius;
+  RadiusType m_NeighborhoodRadius;
 
 };
 
diff --git a/Code/BasicFilters/otbBinaryImageDensityFunction.txx b/Code/BasicFilters/otbBinaryImageDensityFunction.txx
index faabc4abc3..6a992cc5d3 100644
--- a/Code/BasicFilters/otbBinaryImageDensityFunction.txx
+++ b/Code/BasicFilters/otbBinaryImageDensityFunction.txx
@@ -35,7 +35,7 @@ template <class TInputImage, class TCoordRep>
 BinaryImageDensityFunction<TInputImage,TCoordRep>
 ::BinaryImageDensityFunction()
 {
-  m_NeighborhoodRadius = 1;
+  m_NeighborhoodRadius.Fill( 1 );
 }
 
 
@@ -77,11 +77,10 @@ BinaryImageDensityFunction<TInputImage,TCoordRep>
      }
 
   // Create an N-d neighborhood kernel, using a zeroflux boundary condition
-   typename InputImageType::SizeType          kernelSize;
-   kernelSize.Fill( m_NeighborhoodRadius );
-  
+   typename InputImageType::SizeType   kernelSize = m_NeighborhoodRadius;
+
    itk::ConstNeighborhoodIterator<InputImageType>
-    it(kernelSize, this->GetInputImage(), this->GetInputImage()->GetBufferedRegion());
+     it(kernelSize, this->GetInputImage(), this->GetInputImage()->GetBufferedRegion());
 
    // Set the iterator at the desired location
    it.SetLocation(index);
diff --git a/Code/BasicFilters/otbBinaryImageToDensityImageFilter.h b/Code/BasicFilters/otbBinaryImageToDensityImageFilter.h
index b8abde1511..6e9564f4ce 100644
--- a/Code/BasicFilters/otbBinaryImageToDensityImageFilter.h
+++ b/Code/BasicFilters/otbBinaryImageToDensityImageFilter.h
@@ -20,6 +20,8 @@
 
 #include "itkImageToImageFilter.h"
 #include "itkDataObject.h"
+#include "itkConstNeighborhoodIterator.h"
+
 
 namespace otb
 {
@@ -48,6 +50,7 @@ public:
   typedef TInputImage                                          InputImageType;
   typedef typename InputImageType::RegionType                  InputImageRegionType;
   typedef typename InputImageType::Pointer                     InputImagePointerType;
+  typedef typename InputImageType::SizeType                    InputImageSizeType;
 
   typedef TOutputImage                                         OutputImageType;
   typedef typename OutputImageType::Pointer                    OutputImagePointerType;
@@ -55,16 +58,24 @@ public:
   typedef TCountFunction                                       CountFunctionType;
   typedef typename CountFunctionType::Pointer                  CountFunctionPointerType;
 
+  typedef itk::ConstNeighborhoodIterator<TInputImage>     NeighborhoodIteratorType;
+  typedef typename NeighborhoodIteratorType::RadiusType   RadiusType;
+
   /** Shrink factor accessor */
-  itkSetMacro(NeighborhoodRadius,unsigned int);
-  itkGetMacro(NeighborhoodRadius, unsigned int);
+  itkSetMacro(NeighborhoodRadius, RadiusType);
+  itkGetMacro(NeighborhoodRadius, RadiusType);
 
+  void SetNeighborhoodRadius(unsigned int rad)
+    {
+      m_NeighborhoodRadius.Fill(rad);
+      this->Modified();
+    }
 
 
   /** Main computation method */
-
   virtual void ThreadedGenerateData( const InputImageRegionType &outputRegionForThread, int threadId ) ;
-
+  virtual void BeforeThreadedGenerateData();
+  virtual void GenerateInputRequestedRegion();
 
 protected:
   /** Constructor */
@@ -81,7 +92,7 @@ private:
   CountFunctionPointerType    m_CountFunction;
 
   /** The shrink factor */
-  unsigned int m_NeighborhoodRadius;
+  RadiusType m_NeighborhoodRadius;
 
 };
 } // End namespace otb
diff --git a/Code/BasicFilters/otbBinaryImageToDensityImageFilter.txx b/Code/BasicFilters/otbBinaryImageToDensityImageFilter.txx
index 2a95dd2579..75691fe081 100644
--- a/Code/BasicFilters/otbBinaryImageToDensityImageFilter.txx
+++ b/Code/BasicFilters/otbBinaryImageToDensityImageFilter.txx
@@ -20,7 +20,12 @@
 
 #include "otbBinaryImageToDensityImageFilter.h"
 #include "itkImageRegionIterator.h"
-#include "itkImageRegionConstIterator.h"
+//#include "itkImageRegionConstIterator.h"
+#include "itkProgressReporter.h"
+#include "otbMirrorBoundaryCondition.h"
+#include "itkZeroFluxNeumannBoundaryCondition.h"
+#include "itkNeighborhoodAlgorithm.h"
+
 #include "otbMacro.h"
 
 namespace otb
@@ -30,11 +35,10 @@ template <class TInputImage, class TOutputImage, class TCountFunction>
 BinaryImageToDensityImageFilter<TInputImage, TOutputImage, TCountFunction>
 ::BinaryImageToDensityImageFilter()
 {
-  m_NeighborhoodRadius = 1;
-
+  m_NeighborhoodRadius.Fill( 1 );
   m_CountFunction = CountFunctionType::New();
-
 }
+
 /** Destructor */
 template <class TInputImage, class TOutputImage, class TCountFunction>
 BinaryImageToDensityImageFilter<TInputImage, TOutputImage, TCountFunction>
@@ -42,39 +46,119 @@ BinaryImageToDensityImageFilter<TInputImage, TOutputImage, TCountFunction>
 {}
 
 
+template <class TInputImage, class TOutputImage, class TCountFunction>
+void
+BinaryImageToDensityImageFilter<TInputImage, TOutputImage, TCountFunction>
+::GenerateInputRequestedRegion()
+{
+  // call the superclass' implementation of this method
+  Superclass::GenerateInputRequestedRegion();
+
+  // get pointers to the input and output
+  InputImagePointerType inputPtr = const_cast< TInputImage * >( this->GetInput());
+  OutputImagePointerType outputPtr = this->GetOutput();
+
+  if ( !inputPtr || !outputPtr )
+  {
+    return;
+  }
+  // get a copy of the input requested region (should equal the output
+  // requested region)
+  InputImageRegionType inputRequestedRegion = inputPtr->GetRequestedRegion();
+
+  // pad the input requested region by the operator radius
+  inputRequestedRegion.PadByRadius( m_NeighborhoodRadius );
+
+  // 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 << 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;
+  }
+}
+
+template <class TInputImage, class TOutputImage, class TCountFunction>
+void
+BinaryImageToDensityImageFilter<TInputImage, TOutputImage, TCountFunction>
+::BeforeThreadedGenerateData()
+{
+  Superclass::BeforeThreadedGenerateData();
+
+  m_CountFunction->SetInputImage(this->GetInput());
+  m_CountFunction->SetNeighborhoodRadius(m_NeighborhoodRadius);
+}
+
+
 /** Main computation method */
 template <class TInputImage, class TOutputImage, class TCountFunction>
 void
 BinaryImageToDensityImageFilter<TInputImage, TOutputImage, TCountFunction>
 ::ThreadedGenerateData( const InputImageRegionType &outputRegionForThread, int threadId )
 {
-  
-  InputImagePointerType    input = const_cast<InputImageType * > (this->GetInput());
-  OutputImagePointerType   output = this->GetOutput();
+  InputImagePointerType    inputPtr = const_cast<InputImageType * > (this->GetInput());
+  OutputImagePointerType   outputPtr = this->GetOutput();
 
-  m_CountFunction->SetInputImage(input);
+  itk::ZeroFluxNeumannBoundaryCondition<TInputImage> nbc;
+  RadiusType r;
+  r[0]=m_NeighborhoodRadius[0];
+  r[1]=m_NeighborhoodRadius[1];
 
-  itk::ImageRegionConstIterator<InputImageType>   it(input,outputRegionForThread );
-  itk::ImageRegionIterator<OutputImageType>   itOut(output,outputRegionForThread );
-  
-  it.GoToBegin();
-  itOut.GoToBegin();
-  
-  while(!it.IsAtEnd())
-    {
-      m_CountFunction->SetNeighborhoodRadius(m_NeighborhoodRadius);
-      typename InputImageType::IndexType index = it.GetIndex();
+  NeighborhoodIteratorType it;
+  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage>::FaceListType faceList;
+  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage> bC;
+  faceList = bC(inputPtr, outputRegionForThread, r);
+  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<TInputImage>::FaceListType::iterator fit;
+
+  itk::ImageRegionIterator<OutputImageType>     itOut(outputPtr,outputRegionForThread );
+
+  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+
+
+  typename InputImageType::IndexType index;
+ 
+  for (fit=faceList.begin(); fit != faceList.end(); ++fit)
+    { 
+      it = itk::ConstNeighborhoodIterator<TInputImage>(r, inputPtr, *fit);
+      
+      itOut = itk::ImageRegionIterator<TOutputImage>(outputPtr, *fit);
+      it.OverrideBoundaryCondition(&nbc);
+      it.GoToBegin();
       
-      if(outputRegionForThread.IsInside(index))
+      while(!itOut.IsAtEnd())
 	{
-	  itOut.Set(m_CountFunction->EvaluateAtIndex(index));
+	  index = it.GetIndex();
+	  
+	  if(outputRegionForThread.IsInside(index))
+	    {
+	      itOut.Set(m_CountFunction->EvaluateAtIndex(index));
+	    }
+	  
+	  ++itOut;
+	  ++it;
+	  progress.CompletedPixel(); // potential exception thrown here
 	}
-      
-      ++itOut;
-      ++it;
     }
 }
 
+  
 /** PrintSelf method */
 template <class TInputImage, class TOutputImage, class TCountFunction>
 void
@@ -82,8 +166,7 @@ BinaryImageToDensityImageFilter<TInputImage, TOutputImage, TCountFunction>
 ::PrintSelf(std::ostream& os, itk::Indent indent) const
 {
   Superclass::PrintSelf(os,indent);
-  os << indent << "Neighborhood Radius : " << m_NeighborhoodRadius
-  << std::endl;
+  os << indent << "Neighborhood Radius : " << m_NeighborhoodRadius << std::endl;
 }
 } // End namespace otb
 #endif
diff --git a/Code/BasicFilters/otbEdgeDensityImageFilter.h b/Code/BasicFilters/otbEdgeDensityImageFilter.h
index d56fa7945a..0f8e34e9c0 100644
--- a/Code/BasicFilters/otbEdgeDensityImageFilter.h
+++ b/Code/BasicFilters/otbEdgeDensityImageFilter.h
@@ -85,10 +85,11 @@ public:
   itkSetMacro( NeighborhoodRadius, unsigned int );
   itkGetConstReferenceMacro( NeighborhoodRadius, unsigned int );
 
+  /**Set/Get detector */
+  itkSetObjectMacro(Detector, DetectorType);
+  itkGetObjectMacro(Detector, DetectorType);
+  itkGetObjectMacro(DensityImageFilter, DensityImageType);
 
-  /**Set/Get Descriptor from the otbCountmageFunction*/
-  virtual void SetDetector(DetectorType* detector);
-  virtual DetectorType* GetDetector();
 
 protected:
 
@@ -107,7 +108,6 @@ protected:
   /**
    * Main computation method.
    */
-  //virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId );
   virtual void GenerateData( );
 
 private:
@@ -115,9 +115,9 @@ private:
   EdgeDensityImageFilter(const Self&); //purposely not implemented
   void operator=(const Self&); //purposely not implemented
 
-  DetectorPointerType                m_Detector;
-  DensityImagePointerType            m_DensityImageFilter;
-  unsigned int                       m_NeighborhoodRadius;
+  DetectorPointerType       m_Detector;
+  DensityImagePointerType   m_DensityImageFilter;
+  unsigned int              m_NeighborhoodRadius;
 };
 }
 #ifndef OTB_MANUAL_INSTANTIATION
diff --git a/Code/BasicFilters/otbEdgeDensityImageFilter.txx b/Code/BasicFilters/otbEdgeDensityImageFilter.txx
index bef73b4e34..e32dcb8526 100644
--- a/Code/BasicFilters/otbEdgeDensityImageFilter.txx
+++ b/Code/BasicFilters/otbEdgeDensityImageFilter.txx
@@ -29,7 +29,7 @@ namespace otb
 template <class TInputImage , class TOutputImage, class TEdgeDetector, class TDensityCount>
 EdgeDensityImageFilter<TInputImage, TOutputImage, TEdgeDetector, TDensityCount>
 ::EdgeDensityImageFilter()
-{
+{ 
   this->SetNumberOfRequiredInputs( 1 );
   
   m_NeighborhoodRadius = 1;
@@ -46,65 +46,35 @@ EdgeDensityImageFilter<TInputImage, TOutputImage, TEdgeDetector, TDensityCount>
 ::~EdgeDensityImageFilter()
 {}
 
+
 /**
  * threaded Generate Data
  */
-
-/**
-* ThreadedGenerateData Performs the pixel-wise addition
-*/
 template <class TInputImage , class TOutputImage, class TEdgeDetector, class TDensityCount>
 void
 EdgeDensityImageFilter<TInputImage, TOutputImage, TEdgeDetector, TDensityCount>
 ::GenerateData()
-  //::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, int threadId )
 {
-  typename Superclass::OutputImagePointer      outputImage = this->GetOutput();
-  InputImagePointerType ptr = const_cast<InputImageType *>(this->GetInput());
-  if (!ptr)
-    return ;
+  m_Detector->SetInput( this->GetInput() );
 
-  /** Apply Canny Detector*/
-  m_Detector->SetInput(ptr);
-  
+  std::cout<<"###"<<this->GetInput()->GetLargestPossibleRegion()<<std::endl; 
+  m_Detector->Update();
+  m_Detector->UpdateOutputInformation();
+  //m_Detector->SetRequestedRegionToLargestPossibleRegion();
+  std::cout<<"~~~"<<m_Detector->GetOutput()->GetLargestPossibleRegion()<<std::endl;
 
-  /** Compute density on the binaruzed Image */
-  m_DensityImageFilter->SetInput(m_Detector->GetOutput());
   m_DensityImageFilter->SetNeighborhoodRadius(m_NeighborhoodRadius);
+  m_DensityImageFilter->SetInput(m_Detector->GetOutput());
+
+  m_DensityImageFilter->UpdateOutputInformation();
+  std::cout<<"***"<<m_DensityImageFilter->GetOutput()->GetLargestPossibleRegion()<<std::endl;
 
-  /** updating the output*/
   m_DensityImageFilter->GraftOutput(this->GetOutput());
   m_DensityImageFilter->Update();
   this->GraftOutput(m_DensityImageFilter->GetOutput());
 }
 
 
-/**
- * Set Detector
- */
-template <class TInputImage , class TOutputImage, class TEdgeDetector, class TDensityCount>
-void
-EdgeDensityImageFilter<TInputImage, TOutputImage, TEdgeDetector, TDensityCount>
-::SetDetector(DetectorType* detector)
-{
-  m_Detector = detector;
-}
-
-
-/**
- * Get Detector
- */
-template <class TInputImage , class TOutputImage, class TEdgeDetector, class TDensityCount>
-typename EdgeDensityImageFilter<TInputImage, TOutputImage, TEdgeDetector, TDensityCount> 
-::DetectorType *
-EdgeDensityImageFilter<TInputImage, TOutputImage, TEdgeDetector, TDensityCount> 
-::GetDetector()
-{
-  return m_Detector;
-}
-
-
-
 /*----------------------------------------------------------------
   PrintSelf
   -----------------------------------------------------------------*/
-- 
GitLab