From 00b43e66efdbe42e0b95264e241780b00dff7a14 Mon Sep 17 00:00:00 2001 From: Emmanuel Christophe <emmanuel.christophe@orfeo-toolbox.org> Date: Tue, 29 Apr 2008 16:02:35 +0000 Subject: [PATCH] Ajout d'un sampler et energy --- Code/Markov/otbMRFEnergyEdgeFidelity.h | 54 ++++++ Code/Markov/otbMRFSamplerRandomMAP.h | 154 ++++++++++++++++++ .../Markov/MarkovClassification1Example.cxx | 2 +- .../Markov/MarkovClassification2Example.cxx | 8 +- 4 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 Code/Markov/otbMRFEnergyEdgeFidelity.h create mode 100644 Code/Markov/otbMRFSamplerRandomMAP.h diff --git a/Code/Markov/otbMRFEnergyEdgeFidelity.h b/Code/Markov/otbMRFEnergyEdgeFidelity.h new file mode 100644 index 0000000000..bf3501a736 --- /dev/null +++ b/Code/Markov/otbMRFEnergyEdgeFidelity.h @@ -0,0 +1,54 @@ + +#ifndef _otbMRFEnergyEdgeFidelity_h +#define _otbMRFEnergyEdgeFidelity_h + +#include "otbMRFEnergy.h" +#define M_SQUARE(x) ((x)*(x)) + +namespace otb +{ + /** + * \class MRFEnergyEdgeFidelity + * \brief This is the implementation of an edge preserving model for Markov denoising. + * + * This is the implementation of an edge fidelity model for Markov denoising, to be used for + * regularization. Energy is: + * \f[ \sum_{t \in \mathcal{V}_s} U(x_s,x_t) = \Phi(x_s-x_t) \f] + * with + * - \f$ x_s \f$ the label on site s + * - \f$ x_t \f$ the label on site t, a neighbor of s + * - \f$ \Phi \f$ an edge preserving function: + \f[ \Phi(u) = \frac{u^2}{1+u^2} \f] + */ + + template< class TInput1, class TInput2> + class ITK_EXPORT MRFEnergyEdgeFidelity : public MRFEnergy< TInput1, TInput2> + { + public: + typedef MRFEnergyEdgeFidelity Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef itk::ConstNeighborhoodIterator< TInput1 > NeighborhoodIterator; + typedef typename TInput2::PixelType LabelledImagePixelType; + + itkNewMacro(Self); + +// itkSetMacro(Beta, double); + itkTypeMacro(MRFEnergy,Object); + + double GetSingleValue(const InputImagePixelType & value1, const LabelledImagePixelType & value2) + { + return M_SQUARE((value1 - value2))/double(1+M_SQUARE((value1 - value2))); + } + + + protected: + // The constructor and destructor. + MRFEnergyEdgeFidelity() {}; + virtual ~MRFEnergyEdgeFidelity() {}; + }; +} + +#endif diff --git a/Code/Markov/otbMRFSamplerRandomMAP.h b/Code/Markov/otbMRFSamplerRandomMAP.h new file mode 100644 index 0000000000..4b5aaa3803 --- /dev/null +++ b/Code/Markov/otbMRFSamplerRandomMAP.h @@ -0,0 +1,154 @@ + +#ifndef _MRFSamplerRandomMAP_h +#define _MRFSamplerRandomMAP_h + +// #include "otbMRFEnergy.h" +#include "otbMRFSampler.h" + +namespace otb +{ + /** + * \class MRFSamplerRandomMAP + * \brief This is the base class for sampler methods used in the MRF framework. + * + * This is one sampler to be used int he MRF framework. This sampler select the + * value randomly according to the apriori probability. + * + * The probability is defined from the energy as: + * + * \f[ P(X=x)= \frac{1}{Z} \exp^{-U(x)} \f] + * + * where \f$ Z = \sum_x \exp^{-U(x)}\f$ + * + */ + + template< class TInput1, class TInput2> + class ITK_EXPORT MRFSamplerRandomMAP : + public MRFSampler< TInput1, TInput2> + { + public: + + typedef MRFSamplerRandomMAP Self; + typedef itk::Object Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef itk::ConstNeighborhoodIterator< TInput1 > InputImageNeighborhoodIterator; +// typedef itk::NeighborhoodIterator< TInput1 > InputImageNeighborhoodIterator; + typedef itk::NeighborhoodIterator< TInput2 > LabelledImageNeighborhoodIterator; + typedef typename TInput2::PixelType LabelledImagePixelType; + + typedef MRFEnergy<TInput1, TInput2> EnergyFidelityType; + typedef MRFEnergy<TInput2, TInput2> EnergyRegularizationType; + + typedef typename EnergyFidelityType::Pointer EnergyFidelityPointer; + typedef typename EnergyRegularizationType::Pointer EnergyRegularizationPointer; + + itkNewMacro(Self); + + itkTypeMacro(MRFSamplerRandomMAP,Object); + +// void SetNumberOfClasses(unsigned int arg) +// { +// otbDebugMacro("setting NumberOfClasses to " << arg); +// if (this->m_NumberOfClasses != arg) +// { +// this->m_NumberOfClasses = arg; +// repartitionFunction = (double *) calloc(m_NumberOfClasses, sizeof(double)); +// energy = (double *) calloc(m_NumberOfClasses, sizeof(double)); +// this->Modified(); +// } +// } +// itkGetMacro(NumberOfClasses, unsigned int); +// +// itkSetMacro(Lambda, double); +// itkGetMacro(Lambda, double); +// +// itkGetMacro(DeltaEnergy, double); +// itkGetMacro(Value, LabelledImagePixelType); +// +// itkSetObjectMacro( EnergyRegularization, EnergyRegularizationType); +// itkSetObjectMacro( EnergyFidelity, EnergyFidelityType); + + inline int Compute( const InputImageNeighborhoodIterator & itData, + const LabelledImageNeighborhoodIterator & itRegul) + { + this->m_EnergyBefore=this->m_EnergyFidelity->GetValue(itData, itRegul.GetCenterPixel()) + + this->m_Lambda * this->m_EnergyRegularization->GetValue(itRegul, itRegul.GetCenterPixel()); + + //Try all possible value (how to be generic ?) + this->m_EnergyAfter = this->m_EnergyBefore; //default values to current one + this->m_Value = itRegul.GetCenterPixel(); +// otbDebugMacro(<< "Computing MAP for pix " << itData.GetIndex()); + //Compute probability for each possibility + double totalProba=0.0; + for (LabelledImagePixelType valueCurrent = 0; + valueCurrent < this->m_NumberOfClasses; ++valueCurrent) + { +// otbDebugMacro(<< " --> Proposed value " << static_cast<double>(valueCurrent)); + this->m_EnergyCurrent = this->m_EnergyFidelity->GetValue(itData, valueCurrent) + + this->m_Lambda * this->m_EnergyRegularization->GetValue(itRegul, valueCurrent); + + energy[valueCurrent] = this->m_EnergyCurrent; + repartitionFunction[valueCurrent] = vcl_exp(-this->m_EnergyCurrent)+totalProba; + totalProba = repartitionFunction[valueCurrent]; +// otbDebugMacro("valueCurrent, repartitionFunction[valueCurrent] " << (unsigned int) valueCurrent << ", " << repartitionFunction[valueCurrent]); + + } + + //Pick a value according to probability + + double select = (rand()/(double(RAND_MAX)+1) * totalProba); +// otbDebugMacro("repartitionFunction " << repartitionFunction[0] << " " +// << repartitionFunction[1] << " " << repartitionFunction[2] << " " +// << repartitionFunction[3] << " "); + +// otbDebugMacro("select, totalProba " << select << ", " << totalProba); + LabelledImagePixelType valueCurrent = 0; + for (valueCurrent = 0; + valueCurrent < this->m_NumberOfClasses; ++valueCurrent) + { + if (repartitionFunction[valueCurrent] > select) break; + } + + if ( this->m_Value != valueCurrent) + { + this->m_Value = valueCurrent; + this->m_EnergyAfter = energy[valueCurrent]; + } + + this->m_DeltaEnergy= this->m_EnergyAfter - this->m_EnergyBefore; +// otbDebugMacro("Decision " << (unsigned int) valueCurrent); + return 0; + } + + + private: +// unsigned int m_NumberOfClasses; +// double m_EnergyBefore; +// double m_EnergyAfter; +// double m_DeltaEnergy; +// LabelledImagePixelType m_Value; +// EnergyRegularizationPointer m_EnergyRegularization; +// EnergyFidelityPointer m_EnergyFidelity; +// LabelledImagePixelType valueCurrent; +// double m_EnergyCurrent; + double * repartitionFunction ; + double * energy; +// double m_Lambda; + + + protected: + // The constructor and destructor. + MRFSamplerRandomMAP() { + energy = (double *) calloc(this->m_NumberOfClasses, sizeof(double)); + repartitionFunction = (double *) calloc(this->m_NumberOfClasses, sizeof(double)); + } + virtual ~MRFSamplerRandomMAP() {} + + }; + + +} + +#endif diff --git a/Examples/Markov/MarkovClassification1Example.cxx b/Examples/Markov/MarkovClassification1Example.cxx index 497b880d8a..46c5167940 100644 --- a/Examples/Markov/MarkovClassification1Example.cxx +++ b/Examples/Markov/MarkovClassification1Example.cxx @@ -39,7 +39,7 @@ // // This example applies the \doxygen{otb}{MarkovClassificationFilter} to // classify an image into four classes defined by their mean and variance. The -// optimization is done using an Metropolis algorithm with a MAP estimator. The +// optimization is done using an Metropolis algorithm with a random sampler. The // regularization energy is defined by a Potts model and the fidelity by a // Gaussian model. // diff --git a/Examples/Markov/MarkovClassification2Example.cxx b/Examples/Markov/MarkovClassification2Example.cxx index 7c25c723a9..0d5bf64e78 100644 --- a/Examples/Markov/MarkovClassification2Example.cxx +++ b/Examples/Markov/MarkovClassification2Example.cxx @@ -39,7 +39,7 @@ // // This example applies the \doxygen{otb}{MarkovClassificationFilter} to // classify an image into four classes defined by their mean and variance. The -// optimization is done using an Metropolis algorithm with a MAP estimator. The +// optimization is done using an ICM algorithm with a MAP estimator. The // regularization energy is defined by a Potts model and the fidelity by a // Gaussian model. // @@ -66,8 +66,8 @@ // #include "otbMRFEnergyPotts.h" // #include "otbMRFEnergyGaussianClassification.h" // #include "otbMRFOptimizerICM.h" -#include "otbMRFSamplerMAP.h" -// #include "otbMRFSamplerRandomMAP.h" +// #include "otbMRFSamplerMAP.h" +#include "otbMRFSamplerRandomMAP.h" #include "otbMRFOptimizerICM.h" // #include "otbMRFSamplerRandom.h" // Software Guide : EndCodeSnippet @@ -161,7 +161,7 @@ int main(int argc, char* argv[] ) // Software Guide : BeginCodeSnippet - typedef otb::MRFSamplerMAP< InputImageType, LabelledImageType> SamplerType; + typedef otb::MRFSamplerRandomMAP< InputImageType, LabelledImageType> SamplerType; // Software Guide : EndCodeSnippet -- GitLab