From 6359020bd1256a5847c70e714e0c5a70bd3bea2b Mon Sep 17 00:00:00 2001 From: Cyrille Valladeau <cyrille.valladeau@c-s.fr> Date: Fri, 5 Oct 2007 15:26:45 +0000 Subject: [PATCH] =?UTF-8?q?Cr=C3=A9ation=20d'une=20nouvelle=20th=C3=A9mati?= =?UTF-8?q?que=20:=20Fusion.=20Cr=C3=A9ation=20de=20la=20classe=20de=20bas?= =?UTF-8?q?e=20FusionBase.=20Cr=C3=A9ation=20de=20la=20classe=20de=20fusio?= =?UTF-8?q?n=20BayesianFusionImageFilter=20(contribution=20Julien=20Radoux?= =?UTF-8?q?)=20avec=20les=20classes=20MatrixTransposeMatrix=20et=20Streami?= =?UTF-8?q?ngStatisticsVectorImageFilter=20dans=20BasicFilter.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../otbMatrixTransposeMatrixImageFilter.h | 214 +++++++ .../otbMatrixTransposeMatrixImageFilter.txx | 374 ++++++++++++ .../otbStreamingStatisticsVectorImageFilter.h | 198 +++++++ ...tbStreamingStatisticsVectorImageFilter.txx | 554 ++++++++++++++++++ Code/CMakeLists.txt | 1 + Code/Fusion/CMakeLists.txt | 18 + Code/Fusion/foo.cxx | 0 Code/Fusion/otbBayesianFusionFilter.h | 278 +++++++++ Code/Fusion/otbBayesianFusionFilter.txx | 277 +++++++++ Code/Fusion/otbFusionImageBase.h | 119 ++++ Testing/Code/BasicFilters/CMakeLists.txt | 39 ++ .../BasicFilters/otbBasicFiltersTests.cxx | 4 + .../otbMatrixTransposeMatrixImageFilter.cxx | 86 +++ ...otbMatrixTransposeMatrixImageFilterNew.cxx | 59 ++ ...tbStreamingStatisticsVectorImageFilter.cxx | 77 +++ ...treamingStatisticsVectorImageFilterNew.cxx | 50 ++ Testing/Code/CMakeLists.txt | 1 + Testing/Code/Fusion/CMakeLists.txt | 62 ++ .../Code/Fusion/otbBayesianFusionFilter.cxx | 83 +++ .../Fusion/otbBayesianFusionFilterNew.cxx | 63 ++ Testing/Code/Fusion/otbFusionImageBaseNew.cxx | 86 +++ Testing/Code/Fusion/otbFusionTests.cxx | 34 ++ otbIncludeDirectories.cmake | 1 + 23 files changed, 2678 insertions(+) create mode 100644 Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.h create mode 100644 Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.txx create mode 100644 Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.h create mode 100644 Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.txx create mode 100755 Code/Fusion/CMakeLists.txt create mode 100644 Code/Fusion/foo.cxx create mode 100755 Code/Fusion/otbBayesianFusionFilter.h create mode 100755 Code/Fusion/otbBayesianFusionFilter.txx create mode 100755 Code/Fusion/otbFusionImageBase.h create mode 100644 Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx create mode 100644 Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilterNew.cxx create mode 100755 Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx create mode 100644 Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilterNew.cxx create mode 100755 Testing/Code/Fusion/CMakeLists.txt create mode 100755 Testing/Code/Fusion/otbBayesianFusionFilter.cxx create mode 100644 Testing/Code/Fusion/otbBayesianFusionFilterNew.cxx create mode 100644 Testing/Code/Fusion/otbFusionImageBaseNew.cxx create mode 100755 Testing/Code/Fusion/otbFusionTests.cxx diff --git a/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.h b/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.h new file mode 100644 index 0000000000..061ea7896d --- /dev/null +++ b/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.h @@ -0,0 +1,214 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.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 __otbMatrixTransposeMatrixImageFilter_h +#define __otbMatrixTransposeMatrixImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkNumericTraits.h" +#include "itkArray.h" +#include "itkSimpleDataObjectDecorator.h" +#include "otbStreamingTraits.h" +#include "itkImageRegionSplitter.h" +#include "itkVariableSizeMatrix.h" +#include "itkVariableLengthVector.h" + + +namespace otb { + + /** \class MatrixTransposeMatrixImageFilter + * \brief Compute \f[X^T.Y \f]. Allow a padding of ones. + * + * \f[X\f] and \f[Y\f] are the input images. + * The padding has the effect of adding a component filled with ones to the image + * + * \sa StreamingTraits + * \sa StatisticsImageFilter + * \ingroup MathematicalStatisticsImageFilters + */ + template<class TInputImage, class TInputImage2> + class ITK_EXPORT MatrixTransposeMatrixImageFilter : + public itk::ImageToImageFilter<TInputImage, TInputImage> + { + public: + /** Standard Self typedef */ + typedef MatrixTransposeMatrixImageFilter Self; + typedef itk::ImageToImageFilter<TInputImage,TInputImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(MatrixTransposeMatrixImageFilter, ImageToImageFilter); + + /** Image related typedefs. */ + // First Input + typedef TInputImage ImageType; + typedef typename TInputImage::Pointer InputImagePointer; + typedef typename TInputImage::RegionType RegionType; + typedef typename TInputImage::SizeType SizeType; + typedef typename TInputImage::IndexType IndexType; + typedef typename TInputImage::PixelType PixelType; + typedef typename TInputImage::InternalPixelType InternalPixelType; + + typedef typename TInputImage2::IndexType IndexType2; + typedef typename TInputImage2::PixelType PixelType2; + typedef typename TInputImage2::InternalPixelType InternalPixelType2; + + typedef StreamingTraits<TInputImage> StreamingTraitsType; + typedef StreamingMode StreamingModeType; + typedef itk::ImageRegionSplitter<itkGetStaticConstMacro(InputImageDimension)> SplitterType; + typedef typename SplitterType::Pointer SplitterPointer; + + itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension); + + + /** Streaming-related accessors */ + itkSetMacro(BufferMemorySize, unsigned long); + itkGetMacro(BufferMemorySize, unsigned long); + itkSetMacro(BufferNumberOfLinesDivisions, unsigned long); + itkGetMacro(BufferNumberOfLinesDivisions, unsigned long); + itkSetMacro(NumberOfStreamDivisions,unsigned long); + itkGetMacro(NumberOfStreamDivisions,unsigned long); + itkSetMacro(StreamingMode,StreamingModeType); + itkGetMacro(StreamingMode,StreamingModeType); + + + itkSetMacro(UsePadFirstInput,bool); + itkGetMacro(UsePadFirstInput,bool); + itkSetMacro(UsePadSecondInput,bool); + itkGetMacro(UsePadSecondInput,bool); + + + itkSetObjectMacro(RegionSplitter, SplitterType); + itkGetObjectMacro(RegionSplitter, SplitterType); + + /** Image related typedefs. */ + itkStaticConstMacro(ImageDimension, unsigned int, TInputImage::ImageDimension ); + + + + /** Type to use for computations. */ + // First Input + typedef typename itk::NumericTraits<InternalPixelType>::RealType RealType; + typedef itk::VariableLengthVector<RealType> RealPixelType; + + + /** Smart Pointer type to a DataObject. */ + typedef typename itk::DataObject::Pointer DataObjectPointer; + + /** Type of DataObjects used for scalar outputs */ + typedef typename itk::Array<long> ArrayLongPixelType; + typedef typename itk::VariableSizeMatrix<RealType> MatrixType; + typedef typename std::vector<MatrixType> ArrayMatrixType; + typedef typename std::vector<RealPixelType> ArrayRealPixelType; + typedef typename std::vector<PixelType> ArrayPixelType; + typedef itk::SimpleDataObjectDecorator<RealPixelType> RealPixelObjectType; + typedef itk::SimpleDataObjectDecorator<PixelType> PixelObjectType; + typedef itk::SimpleDataObjectDecorator<MatrixType> MatrixObjectType; + + + /** Return the computed transpose(Image1)*Image2. */ + MatrixType GetResult() const { return this->GetResultOutput()->Get(); }; + MatrixObjectType* GetResultOutput(); + const MatrixObjectType* GetResultOutput() const; + + + /** Make a DataObject of the correct type to be used as the specified + * output. + */ + virtual DataObjectPointer MakeOutput(unsigned int idx); + + /** Pass the input through unmodified. Do this by Grafting in the + * AllocateOutputs method. + */ + void AllocateOutputs(); + void GenerateOutputInformation(); + + + /** Input wrapper */ + void SetFirstInput(const TInputImage *input1){ this->SetInput(0, input1 ); }; + void SetSecondInput(const TInputImage2 *input2){ this->SetInput(1, input2 ); }; + + const TInputImage* GetFirstInput() + { + if( this->GetNumberOfInputs() < 1 ) + { + return 0; + } + else + return( static_cast<const TInputImage *>(this->itk::ProcessObject::GetInput(0)) ); + } + + const TInputImage2* GetSecondInput() + { + if( this->GetNumberOfInputs() < 2 ) + { + return 0; + } + else + return( static_cast<const TInputImage2 *>(this->itk::ProcessObject::GetInput(1)) ); + } + + protected: + MatrixTransposeMatrixImageFilter(); + ~MatrixTransposeMatrixImageFilter(){}; + void PrintSelf(std::ostream& os, itk::Indent indent) const; + /** Initialize some accumulators before the threads run. */ + virtual void BeforeThreadedGenerateData (); + /** Do final mean and variance computation from data accumulated in threads. */ + virtual void AfterThreadedGenerateData (); + /** Multi-thread version GenerateData. */ + virtual void ThreadedGenerateData (const RegionType& outputRegionForThread,int threadId); + // Override since the filter needs all the data for the algorithm + virtual void GenerateInputRequestedRegion(); + + private: + MatrixTransposeMatrixImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + ArrayMatrixType m_ThreadSum; + bool m_UsePadFirstInput; + bool m_UsePadSecondInput; + + /** Nulber Of Component per Pixel. Change for padding */ + unsigned int m_NumberOfComponents1; + unsigned int m_NumberOfComponents2; + + /** Use to define the method used to calculate number of divisions */ + unsigned long m_BufferMemorySize; + unsigned long m_BufferNumberOfLinesDivisions; + unsigned long m_NumberOfStreamDivisions; + + SplitterPointer m_RegionSplitter; + + /** Use to determine method of calculation number of divisions */ + StreamingModeType m_StreamingMode; + }; // end of class + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbMatrixTransposeMatrixImageFilter.txx" +#endif + +#endif diff --git a/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.txx b/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.txx new file mode 100644 index 0000000000..b6b5e8ee0d --- /dev/null +++ b/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.txx @@ -0,0 +1,374 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.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 _otbMatrixTransposeMatrixImageFilter_txx +#define _otbMatrixTransposeMatrixImageFilter_txx +#include "otbMatrixTransposeMatrixImageFilter.h" + +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIteratorWithIndex.h" +#include "itkNumericTraits.h" +#include "itkProgressReporter.h" + + +namespace otb { + +template<class TInputImage, class TInputImage2> +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::MatrixTransposeMatrixImageFilter() +{ + this->SetNumberOfRequiredInputs(2); + + // first output is a copy of the image, DataObject created by + // superclass + // + // allocate the data objects for the outputs which are + // just decorators around pixel types + + + typename ImageType::Pointer output1 = static_cast<ImageType*>(this->MakeOutput(0).GetPointer()); + this->itk::ProcessObject::SetNthOutput(0, output1.GetPointer()); + typename MatrixObjectType::Pointer output2 = static_cast<MatrixObjectType*>(this->MakeOutput(1).GetPointer()); + this->itk::ProcessObject::SetNthOutput(1, output2.GetPointer()); + + // false means no pad added + m_UsePadFirstInput = false; + m_UsePadSecondInput = false; + // Streaming initialization + m_BufferMemorySize = 0; + m_BufferNumberOfLinesDivisions = 0; + m_NumberOfStreamDivisions = 0; + // default to AUTOMATIC_NUMBER_OF_DIVISIONS + m_StreamingMode = SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS; + // create default region splitter + m_RegionSplitter = itk::ImageRegionSplitter<InputImageDimension>::New(); + + // Number of component initialisation + m_NumberOfComponents1 = 0; + m_NumberOfComponents2 = 0; +} + + +template<class TInputImage, class TInputImage2> +itk::DataObject::Pointer +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::MakeOutput(unsigned int output) +{ + switch (output) + { + case 0: + return static_cast<itk::DataObject*>(TInputImage::New().GetPointer()); + break; + case 1: + return static_cast<itk::DataObject*>(MatrixObjectType::New().GetPointer()); + break; + default: + // might as well make an image + return static_cast<itk::DataObject*>(TInputImage::New().GetPointer()); + break; + } + +} + + + +template<class TInputImage, class TInputImage2> +typename MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2>::MatrixObjectType* +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::GetResultOutput() +{ + return static_cast<MatrixObjectType*>(this->itk::ProcessObject::GetOutput(1)); +} + +template<class TInputImage, class TInputImage2> +const typename MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2>::MatrixObjectType* +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::GetResultOutput() const +{ + return static_cast<const MatrixObjectType*>(this->itk::ProcessObject::GetOutput(1)); +} + + +template<class TInputImage, class TInputImage2> +void +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::GenerateInputRequestedRegion() +{ + Superclass::GenerateInputRequestedRegion(); + if ( this->GetInput() ) + { + InputImagePointer image = const_cast< typename Superclass::InputImageType * >( this->GetFirstInput() ); + InputImagePointer image2 = const_cast< typename Superclass::InputImageType * >( this->GetSecondInput() ); + + IndexType index = image->GetLargestPossibleRegion().GetIndex(); + SizeType size; + size.Fill(0); + RegionType region; + region.SetSize(size); + region.SetIndex(index); + image->SetRequestedRegion(region); + + IndexType index2 = image2->GetLargestPossibleRegion().GetIndex(); + SizeType size2; + size2.Fill(0); + RegionType region2; + region2.SetSize(size2); + region2.SetIndex(index2); + image2->SetRequestedRegion(region2); + + } +} + +template<class TInputImage, class TInputImage2> +void +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::GenerateOutputInformation() +{ + Superclass::GenerateOutputInformation(); + if ( this->GetInput() ) + { + this->GetOutput()->CopyInformation(this->GetFirstInput()); + this->GetOutput()->SetLargestPossibleRegion(this->GetFirstInput()->GetLargestPossibleRegion()); + } +} + +template<class TInputImage, class TInputImage2> +void +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::AllocateOutputs() +{ + + // Pass the input through as the output + InputImagePointer image = const_cast< TInputImage * >( this->GetInput() ); + this->GraftOutput( image ); + // Nothing that needs to be allocated for the remaining outputs +} + +template<class TInputImage, class TInputImage2> +void +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::BeforeThreadedGenerateData() +{ + if(this->GetOutput()->GetRequestedRegion().GetNumberOfPixels()==0) + { + this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion()); + } + + if ( this->GetFirstInput()->GetLargestPossibleRegion().GetSize() != this->GetSecondInput()->GetLargestPossibleRegion().GetSize() ) + { + itkExceptionMacro( <<" Can't multiply the transposed matrix of a " + << this->GetFirstInput()->GetLargestPossibleRegion().GetSize() + << " and a " + << this->GetSecondInput()->GetLargestPossibleRegion().GetSize() + << " matrix " ); + } + + m_NumberOfComponents1 = this->GetFirstInput()->GetNumberOfComponentsPerPixel(); + m_NumberOfComponents2 = this->GetSecondInput()->GetNumberOfComponentsPerPixel(); + unsigned int numberOfThreads = this->GetNumberOfThreads(); + + if ( m_UsePadFirstInput == true ) + { + m_NumberOfComponents1++; + } + if ( m_UsePadSecondInput == true ) + { + m_NumberOfComponents2++; + } + + MatrixType tempMatrix, initMatrix; + tempMatrix.SetSize(m_NumberOfComponents1, m_NumberOfComponents2); + tempMatrix.Fill(itk::NumericTraits<RealType>::Zero); + m_ThreadSum = ArrayMatrixType(numberOfThreads, tempMatrix); + + initMatrix.SetSize(m_NumberOfComponents2, m_NumberOfComponents2); + initMatrix.Fill(itk::NumericTraits<RealType>::Zero); + this->GetResultOutput()->Set( initMatrix ); +} + + + + +template<class TInputImage, class TInputImage2> +void +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::AfterThreadedGenerateData() +{ + unsigned int numberOfThreads = this->GetNumberOfThreads(); + MatrixType resultMatrix; + resultMatrix.SetSize(m_NumberOfComponents1, m_NumberOfComponents2); + resultMatrix.Fill(itk::NumericTraits<RealType>::Zero); + + + for( unsigned int thread = 0; thread < numberOfThreads; thread++) + { + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * resultMatrix += m_ThreadSum[thread]; + **/ + for (unsigned int i=0; i<resultMatrix.Rows(); i++) + { + for (unsigned int j=0; j<resultMatrix.Cols(); j++) + { + resultMatrix(i, j) += m_ThreadSum[thread](i, j); + } + } + /********END TODO ******/ + } + this->GetResultOutput()->Set( resultMatrix ); +} + +template<class TInputImage, class TInputImage2> +void +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::ThreadedGenerateData(const RegionType& outputRegionForThread, int threadId) +{ + /** + * Grab the input + */ + + InputImagePointer input1Ptr = const_cast< TInputImage * >( this->GetFirstInput() ); + InputImagePointer input2Ptr = const_cast< TInputImage2 * >( this->GetSecondInput() ); + + // support progress methods/callbacks + itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + + // Here we will divide the input region into pieces to process one afther the other. + unsigned int numDivisions = static_cast<unsigned int>(StreamingTraitsType + ::CalculateNumberOfStreamDivisions(this->GetFirstInput(), + outputRegionForThread, + m_StreamingMode, + m_NumberOfStreamDivisions, + m_BufferMemorySize, + m_BufferNumberOfLinesDivisions)); + + + otbMsgDebugMacro(<<"ThreadedGeneraeData() - thread "<<threadId<<" - Thread region: "<<outputRegionForThread); + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId<<" - Streaming configuration: "<<m_StreamingMode<<" "<<m_NumberOfStreamDivisions<<" "<<m_BufferMemorySize<<" "<<m_BufferNumberOfLinesDivisions); + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId <<" - nb of divisions from StreamingTraits: "<<numDivisions); + + + unsigned int numDivisionsFromSplitter = m_RegionSplitter->GetNumberOfSplits(outputRegionForThread, numDivisions); + + + if (numDivisionsFromSplitter < numDivisions) + { + numDivisions = numDivisionsFromSplitter; + } + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId <<" - nb of divisions: "<<numDivisions); + + /* + unsigned int numberOfComponents1 = this->GetFirstInput()->GetNumberOfComponentsPerPixel(); + unsigned int numberOfComponents2 = this->GetSecondInput()->GetNumberOfComponentsPerPixel(); + + MatrixType result; + result.SetSize(numberOfComponents1, numberOfComponents2); + result.Fill(itk::NumericTraits<RealType>::Zero); + */ + + /** + * Loop over the number of pieces, execute the upstream pipeline on each + * piece, and copy the results into the output image. + */ + unsigned int piece; + for (piece = 0; + piece < numDivisions && !this->GetAbortGenerateData(); + piece++) + { + RegionType streamRegion = m_RegionSplitter->GetSplit(piece,numDivisions,outputRegionForThread); + + + input1Ptr->SetRequestedRegion(streamRegion); + input2Ptr->SetRequestedRegion(streamRegion); + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId <<" - streaming region: "<<streamRegion); + input1Ptr->PropagateRequestedRegion(); + input1Ptr->UpdateOutputData(); + input2Ptr->PropagateRequestedRegion(); + input2Ptr->UpdateOutputData(); + + itk::ImageRegionConstIteratorWithIndex<TInputImage> it1 (input1Ptr, streamRegion); + itk::ImageRegionConstIteratorWithIndex<TInputImage> it2 (input2Ptr, streamRegion); + it1.GoToBegin(); + it2.GoToBegin(); + + // loop the second image and get one pixel a time + while (!it1.IsAtEnd()) + { + //IndexType index1 = it1.GetIndex(); + PixelType vectorValue1 = it1.Get(); + //IndexType2 index2 = it2.GetIndex(); + PixelType2 vectorValue2 = it2.Get(); + + // Add a first component to vectorValue2 and vectorValue1 filled with ones. + if (m_UsePadFirstInput == true) + { + PixelType vectortemp1(vectorValue1.Size()+1); + vectortemp1[0] = 1; + for (unsigned int n=0; n<vectorValue1.Size(); n++) + { + vectortemp1[n+1] = vectorValue1[n]; + + } + vectorValue1.SetSize(vectortemp1.Size()); + vectorValue1 = vectortemp1; + } + + if (m_UsePadSecondInput == true) + { + PixelType2 vectortemp2(vectorValue2.Size()+1); + vectortemp2[0] = 1; + for (unsigned int m=0; m<vectorValue2.Size(); m++) + { + vectortemp2[m+1] = vectorValue2[m]; + + } + vectorValue2.SetSize(vectortemp2.Size()); + vectorValue2 = vectortemp2; + } + + for (unsigned int i=0; i<vectorValue1.Size(); i++) + { + for (unsigned int j=0; j<vectorValue2.Size(); j++) + { + m_ThreadSum[threadId](i, j) += vectorValue1[i]*static_cast<InternalPixelType>(vectorValue2[j]); + } + + } + ++it1; + ++it2; + progress.CompletedPixel(); + } + } + //otbMsgDebugMacro(<<"Leaving ThreadedGenerateData()"); +} + +template<class TInputImage, class TInputImage2> +void +MatrixTransposeMatrixImageFilter<TInputImage, TInputImage2> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os,indent); + + os << indent << "Result: " <<this->GetResultOutput()->Get()<< std::endl; +} + + +}// end namespace otb +#endif diff --git a/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.h b/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.h new file mode 100644 index 0000000000..9d3af2769e --- /dev/null +++ b/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.h @@ -0,0 +1,198 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.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 __otbStreamingStatisticsVectorImageFilter_h +#define __otbStreamingStatisticsVectorImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkNumericTraits.h" +#include "itkArray.h" +#include "itkSimpleDataObjectDecorator.h" +#include "otbStreamingTraits.h" +#include "itkImageRegionSplitter.h" +#include "itkVariableSizeMatrix.h" +#include "itkVariableLengthVector.h" + + +namespace otb { + +/** \class StreamingStatisticsVectorImageFilter + * \brief Compute min. max, covariance of a large image using streaming + * + * This filter Computes the same statistics as the StatisticsImageFilter, but it + * supports large image since it processes reasonnable pieces of the input image one + * afther the other. It supports the same streaming mode than the StreamingImageVectorFileWriter. + * + * Of course streaming at the end of a pipeline is only available when each filter in the pipeline + * supports streaming. This filter will also perform multithreading if possible. + * + * \note The output image has no sense at all and should not be used. + * + * \sa StreamingTraits + * \sa StreamingImageVectorFileWriter + * \sa StreamingImageFileWriter + * \sa StatisticsImageFilter + * \ingroup Streamed + * \ingroup Multithreaded + * \ingroup MathematicalStatisticsImageFilters + */ +template<class TInputImage> +class ITK_EXPORT StreamingStatisticsVectorImageFilter : + public itk::ImageToImageFilter<TInputImage, TInputImage> + { + public: + /** Standard Self typedef */ + typedef StreamingStatisticsVectorImageFilter Self; + typedef itk::ImageToImageFilter<TInputImage,TInputImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(StreamingStatisticsVectorImageFilter, ImageToImageFilter); + + /** Image related typedefs. */ + typedef typename TInputImage::Pointer InputImagePointer; + typedef typename TInputImage::RegionType RegionType; + typedef typename TInputImage::SizeType SizeType; + typedef typename TInputImage::IndexType IndexType; + typedef typename TInputImage::PixelType PixelType; + typedef typename TInputImage::InternalPixelType InternalPixelType; + typedef StreamingTraits<TInputImage> StreamingTraitsType; + typedef StreamingMode StreamingModeType; + typedef itk::ImageRegionSplitter<itkGetStaticConstMacro(InputImageDimension)> SplitterType; + typedef typename SplitterType::Pointer SplitterPointer; + + itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension); + + /** Streaming-related accessors */ + itkSetMacro(BufferMemorySize, unsigned long); + itkGetMacro(BufferMemorySize, unsigned long); + itkSetMacro(BufferNumberOfLinesDivisions, unsigned long); + itkGetMacro(BufferNumberOfLinesDivisions, unsigned long); + itkSetMacro(NumberOfStreamDivisions,unsigned long); + itkGetMacro(NumberOfStreamDivisions,unsigned long); + itkSetMacro(StreamingMode,StreamingModeType); + itkGetMacro(StreamingMode,StreamingModeType); + + itkSetObjectMacro(RegionSplitter, SplitterType); + itkGetObjectMacro(RegionSplitter, SplitterType); + + /** Image related typedefs. */ + itkStaticConstMacro(ImageDimension, unsigned int, TInputImage::ImageDimension ); + + /** Type to use for computations. */ + typedef typename itk::NumericTraits<InternalPixelType>::RealType RealType; + typedef itk::VariableLengthVector<RealType> RealPixelType; + + /** Smart Pointer type to a DataObject. */ + typedef typename itk::DataObject::Pointer DataObjectPointer; + + /** Type of DataObjects used for scalar outputs */ + typedef typename itk::VariableSizeMatrix<RealType> MatrixType; + typedef typename std::vector<MatrixType> ArrayMatrixType; + typedef typename itk::Array<long> ArrayLongPixelType; + typedef typename std::vector<RealPixelType> ArrayRealPixelType; + typedef typename std::vector<PixelType> ArrayPixelType; + typedef itk::SimpleDataObjectDecorator<RealPixelType> RealPixelObjectType; + typedef itk::SimpleDataObjectDecorator<PixelType> PixelObjectType; + typedef itk::SimpleDataObjectDecorator<MatrixType> MatrixObjectType; + + + /** Return the computed Minimum. */ + PixelType GetMinimum() const { return this->GetMinimumOutput()->Get(); }; + PixelObjectType* GetMinimumOutput(); + const PixelObjectType* GetMinimumOutput() const; + + /** Return the computed Maximum. */ + PixelType GetMaximum() const { return this->GetMaximumOutput()->Get(); }; + PixelObjectType* GetMaximumOutput(); + const PixelObjectType* GetMaximumOutput() const; + + /** Return the computed Mean. */ + RealPixelType GetMean() const { return this->GetMeanOutput()->Get(); }; + RealPixelObjectType* GetMeanOutput(); + const RealPixelObjectType* GetMeanOutput() const; + + /** Return the compute Sum. */ + RealPixelType GetSum() const { return this->GetSumOutput()->Get(); }; + RealPixelObjectType* GetSumOutput(); + const RealPixelObjectType* GetSumOutput() const; + + /** Return the computed Covariance. */ + MatrixType GetCovariance() const { return this->GetCovarianceOutput()->Get(); }; + MatrixObjectType* GetCovarianceOutput(); + const MatrixObjectType* GetCovarianceOutput() const; + + + /** Make a DataObject of the correct type to be used as the specified + * output. + */ + virtual DataObjectPointer MakeOutput(unsigned int idx); + + /** Pass the input through unmodified. Do this by Grafting in the + * AllocateOutputs method. + */ + void AllocateOutputs(); + void GenerateOutputInformation(); + + protected: + StreamingStatisticsVectorImageFilter(); + ~StreamingStatisticsVectorImageFilter(){}; + void PrintSelf(std::ostream& os, itk::Indent indent) const; + /** Initialize some accumulators before the threads run. */ + void BeforeThreadedGenerateData (); + /** Do final mean and variance computation from data accumulated in threads. */ + void AfterThreadedGenerateData (); + /** Multi-thread version GenerateData. */ + void ThreadedGenerateData (const RegionType& outputRegionForThread,int threadId); + // Override since the filter needs all the data for the algorithm + void GenerateInputRequestedRegion(); + + private: + StreamingStatisticsVectorImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + ArrayRealPixelType m_ThreadSum; + ArrayLongPixelType m_Count; + ArrayPixelType m_ThreadMin; + ArrayPixelType m_ThreadMax; + ArrayMatrixType m_XX; + + /** Use to define the method used to calculate number of divisions */ + unsigned long m_BufferMemorySize; + unsigned long m_BufferNumberOfLinesDivisions; + unsigned long m_NumberOfStreamDivisions; + + SplitterPointer m_RegionSplitter; + + /** Use to determine method of calculation number of divisions */ + StreamingModeType m_StreamingMode; + }; // end of class + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbStreamingStatisticsVectorImageFilter.txx" +#endif + +#endif diff --git a/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.txx b/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.txx new file mode 100644 index 0000000000..aef0e7f995 --- /dev/null +++ b/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.txx @@ -0,0 +1,554 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.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 _otbStreamingStatisticsVectorImageFilter_txx +#define _otbStreamingStatisticsVectorImageFilter_txx +#include "otbStreamingStatisticsVectorImageFilter.h" + +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIteratorWithIndex.h" +#include "itkNumericTraits.h" +#include "itkProgressReporter.h" + + +namespace otb { + +template<class TInputImage> +StreamingStatisticsVectorImageFilter<TInputImage> +::StreamingStatisticsVectorImageFilter() +{ + + // first output is a copy of the image, DataObject created by + // superclass + // + // allocate the data objects for the outputs which are + // just decorators around pixel types + + for (int i=1; i < 3; ++i) + { + typename PixelObjectType::Pointer output = static_cast<PixelObjectType*>(this->MakeOutput(i).GetPointer()); + this->itk::ProcessObject::SetNthOutput(i, output.GetPointer()); + } + + // allocate the data objects for the outputs which are + // just decorators around real types + + for (int i=3; i < 5; ++i) + { + typename RealPixelObjectType::Pointer output = static_cast<RealPixelObjectType*>(this->MakeOutput(i).GetPointer()); + this->itk::ProcessObject::SetNthOutput(i, output.GetPointer()); + } + + // allocate the data objects for the outputs which are + // just decorators around matrix types + typename MatrixObjectType::Pointer output = static_cast<MatrixObjectType*>(this->MakeOutput(5).GetPointer()); + this->itk::ProcessObject::SetNthOutput(5, output.GetPointer()); + + // Streaming initialization + m_BufferMemorySize = 0; + m_BufferNumberOfLinesDivisions = 0; + m_NumberOfStreamDivisions = 0; + // default to AUTOMATIC_NUMBER_OF_DIVISIONS + m_StreamingMode = SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS; + + // create default region splitter + m_RegionSplitter = itk::ImageRegionSplitter<InputImageDimension>::New(); + +} + + +template<class TInputImage> +itk::DataObject::Pointer +StreamingStatisticsVectorImageFilter<TInputImage> +::MakeOutput(unsigned int output) +{ + switch (output) + { + case 0: + return static_cast<itk::DataObject*>(TInputImage::New().GetPointer()); + break; + case 1: + case 2: + return static_cast<itk::DataObject*>(PixelObjectType::New().GetPointer()); + break; + case 3: + case 4: + return static_cast<itk::DataObject*>(RealPixelObjectType::New().GetPointer()); + break; + case 5: + return static_cast<itk::DataObject*>(MatrixObjectType::New().GetPointer()); + break; + default: + // might as well make an image + return static_cast<itk::DataObject*>(TInputImage::New().GetPointer()); + break; + } + +} + + +template<class TInputImage> +typename StreamingStatisticsVectorImageFilter<TInputImage>::PixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetMinimumOutput() +{ + return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(1)); +} + +template<class TInputImage> +const typename StreamingStatisticsVectorImageFilter<TInputImage>::PixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetMinimumOutput() const +{ + return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(1)); +} + + +template<class TInputImage> +typename StreamingStatisticsVectorImageFilter<TInputImage>::PixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetMaximumOutput() +{ + return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(2)); +} + +template<class TInputImage> +const typename StreamingStatisticsVectorImageFilter<TInputImage>::PixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetMaximumOutput() const +{ + return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(2)); +} + + +template<class TInputImage> +typename StreamingStatisticsVectorImageFilter<TInputImage>::RealPixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetMeanOutput() +{ + return static_cast<RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(3)); +} + +template<class TInputImage> +const typename StreamingStatisticsVectorImageFilter<TInputImage>::RealPixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetMeanOutput() const +{ + return static_cast<const RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(3)); +} + +template<class TInputImage> +typename StreamingStatisticsVectorImageFilter<TInputImage>::RealPixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetSumOutput() +{ + return static_cast<RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(4)); +} + +template<class TInputImage> +const typename StreamingStatisticsVectorImageFilter<TInputImage>::RealPixelObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetSumOutput() const +{ + return static_cast<const RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(4)); +} + +template<class TInputImage> +typename StreamingStatisticsVectorImageFilter<TInputImage>::MatrixObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetCovarianceOutput() +{ + return static_cast<MatrixObjectType*>(this->itk::ProcessObject::GetOutput(5)); +} + +template<class TInputImage> +const typename StreamingStatisticsVectorImageFilter<TInputImage>::MatrixObjectType* +StreamingStatisticsVectorImageFilter<TInputImage> +::GetCovarianceOutput() const +{ + return static_cast<const MatrixObjectType*>(this->itk::ProcessObject::GetOutput(5)); +} + + +template<class TInputImage> +void +StreamingStatisticsVectorImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + Superclass::GenerateInputRequestedRegion(); + if ( this->GetInput() ) + { + InputImagePointer image = const_cast< typename Superclass::InputImageType * >( this->GetInput() ); + IndexType index = image->GetLargestPossibleRegion().GetIndex(); + SizeType size; + size.Fill(0); + RegionType region; + region.SetSize(size); + region.SetIndex(index); + image->SetRequestedRegion(region); + } +} + +template<class TInputImage> +void +StreamingStatisticsVectorImageFilter<TInputImage> +::GenerateOutputInformation() +{ + Superclass::GenerateOutputInformation(); + if ( this->GetInput() ) + { + this->GetOutput()->CopyInformation(this->GetInput()); + this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion()); + } +} + +template<class TInputImage> +void +StreamingStatisticsVectorImageFilter<TInputImage> +::AllocateOutputs() +{ + + // Pass the input through as the output + InputImagePointer image = const_cast< TInputImage * >( this->GetInput() ); + this->GraftOutput( image ); + // Nothing that needs to be allocated for the remaining outputs +} + +template<class TInputImage> +void +StreamingStatisticsVectorImageFilter<TInputImage> +::BeforeThreadedGenerateData() +{ + if(this->GetOutput()->GetRequestedRegion().GetNumberOfPixels()==0) + { + this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion()); + } + + unsigned int numberOfThreads = this->GetNumberOfThreads(); + unsigned int numberOfComponent = this->GetInput()->GetNumberOfComponentsPerPixel(); + // Variable Initialisation + PixelType tempPixel; + tempPixel.SetSize(numberOfComponent); + tempPixel.Fill(itk::NumericTraits<InternalPixelType>::Zero); + this->GetMaximumOutput()->Set( tempPixel ); + + tempPixel.Fill(itk::NumericTraits<InternalPixelType>::max()); + this->GetMinimumOutput()->Set( tempPixel ); + + RealPixelType tempRealPixel; + tempRealPixel.SetSize(numberOfComponent); + tempRealPixel.Fill(itk::NumericTraits<RealType>::max()); + this->GetMeanOutput()->Set( tempRealPixel ); + + tempRealPixel.Fill(itk::NumericTraits<RealType>::Zero); + this->GetMeanOutput()->Set( tempRealPixel ); + + MatrixType tempMatrix; + tempMatrix.SetSize(numberOfComponent, numberOfComponent); + tempMatrix.Fill(itk::NumericTraits<RealType>::Zero); + + + // Initialize the tempories + m_Count.SetSize(numberOfThreads); + m_Count.Fill( itk::NumericTraits<long>::Zero ); + + PixelType tempTemporiesPixel; + tempTemporiesPixel.SetSize(numberOfComponent); + tempTemporiesPixel.Fill(itk::NumericTraits<InternalPixelType>::max()); + m_ThreadMin = ArrayPixelType(numberOfThreads, tempTemporiesPixel); + + tempTemporiesPixel.Fill(itk::NumericTraits<InternalPixelType>::Zero); + m_ThreadMax = ArrayPixelType(numberOfThreads, tempTemporiesPixel); + + RealPixelType tempTemporiesRealPixel; + tempTemporiesRealPixel.SetSize(numberOfComponent); + tempTemporiesRealPixel.Fill(itk::NumericTraits<RealType>::Zero); + m_ThreadSum = ArrayRealPixelType(numberOfThreads, tempTemporiesRealPixel); + + m_XX = ArrayMatrixType(numberOfThreads, tempMatrix); + + otbMsgDevMacro(<<"BeforeThreadedGenerateData() - output requested region: "<<this->GetOutput()->GetRequestedRegion()); + otbMsgDevMacro(<<"Leaving BeforeThreadedGenerateData() - nb threads: "<<numberOfThreads); +} + +template<class TInputImage> +void +StreamingStatisticsVectorImageFilter<TInputImage> +::AfterThreadedGenerateData() +{ + //otbMsgDebugMacro(<<"Entering AfterThreadedGenerateData()"); + int i; + long count; + + int numberOfThreads = this->GetNumberOfThreads(); + unsigned int numberOfComponent = this->GetInput()->GetNumberOfComponentsPerPixel(); + + PixelType minimumVector; + minimumVector.SetSize( numberOfComponent ); + minimumVector.Fill(itk::NumericTraits<InternalPixelType>::max()); + + PixelType maximumVector; + maximumVector.SetSize( numberOfComponent ); + maximumVector.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin()); + + RealPixelType sumVector; + sumVector.SetSize( numberOfComponent ); + sumVector.Fill(itk::NumericTraits<InternalPixelType>::Zero); + + RealPixelType meanVector; + meanVector.SetSize( numberOfComponent ); + MatrixType crossedMatrix; + crossedMatrix.SetSize(numberOfComponent,numberOfComponent); + crossedMatrix.Fill(itk::NumericTraits<RealType>::Zero); + count = 0; + + // Find the min/max over all threads and accumulate count, sum and + // sum of squares + for( i = 0; i < numberOfThreads; i++) + { + count += m_Count[i]; + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * crossedMatrix += m_XX[i]; + **/ + if( (m_XX[i].Rows() != crossedMatrix.Rows()) || (m_XX[i].Cols() != crossedMatrix.Cols())) + { + itkExceptionMacro( << "Matrix with size (" << m_XX[i].Rows() << "," << + m_XX[i].Cols() << ") cannot be subtracted from matrix with size (" << + crossedMatrix.Rows() << "," << crossedMatrix.Cols() ); + } + + for( unsigned int r=0; r<m_XX[i].Rows(); r++) + { + for( unsigned int c=0; c<m_XX[i].Cols(); c++ ) + { + crossedMatrix(r,c) += m_XX[i](r,c); + } + } + //**** END TODO **** + + for (unsigned int j=0; j<numberOfComponent; j++) + { + sumVector[j] += m_ThreadSum[i][j]; + if (m_ThreadMin[i][j] < minimumVector[j]) + { + minimumVector[j] = m_ThreadMin[i][j]; + } + if (m_ThreadMax[i][j] > maximumVector[j]) + { + maximumVector[j] = m_ThreadMax[i][j]; + } + } + } + for (unsigned int j=0; j<numberOfComponent; j++) + { + // compute statistics + meanVector[j] = sumVector[j] / static_cast<RealType>(count); + } + + // Compute Matrix Covariance + MatrixType pixelSumMatrix; + pixelSumMatrix.SetSize(static_cast<unsigned int>(numberOfComponent), 1); + pixelSumMatrix.Fill(itk::NumericTraits<RealType>::Zero); + for( unsigned int j = 0; j < numberOfComponent; j++) + { + pixelSumMatrix(j, 0) = sumVector[j]; + } + + MatrixType covMatrix, covMatrixTemp, tempTranspose; + covMatrix.SetSize(static_cast<unsigned int>(numberOfComponent), static_cast<unsigned int>(numberOfComponent)); + covMatrixTemp.SetSize(static_cast<unsigned int>(numberOfComponent), static_cast<unsigned int>(numberOfComponent)); + tempTranspose.SetSize(1, static_cast<unsigned int>(numberOfComponent)); + + covMatrix = crossedMatrix/static_cast<RealType>(count); + pixelSumMatrix/=static_cast<RealType>(count); + tempTranspose = pixelSumMatrix.GetTranspose(); + covMatrixTemp = pixelSumMatrix*tempTranspose; + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + *covMatrix -= covMatrixTemp; + **/ + if( (covMatrix.Rows() != covMatrixTemp.Rows()) || (covMatrix.Cols() != covMatrixTemp.Cols())) + { + itkExceptionMacro( << "Matrix with size (" << covMatrix.Rows() << "," << + covMatrix.Cols() << ") cannot be subtracted from matrix with size (" << + covMatrixTemp.Rows() << "," << covMatrixTemp.Cols() ); + } + + for( unsigned int r=0; r<covMatrix.Rows(); r++) + { + for( unsigned int c=0; c<covMatrix.Cols(); c++ ) + { + covMatrix(r,c) -= covMatrixTemp(r,c); + } + } + //**** END TODO ****/ + + // Set the outputs + this->GetMinimumOutput()->Set( minimumVector ); + this->GetMaximumOutput()->Set( maximumVector ); + this->GetMeanOutput()->Set( meanVector ); + this->GetSumOutput()->Set( sumVector); + this->GetCovarianceOutput()->Set( covMatrix ); + + //otbMsgDebugMacro(<<"Leaving AfterThreadedGenerateData()"); +} + +template<class TInputImage> +void +StreamingStatisticsVectorImageFilter<TInputImage> +::ThreadedGenerateData(const RegionType& outputRegionForThread, int threadId) +{ + //otbMsgDebugMacro(<<"Entering ThreadedGenerateData()"); + /** + * Grab the input + */ + + InputImagePointer inputPtr = const_cast< TInputImage * >( this->GetInput(0) ); + + + // support progress methods/callbacks + itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + + // Here we will divide the input region into pieces to process one afther the other. + unsigned int numDivisions = static_cast<unsigned int>(StreamingTraitsType + ::CalculateNumberOfStreamDivisions(this->GetInput(), + outputRegionForThread, + m_StreamingMode, + m_NumberOfStreamDivisions, + m_BufferMemorySize, + m_BufferNumberOfLinesDivisions)); // calcul en combien fau diviser idealement l'image + + otbMsgDebugMacro(<<"ThreadedGeneraeData() - thread "<<threadId <<" - Thread region: "<<outputRegionForThread); + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId<<" - Streaming configuration: "<<m_StreamingMode<<" "<<m_NumberOfStreamDivisions<<" "<<m_BufferMemorySize<<" "<<m_BufferNumberOfLinesDivisions); + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId <<" - nb of divisions from StreamingTraits: "<<numDivisions); + + unsigned int numDivisionsFromSplitter = m_RegionSplitter->GetNumberOfSplits(outputRegionForThread, numDivisions); + if (numDivisionsFromSplitter < numDivisions) + { + numDivisions = numDivisionsFromSplitter; + } + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId <<" - nb of divisions: "<<numDivisions); + + + MatrixType pixelVector, pixelTransposeVector, pixelSumVector, tempMatrix; + + pixelVector.SetSize(this->GetInput()->GetNumberOfComponentsPerPixel(), 1); + pixelVector.Fill(itk::NumericTraits<RealType>::Zero); + pixelTransposeVector.SetSize(1, this->GetInput()->GetNumberOfComponentsPerPixel()); + pixelTransposeVector.Fill(itk::NumericTraits<RealType>::Zero); + pixelSumVector.SetSize(this->GetInput()->GetNumberOfComponentsPerPixel(), this->GetInput()->GetNumberOfComponentsPerPixel()); + pixelSumVector.Fill(itk::NumericTraits<RealType>::Zero); + tempMatrix.SetSize(this->GetInput()->GetNumberOfComponentsPerPixel(), this->GetInput()->GetNumberOfComponentsPerPixel()); + + /** + * Loop over the number of pieces, execute the upstream pipeline on each + * piece, and copy the results into the output image. + */ + unsigned int piece; + for (piece = 0; + piece < numDivisions && !this->GetAbortGenerateData(); + piece++) + { + //otbMsgDebugMacro(<<"ThreadedGenerateData() - processing piece: "<<piece<<"/"<<numDivisions); + RegionType streamRegion = m_RegionSplitter->GetSplit(piece,numDivisions,outputRegionForThread); + //otbMsgDebugMacro(<<"ThreadedGenerateData() - piece region: "<<streamRegion); + + inputPtr->SetRequestedRegion(streamRegion); + otbMsgDebugMacro(<<"ThreadedGenerateData() - thread "<<threadId <<" - streaming region: "<<streamRegion); + inputPtr->PropagateRequestedRegion(); + inputPtr->UpdateOutputData(); + + + + itk::ImageRegionConstIteratorWithIndex<TInputImage> it (inputPtr, streamRegion); + it.GoToBegin(); + // do the work + while (!it.IsAtEnd()) + { + + IndexType index = it.GetIndex(); + PixelType vectorValue = it.Get(); + for (unsigned int j=0; j<vectorValue.GetSize(); j++) + { + InternalPixelType value = vectorValue[j]; + + RealType realValue = static_cast<RealType>( value ); + if (value < m_ThreadMin[threadId][j]) + { + m_ThreadMin[threadId][j] = value; + } + if (value > m_ThreadMax[threadId][j]) + { + m_ThreadMax[threadId][j] = value; + } + m_ThreadSum[threadId][j] += realValue; + pixelVector(j, 0) = realValue; + } + + ++it; + progress.CompletedPixel(); + pixelTransposeVector = pixelVector.GetTranspose(); + + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * m_XX[threadId]+=pixelVector*pixelTransposeVector; + **/ + tempMatrix = pixelVector*pixelTransposeVector; + if( (m_XX[threadId].Rows() != tempMatrix.Rows()) || (m_XX[threadId].Cols() != tempMatrix.Cols())) + { + itkExceptionMacro( << "Matrix with size (" << m_XX[threadId].Rows() << "," << + m_XX[threadId].Cols() << ") cannot be subtracted from matrix with size (" << + tempMatrix.Rows() << "," << tempMatrix.Cols() ); + } + + for( unsigned int r=0; r<m_XX[threadId].Rows(); r++) + { + for( unsigned int c=0; c<m_XX[threadId].Cols(); c++ ) + { + m_XX[threadId](r,c) += tempMatrix(r,c); + } + } + //**** END TODO **** + m_Count[threadId]++; + } + } + + //otbMsgDebugMacro(<<"Leaving ThreadedGenerateData()"); +} + +template <class TImage> +void +StreamingStatisticsVectorImageFilter<TImage> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os,indent); + + os << indent << "Minimum: " <<this->GetMinimumOutput()->Get()<< std::endl; + os << indent << "Maximum: "<< this->GetMaximumOutput()->Get() << std::endl; + os << indent << "Sum: " << this->GetSumOutput()->Get() << std::endl; + os << indent << "Mean: " << this->GetMeanOutput()->Get() << std::endl; + os << indent << "Covariance: " << this->GetCovarianceOutput()->Get() << std::endl; + +} + + +}// end namespace otb +#endif diff --git a/Code/CMakeLists.txt b/Code/CMakeLists.txt index d493a648f8..167aaa0451 100644 --- a/Code/CMakeLists.txt +++ b/Code/CMakeLists.txt @@ -10,6 +10,7 @@ DisparityMap SpatialReasoning Projections Radiometry +Fusion ) IF(OTB_USE_VISU_GUI) diff --git a/Code/Fusion/CMakeLists.txt b/Code/Fusion/CMakeLists.txt new file mode 100755 index 0000000000..004e778918 --- /dev/null +++ b/Code/Fusion/CMakeLists.txt @@ -0,0 +1,18 @@ +# Sources of non-templated classes. + +FILE(GLOB OTBFusion_SRCS "*.cxx" ) + +ADD_LIBRARY(OTBFusion ${OTBFusion_SRCS}) +TARGET_LINK_LIBRARIES (OTBFusion ITKCommon) + +INSTALL(TARGETS OTBFusion +RUNTIME DESTINATION ${OTB_INSTALL_BIN_DIR} COMPONENT RuntimeLibraries +LIBRARY DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries +ARCHIVE DESTINATION ${OTB_INSTALL_LIB_DIR} COMPONENT Development) + +FILE(GLOB __files1 "${CMAKE_CURRENT_SOURCE_DIR}/*.h") +FILE(GLOB __files2 "${CMAKE_CURRENT_SOURCE_DIR}/*.txx") + +INSTALL(FILES ${__files1} ${__files2} + DESTINATION ${OTB_INSTALL_INCLUDE_DIR}/Fusion + COMPONENT Development) diff --git a/Code/Fusion/foo.cxx b/Code/Fusion/foo.cxx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Code/Fusion/otbBayesianFusionFilter.h b/Code/Fusion/otbBayesianFusionFilter.h new file mode 100755 index 0000000000..68e76858b9 --- /dev/null +++ b/Code/Fusion/otbBayesianFusionFilter.h @@ -0,0 +1,278 @@ +/*========================================================================= + + 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 code is from a Julien Radoux contribution. + + Some parts of this code are derived from ITK. See ITKCopyright.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 __otbBayesianFusionFilter_h +#define __otbBayesianFusionFilter_h + +#include "itkImageToImageFilter.h" +#include "otbVectorImage.h" +#include "itkNumericTraits.h" +#include "otbStreamingStatisticsVectorImageFilter.h" +#include "otbFusionImageBase.h" +#include "otbMatrixTransposeMatrixImageFilter.h" +#include "otbImageToVectorImageCastFilter.h" +#include "itkVariableSizeMatrix.h" + + +namespace otb +{ + namespace Functor + { + template <class TInputMultiSpectral, + class TInputMultiSpectralInterp, + class TInputPanchro, + class TOutput> + class BayesianFunctor + { + public: + BayesianFunctor() {}; + ~BayesianFunctor() {}; + typedef typename TInputMultiSpectral::RealValueType RealType; + typedef typename itk::VariableSizeMatrix<RealType> MatrixType; + + void SetLambda(float lambda){ m_Lambda = lambda;}; + void SetS(float S){ m_S = S;}; + void SetAlpha(float alpha){ m_Alpha = alpha;}; + void SetBeta(MatrixType matrix){ m_Beta = matrix;}; + void SetCovarianceInvMatrix(MatrixType matrix){ m_CovarianceInvMatrix = matrix;}; + void SetVcondopt(MatrixType matrix){ m_Vcondopt = matrix;}; + float GetLambda(){ return m_Lambda;}; + float GetAlpha(){ return m_Alpha;}; + float GetS(){ return m_S;}; + MatrixType GetBeta(){ return m_Beta;}; + MatrixType GetCovarianceInvMatrix(){ return m_CovarianceInvMatrix;}; + MatrixType GetVcondopt(){ return m_Vcondopt;}; + + + + inline TOutput operator() (const TInputMultiSpectral & ms, const TInputMultiSpectralInterp & msi, const TInputPanchro & p) + { + TOutput obs; + obs.SetSize(msi.GetSize()); + MatrixType obsMat, msiVect; + obsMat.SetSize(1, obs.GetSize()); + msiVect.SetSize(1, msi.GetSize()); + for (unsigned int i=0; i<msi.GetSize();i++) + { + msiVect(0, i) = msi[i]; + } + obsMat = msiVect*m_CovarianceInvMatrix; + obsMat *= 2*(1-m_Lambda); + MatrixType PanVect; + PanVect = m_Beta.GetTranspose(); + PanVect *= (p-m_Alpha); + PanVect /= m_S; + PanVect *= 2*m_Lambda; + + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * obsMat += PanVect; + **/ + if( (obsMat.Cols() != PanVect.Cols()) || (obsMat.Rows() != PanVect.Rows()) ) + { + itkGenericExceptionMacro( << "Matrix with size (" << obsMat.Rows() << "," << + obsMat.Cols() << ") cannot be subtracted from matrix with size (" << + PanVect.Rows() << "," << PanVect.Cols() << " )" ); + } + + for( unsigned int r=0; r<obsMat.Rows(); r++) + { + for( unsigned int c=0; c<obsMat.Cols(); c++ ) + { + obsMat(r,c) += PanVect(r,c); + } + } + //**** END TODO ****/ + obsMat *= m_Vcondopt; + for (unsigned int i=0; i<obs.GetSize();i++) + { + obs[i] = obsMat(0,i); + } + return obs; + } + + private: + float m_Lambda; + float m_S; + float m_Alpha; + MatrixType m_CovarianceInvMatrix; + MatrixType m_Beta; + MatrixType m_Vcondopt; + }; + } + + /***** TODO *** + * Complete the description with J. Radoux text + */ + /***** END TODO ***/ + + /** \class StreamingStatisticsVectorImageFilter + * \brief Baesian fusion filter. Contribution of Julien Radoux + * + * + * \sa FusionImageBase + * \sa MatrixTransposeMatrix + * \sa StreamingStatisticsVectorImageFilter + * \ingroup Streamed + * \ingroup Multithreaded + * \ingroup MathematicalStatisticsImageFilters + */ + + + + +template <class TInputMultiSpectralImage, + class TInputMultiSpectralInterpImage, + class TInputPanchroImage, + class TOutputImage> +class ITK_EXPORT BayesianFusionFilter + : public FusionImageBase<TInputMultiSpectralImage, + TInputMultiSpectralInterpImage, + TInputPanchroImage, + TOutputImage, + Functor::BayesianFunctor<ITK_TYPENAME TInputMultiSpectralImage::PixelType, + ITK_TYPENAME TInputMultiSpectralInterpImage::PixelType, + ITK_TYPENAME TInputPanchroImage::PixelType, + ITK_TYPENAME TOutputImage::PixelType> > +{ +public: +/** Extract input and output images dimensions.*/ + itkStaticConstMacro( InputImageDimension, unsigned int, TInputMultiSpectralImage::ImageDimension); + itkStaticConstMacro( OutputImageDimension, unsigned int, TOutputImage::ImageDimension); + + /** "typedef" to simplify the variables definition and the declaration. */ + typedef TInputMultiSpectralImage InputMultiSpectralImageType; + typedef TInputMultiSpectralInterpImage InputMultiSpectralInterpImageType; + typedef TInputPanchroImage InputPanchroImageType; + typedef TOutputImage OutputImageType; + + + + /** "typedef" for standard classes. */ + typedef BayesianFusionFilter Self; + typedef FusionImageBase< InputMultiSpectralImageType, + InputMultiSpectralInterpImageType, + InputPanchroImageType, + OutputImageType, + Functor::BayesianFunctor<ITK_TYPENAME InputMultiSpectralImageType::PixelType, + ITK_TYPENAME InputMultiSpectralInterpImageType::PixelType, + ITK_TYPENAME InputPanchroImageType::PixelType, + ITK_TYPENAME OutputImageType::PixelType> > Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** object factory method. */ + itkNewMacro(Self); + + /** return class name. */ + itkTypeMacro(BayesianFusionFilter, FusionImageBase); + + /** Supported images definition. */ + typedef typename InputMultiSpectralImageType::PixelType InputMultiSpectralPixelType; + typedef typename InputMultiSpectralImageType::InternalPixelType InputMultiSpectralInternalPixelType; + typedef typename InputMultiSpectralInterpImageType::PixelType InputMultiSpectralInterpPixelType; + typedef typename InputMultiSpectralInterpImageType::InternalPixelType InputMultiSpectralInterpInternalPixelType; + typedef typename InputPanchroImageType::PixelType InputPanchroPixelType; + typedef typename OutputImageType::PixelType OutputPixelType; + typedef typename OutputImageType::InternalPixelType OutputInternalPixelType; + + /** Real class typedef definition. */ + typedef typename itk::NumericTraits<InputPanchroPixelType>::RealType InputPanchroRealType; + typedef typename itk::NumericTraits<InputMultiSpectralInternalPixelType>::RealType InputMultiSpectralRealType; + typedef typename InputMultiSpectralImageType::RegionType InputMultiSpectralImageRegionType; + typedef typename itk::NumericTraits<InputMultiSpectralInterpInternalPixelType>::RealType InputMultiSpectralInterpRealType; + typedef typename InputMultiSpectralInterpImageType::RegionType InputMultiSpectralInterpImageRegionType; + typedef typename InputPanchroImageType::RegionType InputPanchroImageRegionType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + + /** Image size "typedef" definition. */ + typedef typename InputMultiSpectralImageType::SizeType SizeType; + + + /** Typedef for statistic computing. */ + typedef StreamingStatisticsVectorImageFilter<InputMultiSpectralImageType> StreamingStatisticsVectorImageFilterType; + typedef typename StreamingStatisticsVectorImageFilterType::MatrixType MatrixType; + typedef MatrixTransposeMatrixImageFilter<InputMultiSpectralImageType, InputMultiSpectralImageType> MSTransposeMSType; + typedef ImageToVectorImageCastFilter<InputPanchroImageType, InputMultiSpectralImageType> CasterType; + + + /** Set the ponderation value. */ + itkSetMacro(Lambda, float); + /** Give the ponderation value. */ + itkGetConstReferenceMacro(Lambda, float); + + /** Set the Beta matrix. */ + itkSetMacro(Beta, MatrixType); + /** Give the Beta matrix. */ + itkGetConstReferenceMacro(Beta, MatrixType); + + /** Set the Covariance matrix. */ + itkSetMacro(CovarianceMatrix, MatrixType); + /** Give the Covariance matrix. */ + itkGetConstReferenceMacro(CovarianceMatrix, MatrixType); + + /** Set the Covariance inverse matrix. */ + itkSetMacro(CovarianceInvMatrix, MatrixType); + /** Give the Covariance inverse matrix. */ + itkGetConstReferenceMacro(CovarianceInvMatrix, MatrixType); + + /** Set the Bayesian Data Fusion matrix. */ + itkSetMacro(Vcondopt, MatrixType); + /** Give the Bayesian Data Fusion matrix. */ + itkGetConstReferenceMacro(Vcondopt, MatrixType); + + /** Set the S coefficient. */ + itkSetMacro(S, float); + /** Give the S coefficient. */ + itkGetConstReferenceMacro(S, float); + + +protected: + BayesianFusionFilter(); + virtual ~BayesianFusionFilter(); + /** Initialize some accumulators before the threads run. */ + void BeforeThreadedGenerateData (); + + +private: + /** Ponderation declaration*/ + float m_Lambda; + float m_S; + /** Multispectral covariance matrix */ + MatrixType m_CovarianceMatrix; + /** Multispectral inverse covariance matrix */ + MatrixType m_CovarianceInvMatrix; + /** Regression coefficients matrix */ + MatrixType m_Beta; + /** Optimisation matrix */ + MatrixType m_Vcondopt; + +}; + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbBayesianFusionFilter.txx" +#endif + +#endif diff --git a/Code/Fusion/otbBayesianFusionFilter.txx b/Code/Fusion/otbBayesianFusionFilter.txx new file mode 100755 index 0000000000..60f991d370 --- /dev/null +++ b/Code/Fusion/otbBayesianFusionFilter.txx @@ -0,0 +1,277 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.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 "otbBayesianFusionFilter.h" + + + +namespace otb +{ + + template <class TInputMultiSpectralImage, + class TInputMultiSpectralInterpImage, + class TInputPanchroImage, + class TOutputImage> + BayesianFusionFilter<TInputMultiSpectralImage, + TInputMultiSpectralInterpImage, + TInputPanchroImage, + TOutputImage> + ::BayesianFusionFilter() + { + m_Lambda = 0.9999; + m_S = 1; + } + + + template <class TInputMultiSpectralImage, + class TInputMultiSpectralInterpImage, + class TInputPanchroImage, + class TOutputImage> + BayesianFusionFilter<TInputMultiSpectralImage, + TInputMultiSpectralInterpImage, + TInputPanchroImage, + TOutputImage> + ::~BayesianFusionFilter() + { + + } + + + template <class TInputMultiSpectralImage, + class TInputMultiSpectralInterpImage, + class TInputPanchroImage, + class TOutputImage> + void + BayesianFusionFilter<TInputMultiSpectralImage, + TInputMultiSpectralInterpImage, + TInputPanchroImage, + TOutputImage> + ::BeforeThreadedGenerateData () + { + // Allocate output + typename OutputImageType::Pointer output = this->GetOutput(); + typename InputMultiSpectralImageType::ConstPointer multiSpec = this->GetMultiSpect(); + typename InputMultiSpectralInterpImageType::ConstPointer multiSpecInterp = this->GetMultiSpectInterp(); + typename InputPanchroImageType::ConstPointer panchro = this->GetPanchro(); + + /** Variable Initialisaton */ + m_Beta.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel()+1, 1); + m_Beta.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero); + + m_CovarianceMatrix.SetSize( multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel() ); + m_CovarianceMatrix.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero); + + m_CovarianceInvMatrix.SetSize( multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel() ); + m_CovarianceInvMatrix.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero); + + m_Vcondopt.SetSize( multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel() ); + m_Vcondopt.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero); + + + /** Compute the inverse of the multispectral interpolated image covariance matrix */ + typename StreamingStatisticsVectorImageFilterType::Pointer covComputefilter = StreamingStatisticsVectorImageFilterType::New(); + covComputefilter->SetInput(multiSpecInterp); + covComputefilter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); + covComputefilter->SetNumberOfStreamDivisions(200); + covComputefilter->Update(); + MatrixType m_CovarianceMatrix = covComputefilter->GetCovariance(); + m_CovarianceInvMatrix = m_CovarianceMatrix.GetInverse(); + + /** Beta computation : Regression model coefficient */ + // MatrixTransform only support vectorimage input + typename CasterType::Pointer caster = CasterType::New(); + caster->SetInput(panchro); + caster->Update(); + // Compute the transpose multispectral image multiplied by itself + typename MSTransposeMSType::Pointer msTransposeMs = MSTransposeMSType::New(); + // Compute the transpose multispectral image multiplied by the panchromatic one + typename MSTransposeMSType::Pointer msTransposePan = MSTransposeMSType::New(); + + // Add a dimension filled with ones to the images + msTransposeMs->SetUsePadFirstInput(true); + msTransposeMs->SetUsePadSecondInput(true); + msTransposePan->SetUsePadFirstInput(true); + + msTransposeMs->SetFirstInput(multiSpec); + msTransposeMs->SetSecondInput(multiSpec); + + msTransposePan->SetFirstInput(multiSpec); + msTransposePan->SetSecondInput( caster->GetOutput() ); + + msTransposeMs->Update(); + msTransposePan->Update(); + + MatrixType temp; + temp = msTransposeMs->GetResultOutput()->Get().GetInverse(); + m_Beta = temp*msTransposePan->GetResultOutput()->Get(); + + // S computation : quadratique mean of the regression residue + // Compute the transpose panchromatic image multiplied by itself + typename MSTransposeMSType::Pointer panTransposePan = MSTransposeMSType::New(); + panTransposePan->SetFirstInput(caster->GetOutput()); + panTransposePan->SetSecondInput(caster->GetOutput()); + panTransposePan->Update(); + + MatrixType S, tempS, tempS2; + S = panTransposePan->GetResultOutput()->Get(); + tempS = msTransposePan->GetResultOutput()->Get().GetTranspose(); + tempS = tempS*m_Beta; + + /** TODO + * A modifier en utilisant l'opérateur - de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * S = S-tempS; + **/ + if( (S.Rows() != tempS.Rows()) || (S.Cols() != tempS.Cols())) + { + itkExceptionMacro( << "Matrix with size (" << S.Rows() << "," << + S.Cols() << ") cannot be subtracted from matrix with size (" << + tempS.Rows() << "," << tempS.Cols() <<" )" ); + } + for( unsigned int r=0; r<S.Rows(); r++) + { + for( unsigned int c=0; c<S.Cols(); c++ ) + { + S(r,c) -= tempS(r,c); + } + } + //**** END TODO ****/ + + tempS = m_Beta.GetTranspose(); + tempS2 = msTransposePan->GetResultOutput()->Get(); + tempS = tempS*tempS2; + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * S = S-tempS; + **/ + if( (S.Rows() != tempS.Rows()) || (S.Cols() != tempS.Cols()) ) + { + itkExceptionMacro( << "Matrix with size (" << S.Rows() << "," << + S.Cols() << ") cannot be subtracted from matrix with size (" << + tempS.Rows() << "," << tempS.Cols() << " )" ); + + } + + for( unsigned int r=0; r<S.Rows(); r++) + { + for( unsigned int c=0; c<S.Cols(); c++ ) + { + S(r,c) -= tempS(r,c); + } + } + //**** END TODO ****/ + + + MatrixType xxT, xxTb, xxTbT, xxTbTb; + xxT = msTransposeMs->GetResultOutput()->Get().GetTranspose(); + xxTb = xxT*m_Beta; + xxTbT = xxTb.GetTranspose(); + xxTbTb = xxTbT*m_Beta; + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * S = S-xxTbTb; + **/ + if( (S.Cols() != xxTbTb.Cols()) || (S.Cols() != xxTbTb.Cols()) ) + { + itkExceptionMacro( << "Matrix with size (" << S.Rows() << "," << + S.Cols() << ") cannot be subtracted from matrix with size (" << + xxTbTb.Rows() << "," << xxTbTb.Cols() << " )" ); + } + + for( unsigned int r=0; r<S.Rows(); r++) + { + for( unsigned int c=0; c<S.Cols(); c++ ) + { + S(r,c) += xxTbTb(r,c); + } + } + //**** END TODO ****/ + + unsigned int size1 = multiSpec->GetLargestPossibleRegion().GetSize()[0]*multiSpec->GetLargestPossibleRegion().GetSize()[1]; + unsigned int size2 = multiSpec->GetNumberOfComponentsPerPixel()+1; + m_S = S(0,0); + m_S /= static_cast<float>(size1-size2); + + + // cutBeta is the N-1 last m_Beta element matrix. + // varPan contains transpose(cutBeta)*cutBeta/S + MatrixType varPan, cutBeta; + varPan.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), 1); + varPan.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero); + cutBeta.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), 1); + cutBeta.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero); + // Take the N-1 m_Beta last elements + for( unsigned int r=1; r<m_Beta.Rows(); r++ ) + { + cutBeta(r-1,0) = m_Beta(r,0); + } + varPan = cutBeta; + + MatrixType tempvarPan; + tempvarPan = varPan.GetTranspose(); + varPan *= tempvarPan; + varPan /= m_S; + + + // Compute the optimization matrix : m_Vcondopt + // eye is the identical matrix which size is the number of components of the multispectral image + MatrixType eye; + eye.SetSize(multiSpecInterp->GetNumberOfComponentsPerPixel(), multiSpecInterp->GetNumberOfComponentsPerPixel()); + eye.Fill(itk::NumericTraits<InputMultiSpectralInterpRealType>::Zero); + for( unsigned int r=1; r<eye.Rows(); r++) + { + eye(r,r) = vcl_pow(10., -12.); + } + + /** TODO + * A modifier en utilisant l'opérateur + de la méthode. Pour le moment probleme avec exceptionmacro (pas de GetClassName...) + * m_Vcondopt = 2 *m_Lambda*varPan+2*m_CovarianceInvMatrix*(1-m_Lambda)+eye; + **/ + if( (m_Vcondopt.Cols() != varPan.Cols()) || (m_Vcondopt.Cols() != varPan.Cols()) + || (m_Vcondopt.Cols() != m_CovarianceInvMatrix.Cols()) || (m_Vcondopt.Cols() != m_CovarianceInvMatrix.Cols())) + { + itkExceptionMacro( << "Matrix with size (" << m_Vcondopt.Rows() << "," << + m_Vcondopt.Cols() << ") cannot be subtracted from matrix with size (" << + varPan.Rows() << "," << varPan.Cols() << " ) or ( " << + m_CovarianceInvMatrix.Rows() << "," << m_CovarianceInvMatrix.Cols()<<")" ); + } + for( unsigned int r=0; r<m_Vcondopt.Rows(); r++) + { + for( unsigned int c=0; c<m_Vcondopt.Cols(); c++ ) + { + m_Vcondopt(r,c) = 2 *m_Lambda*varPan(r,c) + +2*m_CovarianceInvMatrix(r,c)*(1-m_Lambda) + +eye(r,c); + } + } + //**** END TODO ****/ + m_Vcondopt = m_Vcondopt.GetInverse(); + + + // Functor initialisation + this->GetFunctor().SetVcondopt(m_Vcondopt); + this->GetFunctor().SetBeta(cutBeta); + this->GetFunctor().SetAlpha(m_Beta(0,0)); + this->GetFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix); + this->GetFunctor().SetLambda(m_Lambda); + this->GetFunctor().SetS(m_S); + } + + +} // end namespace otb diff --git a/Code/Fusion/otbFusionImageBase.h b/Code/Fusion/otbFusionImageBase.h new file mode 100755 index 0000000000..ae9aa10a6f --- /dev/null +++ b/Code/Fusion/otbFusionImageBase.h @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAddImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/24 16:03:15 $ + Version: $Revision: 1.11 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 __otbFusionImageBase_h +#define __otbFusionImageBase_h + +#include "itkTernaryFunctorImageFilter.h" +#include "itkNumericTraits.h" + + +namespace otb +{ + /** \class FusionImageBase + * Basic class for every Fusion classes. + * \sa TernaryFunctorImageFilter + */ + template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage, class TOutputImage, class TFunctor> + class ITK_EXPORT FusionImageBase : public itk::TernaryFunctorImageFilter<TInputMultiSpectralImage, TInputMultiSpectralInterpImage, TInputPanchroImage, TOutputImage, TFunctor> + { + public: + /** Extract input and output images dimensions.*/ + itkStaticConstMacro( InputImageDimension,unsigned int, TInputMultiSpectralImage::ImageDimension); + itkStaticConstMacro( OutputImageDimension,unsigned int, TOutputImage::ImageDimension); + + /** "typedef" to simplify the variables definition and the declaration. */ + typedef TInputMultiSpectralImage InputMultiSpectralImageType; + typedef TInputMultiSpectralInterpImage InputMultiSpectralInterpImageType; + typedef TInputPanchroImage InputPanchroImageType; + typedef TOutputImage OutputImageType; + typedef TFunctor FunctorType; + + /** "typedef" for standard classes. */ + typedef FusionImageBase Self; + typedef itk::TernaryFunctorImageFilter< InputMultiSpectralImageType, + InputMultiSpectralInterpImageType, + InputPanchroImageType, + OutputImageType, + FunctorType> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** object factory method. */ + itkNewMacro(Self); + + /** return class name. */ + itkTypeMacro(FusionImageBase, TernaryFunctorImageFilter); + + /** Supported images definition. */ + typedef typename InputMultiSpectralImageType::PixelType InputMultiSpectralPixelType; + typedef typename InputMultiSpectralInterpImageType::PixelType InputMultiSpectralInterpPixelType; + typedef typename InputPanchroImageType::PixelType InputPanchroPixelType; + typedef typename OutputImageType::PixelType OutputPixelType; + /** Real class typedef definition. */ + typedef typename itk::NumericTraits<InputMultiSpectralPixelType>::RealType InputMultiSpectralRealType; + typedef typename itk::NumericTraits<InputMultiSpectralInterpPixelType>::RealType InputMultiSpectralInterpRealType; + typedef typename itk::NumericTraits<InputPanchroPixelType>::RealType InputPanchroRealType; + typedef typename InputMultiSpectralImageType::RegionType InputMultiSpectralImageRegionType; + typedef typename InputMultiSpectralInterpImageType::RegionType InputMultiSpectralInterpImageRegionType; + typedef typename InputPanchroImageType::RegionType InputPanchroImageRegionType; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + /** Image size "typedef" definition. */ + typedef typename InputMultiSpectralImageType::SizeType SizeType; + + + void SetMultiSpect(const InputMultiSpectralImageType *multiSpect){ this->SetInput1( multiSpect ); }; + void SetMultiSpectInterp(const InputMultiSpectralInterpImageType *multiSpectInterp){ this->SetInput2( multiSpectInterp ); }; + void SetPanchro(const InputPanchroImageType *panchro){ this->SetInput3( panchro ); }; + + const InputMultiSpectralImageType* GetMultiSpect() + { + if( this->GetNumberOfInputs() < 1 ) + { + return 0; + } + else + return( static_cast<const InputMultiSpectralImageType *>(this->itk::ProcessObject::GetInput(0)) ); + } + + const InputMultiSpectralInterpImageType* GetMultiSpectInterp() + { + if( this->GetNumberOfInputs() < 2 ) + { + return 0; + } + else + return( static_cast<const InputMultiSpectralInterpImageType *>(this->itk::ProcessObject::GetInput(1)) ); + } + + const InputPanchroImageType* GetPanchro() + { + if( this->GetNumberOfInputs() < 3 ) + { + return 0; + } + else + return( static_cast<const InputPanchroImageType *>(this->itk::ProcessObject::GetInput(2)) ); + } + + + }; + +} // end namespace otb + + +#endif diff --git a/Testing/Code/BasicFilters/CMakeLists.txt b/Testing/Code/BasicFilters/CMakeLists.txt index 807f6d6ee7..6dd56d127b 100755 --- a/Testing/Code/BasicFilters/CMakeLists.txt +++ b/Testing/Code/BasicFilters/CMakeLists.txt @@ -379,6 +379,41 @@ ADD_TEST(StreamingResampleImageFilterCompareWithITK ${BASICFILTERS_TESTS} #) + +# ------- otb::StreamingStatisticsVectorImageFilter ---------------------------- + +ADD_TEST(bfTuStreamingStatisticsVectorImageFilterNew ${BASICFILTERS_TESTS} + otbStreamingStatisticsVectorImageFilterNew) + +ADD_TEST(bfTvStreamingStatisticsVectorImageFilter ${BASICFILTERS_TESTS} + --compare-ascii ${TOL} + ${BASELINE_FILES}/bfStreamingStatisticsVectorImageFilterResults.txt + ${TEMP}/bfTvStreamingStatisticsVectorImageFilterResults.txt + otbStreamingStatisticsVectorImageFilter + #${IMAGEDATA}/SPOT5_SCENE01/IMAGERY.TIF + ${INPUTDATA}/sbuv.png + ${TEMP}/bfTvStreamingStatisticsVectorImageFilterResults.txt + ) + + +# ------- otb::MatrixTransposeMatrixImageFilter ---------------------------- + +ADD_TEST(bfTuMatrixTransposeMatrixImageFilterNew ${BASICFILTERS_TESTS} + otbMatrixTransposeMatrixImageFilterNew) + +ADD_TEST(bfTvMatrixTransposeMatrixImageFilter ${BASICFILTERS_TESTS} + --compare-ascii ${TOL} + ${BASELINE_FILES}/bfTvMatrixTransposeMatrixImageFilterResults.txt + ${TEMP}/bfMatrixTransposeMatrixImageFilterResults.txt + otbMatrixTransposeMatrixImageFilter + ${INPUTDATA}/multiSpect.tif + ${INPUTDATA}/multiSpectInterp.tif + ${TEMP}/bfTvMatrixTransposeMatrixImageFilterResults.txt + ) + + + + # A enrichir SET(BasicFilters_SRCS otbLeeFilter.cxx @@ -424,6 +459,10 @@ otbVectorImageTo3DScalarImageFilter.cxx otbStreamingResampleImageFilterNew.cxx otbStreamingResampleImageFilter.cxx otbStreamingResampleImageFilterCompareWithITK.cxx +otbStreamingStatisticsVectorImageFilterNew.cxx +otbStreamingStatisticsVectorImageFilter.cxx +otbMatrixTransposeMatrixImageFilterNew.cxx +otbMatrixTransposeMatrixImageFilter.cxx ) diff --git a/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx b/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx index 4cc88ae3de..d169dfc6ff 100755 --- a/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx +++ b/Testing/Code/BasicFilters/otbBasicFiltersTests.cxx @@ -70,4 +70,8 @@ REGISTER_TEST(otbVectorImageTo3DScalarImageFilter); REGISTER_TEST(otbStreamingResampleImageFilterNew); REGISTER_TEST(otbStreamingResampleImageFilter); REGISTER_TEST(otbStreamingResampleImageFilterCompareWithITK); +REGISTER_TEST(otbStreamingStatisticsVectorImageFilterNew); +REGISTER_TEST(otbStreamingStatisticsVectorImageFilter); +REGISTER_TEST(otbMatrixTransposeMatrixImageFilterNew); +REGISTER_TEST(otbMatrixTransposeMatrixImageFilter); } diff --git a/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx new file mode 100644 index 0000000000..755a763b5d --- /dev/null +++ b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx @@ -0,0 +1,86 @@ +/*========================================================================= + + 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 "otbMatrixTransposeMatrixImageFilter.h" + + +int otbMatrixTransposeMatrixImageFilter( int argc, char * argv[] ) +{ + try + { + + const char * infname1 = argv[1]; + const char * infname2 = argv[2]; + const char * outfname = argv[3]; + + const unsigned int Dimension = 2; + typedef unsigned char InputPixelType; + typedef unsigned char OutputPixelType; + + typedef otb::VectorImage<InputPixelType,Dimension> InputImage1Type; + typedef otb::VectorImage<InputPixelType,Dimension> InputImage2Type; + typedef otb::MatrixTransposeMatrixImageFilter<InputImage1Type, InputImage2Type > MatrixTransposeMatrixImageFilterType; + typedef otb::ImageFileReader<InputImage1Type> ReaderType1; + typedef otb::ImageFileReader<InputImage2Type> ReaderType2; + + // Instantiation + MatrixTransposeMatrixImageFilterType::Pointer filter = MatrixTransposeMatrixImageFilterType::New(); + ReaderType1::Pointer reader1 = ReaderType1::New(); + ReaderType2::Pointer reader2 = ReaderType2::New(); + + reader1->SetFileName(infname1); + reader2->SetFileName(infname2); + + filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); + filter->SetNumberOfStreamDivisions(200); + filter->SetFirstInput(reader1->GetOutput()); + filter->SetSecondInput(reader2->GetOutput()); + filter->SetUsePadFirstInput(true); + filter->SetUsePadSecondInput(true); + + filter->Update(); + + std::ofstream file; + file.open(outfname); + file<<"transpose : "<<filter->GetResult()<<std::endl; + file.close(); + + } + + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Exception levee inconnue !" << std::endl; + return EXIT_FAILURE; + } + + + return EXIT_SUCCESS; +} + + diff --git a/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilterNew.cxx b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilterNew.cxx new file mode 100644 index 0000000000..0895616f67 --- /dev/null +++ b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilterNew.cxx @@ -0,0 +1,59 @@ +/*========================================================================= + + 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 "otbMatrixTransposeMatrixImageFilter.h" + + +int otbMatrixTransposeMatrixImageFilterNew( int argc, char * argv[] ) +{ + try + { + const unsigned int Dimension = 2; + typedef unsigned char InputPixelType; + typedef unsigned char OutputPixelType; + + typedef otb::VectorImage<InputPixelType,Dimension> InputImage1Type; + typedef otb::VectorImage<InputPixelType,Dimension> InputImage2Type; + typedef otb::MatrixTransposeMatrixImageFilter<InputImage1Type, InputImage2Type > MatrixTransposeMatrixImageFilterType; + + // Instantiation + MatrixTransposeMatrixImageFilterType::Pointer filter = MatrixTransposeMatrixImageFilterType::New(); + + } + + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Exception levee inconnue !" << std::endl; + return EXIT_FAILURE; + } + + + return EXIT_SUCCESS; +} + + diff --git a/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx new file mode 100755 index 0000000000..c86b02e690 --- /dev/null +++ b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx @@ -0,0 +1,77 @@ +/*========================================================================= + + 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 "otbStreamingStatisticsVectorImageFilter.h" +#include "otbImageFileReader.h" +#include "otbVectorImage.h" +#include <fstream> +#include "otbStreamingTraits.h" + +int otbStreamingStatisticsVectorImageFilter(int argc, char * argv[]) +{ + try + { + + const char * infname = argv[1]; + const char * outfname = argv[2]; + + const unsigned int Dimension = 2; + typedef double PixelType; + + typedef otb::VectorImage<PixelType,Dimension> ImageType; + typedef otb::ImageFileReader<ImageType> ReaderType; + typedef otb::StreamingStatisticsVectorImageFilter<ImageType> StreamingStatisticsVectorImageFilterType; + + // Instantiating object + StreamingStatisticsVectorImageFilterType::Pointer filter = StreamingStatisticsVectorImageFilterType::New(); + + + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(infname); + + filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); + filter->SetNumberOfStreamDivisions(200); + filter->SetInput(reader->GetOutput()); + filter->Update(); + + + std::ofstream file; + file.open(outfname); + file<<"Minimum: "<<filter->GetMinimum()<<std::endl; + file<<"Maximum: "<<filter->GetMaximum()<<std::endl; + file<<"Sum: "<<filter->GetSum()<<std::endl; + file<<"Mean: "<<filter->GetMean()<<std::endl; + file<<"Covariance: "<<filter->GetCovariance()<<std::endl; + file.close(); + } + + 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/otbStreamingStatisticsVectorImageFilterNew.cxx b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilterNew.cxx new file mode 100644 index 0000000000..e8ca952935 --- /dev/null +++ b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilterNew.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 "otbStreamingStatisticsVectorImageFilter.h" +#include "otbVectorImage.h" + +int otbStreamingStatisticsVectorImageFilterNew(int argc, char * argv[]) +{ + try + { + const unsigned int Dimension = 2; + typedef unsigned char PixelType; + + typedef otb::VectorImage<PixelType,Dimension> ImageType; + typedef otb::StreamingStatisticsVectorImageFilter<ImageType> StreamingStatisticsVectorImageFilterType; + + // Instantiating object + StreamingStatisticsVectorImageFilterType::Pointer object = StreamingStatisticsVectorImageFilterType::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; +} diff --git a/Testing/Code/CMakeLists.txt b/Testing/Code/CMakeLists.txt index 803a321f39..2168fb5bad 100644 --- a/Testing/Code/CMakeLists.txt +++ b/Testing/Code/CMakeLists.txt @@ -12,6 +12,7 @@ DisparityMap SpatialReasoning Projections Radiometry +Fusion ) IF(OTB_USE_VISU_GUI) diff --git a/Testing/Code/Fusion/CMakeLists.txt b/Testing/Code/Fusion/CMakeLists.txt new file mode 100755 index 0000000000..b72f6fd187 --- /dev/null +++ b/Testing/Code/Fusion/CMakeLists.txt @@ -0,0 +1,62 @@ + +IF( NOT OTB_DISABLE_CXX_TESTING ) + +SET(BASELINE ${OTB_DATA_ROOT}/Baseline/OTB/Images) +SET(BASELINE_FILES ${OTB_DATA_ROOT}/Baseline/OTB/Files) +SET(INPUTDATA ${OTB_DATA_ROOT}/Input) +#Images de teledetection (grosses images ) +SET(IMAGEDATA ${OTB_DATA_ROOT}/LargeInput ) +SET(TEMP ${OTBTesting_BINARY_DIR}/Temporary) + +#Tolerance de base +SET(TOL 0.0) + +#Tolerance sur la difference des valeurs numeriques dans le --compare-ascii +SET(EPS 0.001) + +#Tolerance sur diff pixel image +#EPSILON est different de 0.0 pour les tests multiplateformes avec différentes options de compilation. +SET(EPSILON 0.00000001) + +SET(FUSION_TESTS ${CXX_TEST_PATH}/otbFusionTests) + + +# ------- otb::ImageFusionBase ------------------------------ +ADD_TEST(fuTuFusionImageBaseNew ${FUSION_TESTS} + otbFusionImageBaseNew +) +# ------- otb::BayesianFusionFilter ------------------------------ +ADD_TEST(fuTuBayesianFusionFilterNew ${FUSION_TESTS} + otbBayesianFusionFilterNew +) + +ADD_TEST(fuTvBayesianFusionFilter ${FUSION_TESTS} + --compare-image ${TOL} ${BASELINE}/fuTvBayesianFusion.tif + ${TEMP}/fuTvBayesianFusion.tif + otbBayesianFusionFilter + ${INPUTDATA}/multiSpect.tif + ${INPUTDATA}/multiSpectInterp.tif + ${INPUTDATA}/panchro.tif + ${TEMP}/fuTvBayesianFusion.tif +) + + +# A enrichir +SET(Fusion_SRCS +otbFusionImageBaseNew.cxx +otbBayesianFusionFilterNew.cxx +otbBayesianFusionFilter.cxx +) + + +INCLUDE_DIRECTORIES("${OTBTesting_BINARY_DIR}") + +ADD_EXECUTABLE(otbFusionTests otbFusionTests.cxx ${Fusion_SRCS}) +TARGET_LINK_LIBRARIES(otbFusionTests OTBFusion OTBCommon OTBIO gdal ITKIO ITKCommon ITKAlgorithms) + + +ENDIF( NOT OTB_DISABLE_CXX_TESTING ) + + + + diff --git a/Testing/Code/Fusion/otbBayesianFusionFilter.cxx b/Testing/Code/Fusion/otbBayesianFusionFilter.cxx new file mode 100755 index 0000000000..625b3ed3a4 --- /dev/null +++ b/Testing/Code/Fusion/otbBayesianFusionFilter.cxx @@ -0,0 +1,83 @@ +/*========================================================================= + + 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 "otbImageFileReader.h" +#include "otbImageFileWriter.h" +#include "otbVectorImage.h" +#include "otbImage.h" + +#include "otbBayesianFusionFilter.h" + +int otbBayesianFusionFilter( int argc, char * argv[] ) +{ + try + { + const char * multispect = argv[1]; + const char * multispectinterp = argv[2]; + const char * panchro = argv[3]; + const char * output = argv[4]; + + const unsigned int Dimension = 2; + typedef double PixelType; + + + typedef otb::VectorImage<PixelType,Dimension> VectorImageType; + typedef otb::Image<PixelType,Dimension> PanchroImageType; + typedef otb::ImageFileReader<VectorImageType> VectorReaderType; + typedef otb::ImageFileReader<PanchroImageType> ImageReaderType; + typedef otb::ImageFileWriter<VectorImageType> VectorImageWriterType; + typedef otb::BayesianFusionFilter<VectorImageType, VectorImageType, PanchroImageType, VectorImageType> FilterType; + + VectorReaderType::Pointer multiSpectReader = VectorReaderType::New(); + VectorReaderType::Pointer multiSpectInterpReader = VectorReaderType::New(); + ImageReaderType::Pointer panchroReader = ImageReaderType::New(); + FilterType::Pointer filter = FilterType::New(); + VectorImageWriterType::Pointer writer = VectorImageWriterType::New(); + + multiSpectReader->SetFileName(multispect); + multiSpectInterpReader->SetFileName(multispectinterp); + panchroReader->SetFileName(panchro); + + filter->SetMultiSpect(multiSpectReader->GetOutput()); + filter->SetMultiSpectInterp(multiSpectInterpReader->GetOutput()); + filter->SetPanchro(panchroReader->GetOutput()); + writer->SetInput( filter->GetOutput() ); + writer->SetFileName(output); + writer->Update(); + + } + + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Exception levee inconnue !" << std::endl; + return EXIT_FAILURE; + } + + + return EXIT_SUCCESS; +} + + diff --git a/Testing/Code/Fusion/otbBayesianFusionFilterNew.cxx b/Testing/Code/Fusion/otbBayesianFusionFilterNew.cxx new file mode 100644 index 0000000000..614056dfbd --- /dev/null +++ b/Testing/Code/Fusion/otbBayesianFusionFilterNew.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 "itkExceptionObject.h" +#include "otbImageFileReader.h" +#include "otbImageFileWriter.h" +#include "otbVectorImage.h" +#include "otbImage.h" + +#include "otbBayesianFusionFilter.h" + +int otbBayesianFusionFilterNew( int argc, char * argv[] ) +{ + try + { + + const unsigned int Dimension = 2; + typedef double PixelType; + + + typedef otb::VectorImage<PixelType,Dimension> VectorImageType; + typedef otb::Image<PixelType,Dimension> PanchroImageType; + typedef otb::ImageFileReader<VectorImageType> VectorReaderType; + typedef otb::ImageFileReader<PanchroImageType> ImageReaderType; + typedef otb::BayesianFusionFilter<VectorImageType, VectorImageType, PanchroImageType, VectorImageType> FilterType; + + FilterType::Pointer filter = FilterType::New(); + + } + + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Exception levee inconnue !" << std::endl; + return EXIT_FAILURE; + } + + + return EXIT_SUCCESS; +} + + diff --git a/Testing/Code/Fusion/otbFusionImageBaseNew.cxx b/Testing/Code/Fusion/otbFusionImageBaseNew.cxx new file mode 100644 index 0000000000..7b983ea2b5 --- /dev/null +++ b/Testing/Code/Fusion/otbFusionImageBaseNew.cxx @@ -0,0 +1,86 @@ +/*========================================================================= + + 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 "otbFusionImageBase.h" + +namespace Functor +{ + template <class TInputMultiSpectral, class TInputMultiSpectralInterp, class TInputPanchro, class TOutput> + class NewFunctorTest + { + public: + NewFunctorTest() {}; + ~NewFunctorTest() {}; + + inline TOutput operator() (const TInputMultiSpectral & A, const TInputMultiSpectralInterp & B, const TInputPanchro & C) + { + return(static_cast<TOutput>(A[0]) + static_cast<TOutput>(B[0]) + static_cast<TOutput>(C)); + + } + }; +} + +int otbFusionImageBaseNew( int argc, char * argv[] ) +{ + try + { + const unsigned int Dimension = 2; + typedef unsigned char InputPixelType; + typedef unsigned char OutputPixelType; + + typedef otb::Image<InputPixelType,Dimension> InputPanchroImageType; + typedef otb::VectorImage<InputPixelType,Dimension> InputMultiSpectralImageType; + typedef otb::VectorImage<InputPixelType,Dimension> InputMultiSpectralInterpImageType; + typedef otb::Image<OutputPixelType,Dimension> OutputImageType; + + typedef otb::FusionImageBase<InputMultiSpectralImageType, + InputMultiSpectralInterpImageType, + InputPanchroImageType, + OutputImageType, + Functor::NewFunctorTest<InputMultiSpectralImageType::PixelType, + InputMultiSpectralInterpImageType::PixelType, + InputPanchroImageType::PixelType, + OutputImageType::PixelType> + > FusionImageBaseType; + + // Instantiation + FusionImageBaseType::Pointer base = FusionImageBaseType::New(); + + } + + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Exception levee inconnue !" << std::endl; + return EXIT_FAILURE; + } + + + return EXIT_SUCCESS; +} + + diff --git a/Testing/Code/Fusion/otbFusionTests.cxx b/Testing/Code/Fusion/otbFusionTests.cxx new file mode 100755 index 0000000000..6fa5dc19c4 --- /dev/null +++ b/Testing/Code/Fusion/otbFusionTests.cxx @@ -0,0 +1,34 @@ +/*========================================================================= + + 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. + +=========================================================================*/ + +// this file defines the otbCommonTest for the test driver +// and all it expects is that you have a function called RegisterTests +#if defined(_MSC_VER) +#pragma warning ( disable : 4786 ) +#endif + +#include <iostream> +#include "otbTestMain.h" + + +void RegisterTests() +{ +REGISTER_TEST(otbBayesianFusionFilterNew); +REGISTER_TEST(otbBayesianFusionFilter); +REGISTER_TEST(otbFusionImageBaseNew); +} diff --git a/otbIncludeDirectories.cmake b/otbIncludeDirectories.cmake index 4f4f0ee87f..96af8bb6fc 100644 --- a/otbIncludeDirectories.cmake +++ b/otbIncludeDirectories.cmake @@ -20,6 +20,7 @@ SET(OTB_INCLUDE_DIRS_BUILD_TREE ${OTB_INCLUDE_DIRS_BUILD_TREE} ${OTB_SOURCE_DIR}/Code/DisparityMap ${OTB_SOURCE_DIR}/Code/Visu ${OTB_SOURCE_DIR}/Code/Gui + ${OTB_SOURCE_DIR}/Code/Fusion ${OTB_SOURCE_DIR}/Code/Projections ${OTB_SOURCE_DIR}/Code/Radiometry ${OTB_SOURCE_DIR}/Utilities/BGL -- GitLab