diff --git a/Examples/Markov/CMakeLists.txt b/Examples/Markov/CMakeLists.txt index 70d1f24da89a09fec817ee6f5babb50e25f56173..c4d85b17a0c5be52b1fa5970b4d3a6c916d83a1a 100755 --- a/Examples/Markov/CMakeLists.txt +++ b/Examples/Markov/CMakeLists.txt @@ -3,6 +3,8 @@ INCLUDE_REGULAR_EXPRESSION("^.*$") SET(Markov_EXAMPLES ${CXX_TEST_PATH}/otbMarkovExamplesTests) +#ADD_EXECUTABLE(testRandom testRandom.cxx ) +#TARGET_LINK_LIBRARIES(testRandom OTBMarkov OTBCommon OTBIO ITKNumerics ITKIO) ADD_EXECUTABLE(MarkovRandomField1Example MarkovRandomField1Example.cxx ) TARGET_LINK_LIBRARIES(MarkovRandomField1Example OTBMarkov OTBCommon OTBIO ITKNumerics ITKIO) @@ -10,6 +12,9 @@ TARGET_LINK_LIBRARIES(MarkovRandomField1Example OTBMarkov OTBCommon OTBIO ITKNum ADD_EXECUTABLE(MarkovRandomField2Example MarkovRandomField2Example.cxx ) TARGET_LINK_LIBRARIES(MarkovRandomField2Example OTBMarkov OTBCommon OTBIO ITKNumerics ITKIO) +# ADD_EXECUTABLE(MarkovRandomField3Example MarkovRandomField3Example.cxx ) +# TARGET_LINK_LIBRARIES(MarkovRandomField3Example OTBMarkov OTBCommon OTBIO ITKNumerics ITKIO) + IF( NOT OTB_DISABLE_CXX_TESTING AND NOT OTB_DISABLE_CXX_EXAMPLES_TESTING ) SET(BASELINE ${OTB_DATA_ROOT}/Baseline/Examples/Markov) @@ -28,13 +33,22 @@ ADD_TEST(MarkovRandomField1ExampleTest ${EXE_TESTS} ${TEMP}/MarkovRandomField1.png MarkovRandomField1ExampleTest ${INPUTDATA}/QB_Suburb.png - ${INPUTDATA}/RandomImage.png ${TEMP}/MarkovRandomField1.png 1.0 - 30 + 20 1.0 ) +ADD_TEST(MarkovRandomField2ExampleTest ${EXE_TESTS} + --compare-image ${EPSILON} + ${BASELINE}/MarkovRandomField2.png + ${TEMP}/MarkovRandomField2.png + MarkovRandomField1ExampleTest + ${INPUTDATA}/QB_Suburb.png + ${TEMP}/MarkovRandomField2.png + 1.0 + 5 +) INCLUDE_DIRECTORIES("${OTBTesting_BINARY_DIR}") diff --git a/Examples/Markov/MarkovRandomField1Example.cxx b/Examples/Markov/MarkovRandomField1Example.cxx index 1cad19411a8c3ea51878b48f8272adc3458e6f88..b07634766ab2a9a708ef348b60bb529b9097c1bb 100644 --- a/Examples/Markov/MarkovRandomField1Example.cxx +++ b/Examples/Markov/MarkovRandomField1Example.cxx @@ -25,24 +25,25 @@ #endif // Software Guide : BeginCommandLineArgs -// INPUTS: {QB_Suburb.png}, {RandomImage.png} -// OUTPUTS: {MarkovClassification1.png} -// 1.0 30 1.0 +// INPUTS: {QB_Suburb.png} +// OUTPUTS: {MarkovRandomField1.png} +// 1.0 20 1.0 // Software Guide : EndCommandLineArgs // Software Guide : BeginLatex // -// This example illustrates the details of the \doxygen{otb}{MarkovClassificationFilter}. +// This example illustrates the details of the \doxygen{otb}{MarkovRandomFieldFilter}. // This filter is an application of the Markov Random Fields for classification, // segmentation or restauration. // -// This example applies the \doxygen{otb}{MarkovClassificationFilter} to +// This example applies the \doxygen{otb}{MarkovRandomFieldFilter} to // classify an image into four classes defined by their mean and variance. 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. // +// // Software Guide : EndLatex #include "otbImageFileReader.h" @@ -54,7 +55,7 @@ // Software Guide : BeginLatex // -// The first step towards the use of this filter is the inclusion of the proper +// The first step toward the use of this filter is the inclusion of the proper // header files. // // Software Guide : EndLatex @@ -71,11 +72,12 @@ int main(int argc, char* argv[] ) { - if( argc < 6 ) + if( argc != 6 ) { + std::cerr << "Missing Parameters "<< argc << std::endl; std::cerr << "Missing Parameters " << std::endl; std::cerr << "Usage: " << argv[0]; - std::cerr << " inputImage inputInitialization output lambda iterations temperature" << std::endl; + std::cerr << " inputImage output lambda iterations temperature" << std::endl; return 1; } @@ -84,7 +86,7 @@ int main(int argc, char* argv[] ) // // Then we must decide what pixel type to use for the image. We // choose to make all computations with double precision. - // The labeled image is of type unsigned char to allow up to 256 different + // The labelled image is of type unsigned char which allows up to 256 different // classes. // // Software Guide : EndLatex @@ -112,19 +114,15 @@ int main(int argc, char* argv[] ) // Software Guide : BeginCodeSnippet typedef otb::ImageFileReader< InputImageType > ReaderType; - typedef otb::ImageFileReader< LabelledImageType > ReaderLabelledType; typedef otb::ImageFileWriter< LabelledImageType > WriterType; ReaderType::Pointer reader = ReaderType::New(); - ReaderLabelledType::Pointer reader2 = ReaderLabelledType::New(); WriterType::Pointer writer = WriterType::New(); const char * inputFilename = argv[1]; - const char * labelledFilename = argv[2]; - const char * outputFilename = argv[3]; + const char * outputFilename = argv[2]; reader->SetFileName( inputFilename ); - reader2->SetFileName( labelledFilename ); writer->SetFileName( outputFilename ); // Software Guide : EndCodeSnippet @@ -132,8 +130,8 @@ int main(int argc, char* argv[] ) // Software Guide : BeginLatex // // Finally, we define the different classes necessary for the Markov classification. - // A \doxygen{otb}{MarkovClassificationFilter} is instanciated, this is the - // main class which connects the others to do the Markov classification. + // A \doxygen{otb}{MarkovRandomFieldFilter} is instanciated, this is the + // main class which connect the other to do the Markov classification. // // Software Guide : EndLatex @@ -149,7 +147,7 @@ int main(int argc, char* argv[] ) // An \doxygen{otb}{MRFSamplerRandomMAP}, which derives from the // \doxygen{otb}{MRFSampler}, is instanciated. The sampler is in charge of // proposing a modification for a given site. The - // \doxygen{otb}{MRFSamplerRandomMAP}, randomly picks one possible value + // \doxygen{otb}{MRFSamplerRandomMAP}, randomly pick one possible value // according to the MAP probability. // // Software Guide : EndLatex @@ -178,9 +176,9 @@ int main(int argc, char* argv[] ) // Software Guide : BeginLatex // - // Two energies, deriving from the \doxygen{otb}{MRFEnergy} class needs to be instanciated. One energy - // is required for the regularization, taking into account the relationship between neighborhing pixels - // in the classified image. Here, this is done with the \doxygen{otb}{MRFEnergyPotts} which implements + // Two energy, deriving from the \doxygen{otb}{MRFEnergy} class need to be instanciated. One energy + // is required for the regularization, taking into account the relashionship between neighborhing pixels + // in the classified image. Here it is done with the \doxygen{otb}{MRFEnergyPotts} which implement // a Potts model. // // The second energy is for the fidelity to the original data. Here it is done with an @@ -216,7 +214,7 @@ int main(int argc, char* argv[] ) // Software Guide : BeginLatex // - // Variables for the \doxygen{otb}{MRFEnergyGaussianClassification} class, meand + // Parameter for the \doxygen{otb}{MRFEnergyGaussianClassification} class, meand // and standard deviation are created. // // Software Guide : EndLatex @@ -225,25 +223,6 @@ int main(int argc, char* argv[] ) // Software Guide : BeginCodeSnippet unsigned int nClass = 4; - itk::VariableLengthVector<double> mean; - itk::VariableLengthVector<double> stdDev; - mean.SetSize(nClass); - stdDev.SetSize(nClass); - mean[0]=10;mean[1]=80;mean[2]=150;mean[3]=220; - stdDev[0]=10;stdDev[1]=10;stdDev[2]=10;stdDev[3]=10; - - // Software Guide : EndCodeSnippet - - - // Software Guide : BeginLatex - // - // These parameters are passed to the different classs and the sampler, optimizer and - // energies are connected with the Markov filter. - // - // Software Guide : EndLatex - - // Software Guide : BeginCodeSnippet - energyFidelity->SetNumberOfParameters(2*nClass); EnergyFidelityType::ParametersType parameters; parameters.SetSize(energyFidelity->GetNumberOfParameters()); @@ -256,18 +235,33 @@ int main(int argc, char* argv[] ) parameters[6]=220.0;//Class 3 mean parameters[7]=10.0; //Class 3 stde energyFidelity->SetParameters(parameters); - OptimizerType::ParametersType paramOpt(1); - paramOpt.Fill(atof(argv[6])); - optimizer->SetParameters(paramOpt); - markovFilter->SetValueInsteadRandom(500); // Unable rand() calculation + + // Software Guide : EndCodeSnippet + + + // Software Guide : BeginLatex + // + // Parameters are given to the different class an the sampler, optimizer and + // energies are connected with the Markov filter. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + + optimizer->SetParameters(atoi(argv[5])); markovFilter->SetNumberOfClasses(nClass); - markovFilter->SetMaximumNumberOfIterations(atoi(argv[5])); - markovFilter->SetErrorTolerance(-1.0); - markovFilter->SetLambda(atof(argv[4])); + markovFilter->SetMaximumNumberOfIterations(atoi(argv[4])); + markovFilter->SetErrorTolerance(0.0); + markovFilter->SetLambda(atof(argv[3])); markovFilter->SetNeighborhoodRadius(1); - + markovFilter->SetEnergyRegularization(static_cast<MarkovRandomFieldFilterType::EnergyRegularizationPointer>(energyRegularization)); + markovFilter->SetEnergyFidelity(static_cast<MarkovRandomFieldFilterType::EnergyFidelityPointer>(energyFidelity)); + /** Pas de finction concordante avec l'appel EnergyPotts*/ + /* markovFilter->SetEnergyRegularization(energyRegularization); markovFilter->SetEnergyFidelity(energyFidelity); + */ markovFilter->SetOptimizer(optimizer); markovFilter->SetSampler(sampler); @@ -276,13 +270,12 @@ int main(int argc, char* argv[] ) // Software Guide : BeginLatex // // The pipeline is connected. An \doxygen{itk}{RescaleIntensityImageFilter} - // rescales the classified image before saving it. + // rescale the classified image before saving it. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet - markovFilter->SetTrainingInput(reader2->GetOutput()); markovFilter->SetInput(reader->GetOutput()); typedef itk::RescaleIntensityImageFilter @@ -299,7 +292,7 @@ int main(int argc, char* argv[] ) // Software Guide : BeginLatex // - // Finally, the pipeline execution is triggered. + // Finally, the pipeline execution is trigerred. // // Software Guide : EndLatex @@ -308,20 +301,6 @@ int main(int argc, char* argv[] ) writer->Update(); // Software Guide : EndCodeSnippet - - // Software Guide : BeginLatex -// Figure \ref{fig:MARKOVCLASS1} shows the result of the MRF classification. -// \begin{figure} -// \center -// \includegraphics[width=0.45\textwidth]{QB_Suburb.eps} -// \includegraphics[width=0.45\textwidth]{MarkovClassification1.eps} -// \itkcaption[Markov Random Field Image Classification]{Result of the MRF -// classification using a Metropolis algorithm with a random sampler -// and a Potts regularization energy and a Gaussian fidelity. Left: Original image. Right: image of classes.} -// \label{fig:MARKOVCLASS1} -// \end{figure} -// Software Guide : EndLatex - return 0; diff --git a/Examples/Markov/MarkovRandomField2Example.cxx b/Examples/Markov/MarkovRandomField2Example.cxx index bc7e1c8ed388ce686c40bd43791056b32c0882d6..395ef409df926dd8ca1120ecd0f07a4ff0a652d0 100644 --- a/Examples/Markov/MarkovRandomField2Example.cxx +++ b/Examples/Markov/MarkovRandomField2Example.cxx @@ -25,23 +25,20 @@ #endif // Software Guide : BeginCommandLineArgs -// INPUTS: {QB_Suburb.png RandomImage.png} -// OUTPUTS: {MarkovClassification2.png} -// 1.0 30 1.0 +// INPUTS: {QB_Suburb.png} +// OUTPUTS: {MarkovRandomField1.png} +// 1.0 5 // Software Guide : EndCommandLineArgs // Software Guide : BeginLatex // -// This example illustrates the details of the \doxygen{otb}{MarkovClassificationFilter}. -// This filter is an application of the Markov Random Fields for classification, -// segmentation or restauration. -// -// 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 ICM algorithm with a MAP estimator. The -// regularization energy is defined by a Potts model and the fidelity by a -// Gaussian model. +// Using a similar structure as the previous program and the same energy +// function, we are now going to slightly alter the program to use a +// different sampler and optimizer. The proposed sample is proposed +// randomly according to the MAP probability and the optimizer is the +// ICM which accept the proposed sample if it enable a reduction of +// the energy. // // Software Guide : EndLatex @@ -54,47 +51,31 @@ // Software Guide : BeginLatex // -// The first step toward the use of this filter is the inclusion of the proper -// header files. +// First, we need to include header specific to these class: // // Software Guide : EndLatex -// Software Guide : BeginCodeSnippet + #include "otbMRFEnergy.h" #include "otbMRFEnergyPotts.h" #include "otbMRFEnergyGaussianClassification.h" -// #include "otbMRFEnergyPotts.h" -// #include "otbMRFEnergyGaussianClassification.h" -// #include "otbMRFOptimizerICM.h" -// #include "otbMRFSamplerMAP.h" + +// Software Guide : BeginCodeSnippet #include "otbMRFSamplerRandomMAP.h" #include "otbMRFOptimizerICM.h" -// #include "otbMRFSamplerRandom.h" // Software Guide : EndCodeSnippet - +#include "otbMRFSamplerRandom.h" int main(int argc, char* argv[] ) { - if( argc < 6 ) + if( argc != 5 ) { std::cerr << "Missing Parameters " << std::endl; std::cerr << "Usage: " << argv[0]; - std::cerr << " inputImage inputInitialization output lambda iterations temperature" << std::endl; + std::cerr << " inputImage output lambda iterations" << std::endl; return 1; } - - - // Software Guide : BeginLatex - // - // Then we must decide what pixel type to use for the image. We - // choose to make all computations with double precision. - // The labelled image is of type unsigned char to allow up to 256 different - // classes. - // - // Software Guide : EndLatex - - // Software Guide : BeginCodeSnippet const unsigned int Dimension = 2; @@ -103,78 +84,35 @@ int main(int argc, char* argv[] ) typedef otb::Image<InternalPixelType, Dimension> InputImageType; typedef otb::Image<LabelledPixelType, Dimension> LabelledImageType; - // Software Guide : EndCodeSnippet - - - // Software Guide : BeginLatex - // - // We define a reader for the image to be classified, an initialisation for the - // classification (which could be random) and a writer for the final - // classification. - // - // Software Guide : EndLatex - - // Software Guide : BeginCodeSnippet - typedef otb::ImageFileReader< InputImageType > ReaderType; - typedef otb::ImageFileReader< LabelledImageType > ReaderLabelledType; typedef otb::ImageFileWriter< LabelledImageType > WriterType; ReaderType::Pointer reader = ReaderType::New(); - ReaderLabelledType::Pointer reader2 = ReaderLabelledType::New(); WriterType::Pointer writer = WriterType::New(); const char * inputFilename = argv[1]; - const char * labelledFilename = argv[2]; - const char * outputFilename = argv[3]; + const char * outputFilename = argv[2]; reader->SetFileName( inputFilename ); - reader2->SetFileName( labelledFilename ); writer->SetFileName( outputFilename ); - // Software Guide : EndCodeSnippet - - // Software Guide : BeginLatex - // - // Finally, we define the different classes necessary for the Markov classification. - // A \doxygen{otb}{MarkovClassificationFilter} is instanciated, this is the - // main class which connect the other to do the Markov classification. - // - // Software Guide : EndLatex - - // Software Guide : BeginCodeSnippet - typedef otb::MarkovRandomFieldFilter <InputImageType,LabelledImageType> MarkovRandomFieldFilterType; - // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // - // An \doxygen{otb}{MRFSamplerRandomMAP}, which derives from the - // \doxygen{otb}{MRFSampler}, is instanciated. The sampler is in charge of - // proposing a modification for a given site. The - // \doxygen{otb}{MRFSamplerRandomMAP}, randomly pick one possible value - // according to the MAP probability. + // And to declare these new type: // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet typedef otb::MRFSamplerRandomMAP< InputImageType, LabelledImageType> SamplerType; +// typedef otb::MRFSamplerRandom< InputImageType, LabelledImageType> SamplerType; - // Software Guide : EndCodeSnippet - // Software Guide : BeginLatex - // - // An \doxygen{otb}{MRFOptimizerMetropoli}, which derives from the - // \doxygen{otb}{MRFOptimizer}, is instanciated. The optimizer is in charge - // of accepting or rejecting the value proposed by the sampler. The - // \doxygen{otb}{MRFSamplerRandomMAP}, accept the proposal according to the - // variation of energy it causes and a temperature parameter. - // - // Software Guide : EndLatex // Software Guide : BeginCodeSnippet @@ -182,74 +120,18 @@ int main(int argc, char* argv[] ) // Software Guide : EndCodeSnippet - // Software Guide : BeginLatex - // - // Two energy, deriving from the \doxygen{otb}{MRFEnergy} class need to be instanciated. One energy - // is required for the regularization, taking into account the relashionship between neighborhing pixels - // in the classified image. Here it is done with the \doxygen{otb}{MRFEnergyPotts} which implement - // a Potts model. - // - // The second energy is for the fidelity to the original data. Here it is done with an - // \doxygen{otb}{MRFEnergyGaussianClassification} class, which defines a gaussian model for the data. - // - // Software Guide : EndLatex - - // Software Guide : BeginCodeSnippet - typedef otb::MRFEnergyPotts <LabelledImageType, LabelledImageType> EnergyRegularizationType; typedef otb::MRFEnergyGaussianClassification <InputImageType, LabelledImageType> EnergyFidelityType; - // Software Guide : EndCodeSnippet - - // Software Guide : BeginLatex - // - // The different filters composing our pipeline are created by invoking their - // \code{New()} methods, assigning the results to smart pointers. - // - // Software Guide : EndLatex - - // Software Guide : BeginCodeSnippet - MarkovRandomFieldFilterType::Pointer markovFilter = MarkovRandomFieldFilterType::New(); EnergyRegularizationType::Pointer energyRegularization = EnergyRegularizationType::New(); EnergyFidelityType::Pointer energyFidelity = EnergyFidelityType::New(); OptimizerType::Pointer optimizer = OptimizerType::New(); SamplerType::Pointer sampler = SamplerType::New(); - // Software Guide : EndCodeSnippet - - // Software Guide : BeginLatex - // - // Parameter for the \doxygen{otb}{MRFEnergyGaussianClassification} class, meand - // and standard deviation are created. - // - // Software Guide : EndLatex - - - // Software Guide : BeginCodeSnippet - unsigned int nClass = 4; - itk::VariableLengthVector<double> mean; - itk::VariableLengthVector<double> stdDev; - mean.SetSize(nClass); - stdDev.SetSize(nClass); - mean[0]=10;mean[1]=80;mean[2]=150;mean[3]=220; - stdDev[0]=10;stdDev[1]=10;stdDev[2]=10;stdDev[3]=10; - - // Software Guide : EndCodeSnippet - - - // Software Guide : BeginLatex - // - // Parameters are given to the different class an the sampler, optimizer and - // energies are connected with the Markov filter. - // - // Software Guide : EndLatex - - // Software Guide : BeginCodeSnippet - energyFidelity->SetNumberOfParameters(2*nClass); EnergyFidelityType::ParametersType parameters; parameters.SetSize(energyFidelity->GetNumberOfParameters()); @@ -262,30 +144,26 @@ int main(int argc, char* argv[] ) parameters[6]=220.0;//Class 3 mean parameters[7]=10.0; //Class 3 stde energyFidelity->SetParameters(parameters); - - markovFilter->SetNumberOfClasses(nClass); - markovFilter->SetMaximumNumberOfIterations(atoi(argv[5])); - markovFilter->SetErrorTolerance(-1.0); - markovFilter->SetLambda(atof(argv[4])); - markovFilter->SetNeighborhoodRadius(1); - - markovFilter->SetEnergyRegularization(energyRegularization); - markovFilter->SetEnergyFidelity(energyFidelity); - markovFilter->SetOptimizer(optimizer); - markovFilter->SetSampler(sampler); - // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // - // The pipeline is connected. An \doxygen{itk}{RescaleIntensityImageFilter} - // rescale the classified image before saving it. + // As the \doxygen{otb}{MRFOptimizerICM} does not have any parameters, + // the call to \code{optimizer->SetParameters()} must be removed // // Software Guide : EndLatex - // Software Guide : BeginCodeSnippet + markovFilter->SetNumberOfClasses(nClass); + markovFilter->SetMaximumNumberOfIterations(atoi(argv[4])); + markovFilter->SetErrorTolerance(0.0); + markovFilter->SetLambda(atof(argv[3])); + markovFilter->SetNeighborhoodRadius(1); + + markovFilter->SetEnergyRegularization(static_cast<MarkovRandomFieldFilterType::EnergyRegularizationPointer>(energyRegularization)); + markovFilter->SetEnergyFidelity(static_cast<MarkovRandomFieldFilterType::EnergyFidelityPointer>(energyFidelity)); + markovFilter->SetOptimizer(optimizer); + markovFilter->SetSampler(sampler); - markovFilter->SetTrainingInput(reader2->GetOutput()); markovFilter->SetInput(reader->GetOutput()); typedef itk::RescaleIntensityImageFilter @@ -298,20 +176,14 @@ int main(int argc, char* argv[] ) writer->SetInput( rescaleFilter->GetOutput() ); - // Software Guide : EndCodeSnippet + writer->Update(); // Software Guide : BeginLatex // - // Finally, the pipeline execution is trigerred. + // Apart from these, no further modification is required. // // Software Guide : EndLatex - // Software Guide : BeginCodeSnippet - - writer->Update(); - - // Software Guide : EndCodeSnippet - return 0; } diff --git a/Examples/Markov/MarkovRandomField3Example.cxx b/Examples/Markov/MarkovRandomField3Example.cxx new file mode 100755 index 0000000000000000000000000000000000000000..6ec7d6bfac84581a799cb09af3525f5f8d040ee6 --- /dev/null +++ b/Examples/Markov/MarkovRandomField3Example.cxx @@ -0,0 +1,310 @@ + +/*========================================================================= + + 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. + +=========================================================================*/ +#if defined(_MSC_VER) +#pragma warning ( disable : 4786 ) +#endif + +#ifdef __BORLANDC__ +#define ITK_LEAN_AND_MEAN +#endif + +// Software Guide : BeginCommandLineArgs +// INPUTS: {QB_Suburb.png RandomImage.png} +// OUTPUTS: {MarkovRandomField1.png} +// 1.0 30 1.0 +// Software Guide : EndCommandLineArgs + + +// Software Guide : BeginLatex +// +// This example illustrates the details of the \doxygen{otb}{MarkovRandomFieldFilter}. +// This filter is an application of the Markov Random Fields for classification, +// segmentation or restauration. +// +// This example applies the \doxygen{otb}{MarkovRandomFieldFilter} to +// classify an image into four classes defined by their mean and variance. 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. +// +// The starting state of classification is given by the image proposed as a second +// parameter. It could be a random image. +// +// Software Guide : EndLatex + +#include "otbImageFileReader.h" +#include "otbImageFileWriter.h" +#include "otbImage.h" +#include "otbMarkovRandomFieldFilter.h" +#include "itkRescaleIntensityImageFilter.h" + + +// Software Guide : BeginLatex +// +// The first step toward the use of this filter is the inclusion of the proper +// header files. +// +// Software Guide : EndLatex + +// Software Guide : BeginCodeSnippet +#include "otbMRFEnergy.h" +#include "otbMRFEnergyPotts.h" +#include "otbMRFEnergyGaussianClassification.h" +#include "otbMRFOptimizerMetropolis.h" +#include "otbMRFSamplerRandom.h" +// Software Guide : EndCodeSnippet + + +int main(int argc, char* argv[] ) +{ + + if( argc != 7 ) + { + std::cerr << "Missing Parameters " << std::endl; + std::cerr << "Usage: " << argv[0]; + std::cerr << " inputImage inputInitialization output lambda iterations temperature" << std::endl; + return 1; + } + + + // Software Guide : BeginLatex + // + // Then we must decide what pixel type to use for the image. We + // choose to make all computations with double precision. + // The labelled image is of type unsigned char to allow up to 256 different + // classes. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + const unsigned int Dimension = 2; + + typedef double InternalPixelType; + typedef unsigned char LabelledPixelType; + typedef otb::Image<InternalPixelType, Dimension> InputImageType; + typedef otb::Image<LabelledPixelType, Dimension> LabelledImageType; + + // Software Guide : EndCodeSnippet + + + // Software Guide : BeginLatex + // + // We define a reader for the image to be classified, an initialisation for the + // classification (which could be random) and a writer for the final + // classification. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + typedef otb::ImageFileReader< InputImageType > ReaderType; + typedef otb::ImageFileReader< LabelledImageType > ReaderLabelledType; + typedef otb::ImageFileWriter< LabelledImageType > WriterType; + + ReaderType::Pointer reader = ReaderType::New(); + ReaderLabelledType::Pointer reader2 = ReaderLabelledType::New(); + WriterType::Pointer writer = WriterType::New(); + + const char * inputFilename = argv[1]; + const char * labelledFilename = argv[2]; + const char * outputFilename = argv[3]; + + reader->SetFileName( inputFilename ); + reader2->SetFileName( labelledFilename ); + writer->SetFileName( outputFilename ); + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // Finally, we define the different classes necessary for the Markov classification. + // A \doxygen{otb}{MarkovRandomFieldFilter} is instanciated, this is the + // main class which connect the other to do the Markov classification. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + typedef otb::MarkovRandomFieldFilter + <InputImageType,LabelledImageType> MarkovRandomFieldFilterType; + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // An \doxygen{otb}{MRFSamplerRandomMAP}, which derives from the + // \doxygen{otb}{MRFSampler}, is instanciated. The sampler is in charge of + // proposing a modification for a given site. The + // \doxygen{otb}{MRFSamplerRandomMAP}, randomly pick one possible value + // according to the MAP probability. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + typedef otb::MRFSamplerRandom< InputImageType, LabelledImageType> SamplerType; + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // An \doxygen{otb}{MRFOptimizerMetropoli}, which derives from the + // \doxygen{otb}{MRFOptimizer}, is instanciated. The optimizer is in charge + // of accepting or rejecting the value proposed by the sampler. The + // \doxygen{otb}{MRFSamplerRandomMAP}, accept the proposal according to the + // variation of energy it causes and a temperature parameter. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + typedef otb::MRFOptimizerMetropolis OptimizerType; + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // Two energy, deriving from the \doxygen{otb}{MRFEnergy} class need to be instanciated. One energy + // is required for the regularization, taking into account the relashionship between neighborhing pixels + // in the classified image. Here it is done with the \doxygen{otb}{MRFEnergyPotts} which implement + // a Potts model. + // + // The second energy is for the fidelity to the original data. Here it is done with an + // \doxygen{otb}{MRFEnergyGaussianClassification} class, which defines a gaussian model for the data. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + typedef otb::MRFEnergyPotts + <LabelledImageType, LabelledImageType> EnergyRegularizationType; + typedef otb::MRFEnergyGaussianClassification + <InputImageType, LabelledImageType> EnergyFidelityType; + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // The different filters composing our pipeline are created by invoking their + // \code{New()} methods, assigning the results to smart pointers. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + MarkovRandomFieldFilterType::Pointer markovFilter = MarkovRandomFieldFilterType::New(); + EnergyRegularizationType::Pointer energyRegularization = EnergyRegularizationType::New(); + EnergyFidelityType::Pointer energyFidelity = EnergyFidelityType::New(); + OptimizerType::Pointer optimizer = OptimizerType::New(); + SamplerType::Pointer sampler = SamplerType::New(); + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // Parameter for the \doxygen{otb}{MRFEnergyGaussianClassification} class, meand + // and standard deviation are created. + // + // Software Guide : EndLatex + + + // Software Guide : BeginCodeSnippet + + unsigned int nClass = 4; + energyFidelity->SetNumberOfParameters(2*nClass); + EnergyFidelityType::ParametersType parameters; + parameters.SetSize(energyFidelity->GetNumberOfParameters()); + parameters[0]=10.0; //Class 0 mean + parameters[1]=10.0; //Class 0 stdev + parameters[2]=80.0;//Class 1 mean + parameters[3]=10.0; //Class 1 stdev + parameters[4]=150.0; //Class 2 mean + parameters[5]=10.0; //Class 2 stdev + parameters[6]=220.0;//Class 3 mean + parameters[7]=10.0; //Class 3 stde + energyFidelity->SetParameters(parameters); + + // Software Guide : EndCodeSnippet + + + // Software Guide : BeginLatex + // + // Parameters are given to the different class an the sampler, optimizer and + // energies are connected with the Markov filter. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + + optimizer->SetParameters(atoi(argv[6])); + markovFilter->SetNumberOfClasses(nClass); + markovFilter->SetMaximumNumberOfIterations(atoi(argv[5])); + markovFilter->SetErrorTolerance(0.0); + markovFilter->SetLambda(atof(argv[4])); + markovFilter->SetNeighborhoodRadius(1); + + markovFilter->SetEnergyRegularization(static_cast<MarkovRandomFieldFilterType::EnergyRegularizationPointer>(energyRegularization)); + markovFilter->SetEnergyFidelity(static_cast<MarkovRandomFieldFilterType::EnergyFidelityPointer>(energyFidelity)); + markovFilter->SetOptimizer(optimizer); + markovFilter->SetSampler(sampler); + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // The pipeline is connected. An \doxygen{itk}{RescaleIntensityImageFilter} + // rescale the classified image before saving it. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + markovFilter->SetTrainingInput(reader2->GetOutput()); + markovFilter->SetInput(reader->GetOutput()); + + typedef itk::RescaleIntensityImageFilter + < LabelledImageType, LabelledImageType > RescaleType; + RescaleType::Pointer rescaleFilter = RescaleType::New(); + rescaleFilter->SetOutputMinimum(0); + rescaleFilter->SetOutputMaximum(255); + + rescaleFilter->SetInput( markovFilter->GetOutput() ); + + writer->SetInput( rescaleFilter->GetOutput() ); + + // Software Guide : EndCodeSnippet + + // Software Guide : BeginLatex + // + // Finally, the pipeline execution is trigerred. + // + // Software Guide : EndLatex + + // Software Guide : BeginCodeSnippet + + writer->Update(); + + // Software Guide : EndCodeSnippet + + return 0; + +} + diff --git a/Examples/Markov/otbMarkovExamplesTests.cxx b/Examples/Markov/otbMarkovExamplesTests.cxx index a7bbca718a4112bd17787acdc8c114c4c623cfaa..d37d9c63fa8d3f31bd586af3f9e026c4f294548d 100644 --- a/Examples/Markov/otbMarkovExamplesTests.cxx +++ b/Examples/Markov/otbMarkovExamplesTests.cxx @@ -25,12 +25,17 @@ void RegisterTests() { -REGISTER_TEST(MarkovRandomField1ExampleTest); + REGISTER_TEST(MarkovRandomField1ExampleTest); + REGISTER_TEST(MarkovRandomField2ExampleTest); } #undef main #define main MarkovRandomField1ExampleTest #include "MarkovRandomField1Example.cxx" +#undef main +#define main MarkovRandomField2ExampleTest +#include "MarkovRandomField2Example.cxx" +