diff --git a/Data/Baseline/OTB/Images/apTvUtSmoothingTestAnisotropic.tif b/Data/Baseline/OTB/Images/apTvUtSmoothingTestAnisotropic.tif new file mode 100644 index 0000000000000000000000000000000000000000..5336d199981b5d04949f5975d7db85891472cc02 --- /dev/null +++ b/Data/Baseline/OTB/Images/apTvUtSmoothingTestAnisotropic.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdd0ce0f98ec479767e9e4cbb8f118753963f9a91c689870c3f02758de94d15e +size 3422183 diff --git a/Data/Baseline/OTB/Images/apTvUtSmoothingTestGaussian.tif b/Data/Baseline/OTB/Images/apTvUtSmoothingTestGaussian.tif new file mode 100644 index 0000000000000000000000000000000000000000..539c8486c84743e13cdaccf1c654fd11e3191975 --- /dev/null +++ b/Data/Baseline/OTB/Images/apTvUtSmoothingTestGaussian.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a9e56c55f2cb4f16ad31b762f1a38283c664d5570671fdf5f8a905f03a53a13 +size 3308861 diff --git a/Data/Input/apTvUtSmoothingTest_OutXML.xml b/Data/Input/apTvUtSmoothingTest_OutXML.xml deleted file mode 100644 index 2f95025e38bfb54bf6b8d5d9accf3e91b02c62f4..0000000000000000000000000000000000000000 --- a/Data/Input/apTvUtSmoothingTest_OutXML.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" ?> -<OTB> - <version>3.18</version> - <build>18-05-2013</build> - <platform>Linux</platform> - <application> - <name>Smoothing</name> - <descr>Apply a smoothing filter to an image</descr> - <doc> - <name>Smoothing</name> - <longdescr>This application applies smoothing filter to an image. Either gaussian, mean, or anisotropic diffusion are available.</longdescr> - <authors>OTB-Team</authors> - <limitations>None</limitations> - <seealso> </seealso> - <tags> - <tag>Image Filtering</tag> - </tags> - </doc> - <parameter mandatory="true"> - <key>in</key> - <type>InputImage</type> - <name>Input Image</name> - <value>/home/rashad/repos/orfeo/OTB-Data/Input/poupees.tif</value> - </parameter> - <parameter mandatory="true"> - <key>out</key> - <type>OutputImage</type> - <name>Output Image</name> - <value>/home/rashad/repos/orfeo/build/OTB_/test-build/Testing/Temporary/apTvUtSmoothingTest_OutXML.tif</value> - </parameter> - <parameter mandatory="true"> - <key>type</key> - <type>Choice</type> - <name>Smoothing Type</name> - <value>mean</value> - </parameter> - </application> -</OTB> diff --git a/Modules/Applications/AppFiltering/app/otbFastNLMeans.cxx b/Modules/Applications/AppFiltering/app/otbFastNLMeans.cxx index 3ed27ed028bfe43d0e1c27e626c9ab6d155125a3..c6e12f241bdadc42a6f1852289d111f78c37a4cb 100644 --- a/Modules/Applications/AppFiltering/app/otbFastNLMeans.cxx +++ b/Modules/Applications/AppFiltering/app/otbFastNLMeans.cxx @@ -59,7 +59,7 @@ private: "This filter relies on integral images. Overflow may happen though the risk is limited " " by OTB mechanism which process data by chunks."); SetDocAuthors("OTB-Team"); - SetDocSeeAlso(" "); + SetDocSeeAlso("Smoothing"); AddDocTag(Tags::Filter); // Parameter declarations @@ -110,25 +110,25 @@ private: void DoExecute() override { - // Get the input image - ImageType::Pointer imIn = this->GetParameterFloatImage("in"); - float sigma = this->GetParameterFloat("sig"); - float cutoffDistance = this->GetParameterFloat("thresh"); - int halfPatchSize = this->GetParameterInt("patchradius"); - int halfSearchSize = this->GetParameterInt("searchradius"); - NLMeansFilterType::Pointer nlMeansFilter = NLMeansFilterType::New(); + // Get the input parameters + const auto imIn = this->GetParameterFloatImage("in"); + const auto sigma = this->GetParameterFloat("sig"); + const auto cutoffDistance = this->GetParameterFloat("thresh"); + const auto halfPatchSize = this->GetParameterInt("patchradius"); + const auto halfSearchSize = this->GetParameterInt("searchradius"); + + auto nlMeansFilter = NLMeansFilterType::New(); + nlMeansFilter->SetInput(imIn); nlMeansFilter->SetSigma(sigma); nlMeansFilter->SetHalfWindowSize(halfPatchSize); nlMeansFilter->SetHalfSearchSize(halfSearchSize); nlMeansFilter->SetCutOffDistance(cutoffDistance); - m_FilterRef = nlMeansFilter; SetParameterOutputImage("out", nlMeansFilter->GetOutput()); RegisterPipeline(); } - itk::LightObject::Pointer m_FilterRef; }; // end class } // namespace Wrapper diff --git a/Modules/Applications/AppFiltering/app/otbSmoothing.cxx b/Modules/Applications/AppFiltering/app/otbSmoothing.cxx index f465172b66a2ad441e7c12888d917409785a1d89..4803bc7e934cfe09e825ea39c82f1d571284b718 100644 --- a/Modules/Applications/AppFiltering/app/otbSmoothing.cxx +++ b/Modules/Applications/AppFiltering/app/otbSmoothing.cxx @@ -62,11 +62,21 @@ private: SetDocLongDescription( "This application applies a smoothing filter to an " - "image. Three methods can be used: a gaussian filter , a mean filter " - ", or an anisotropic diffusion using the Perona-Malik algorithm."); + "image. Three methods can be used: a mean filter, a gaussian filter based on [1]" + ", or an anisotropic diffusion using the Perona-Malik algorithm [2]."); SetDocLimitations("None"); SetDocAuthors("OTB-Team"); - SetDocSeeAlso(" "); + SetDocSeeAlso("FastNLMeans \n" + "[1] Tony Lindeberg Discrete " + "Scale-Space Theory and the Scale-Space Primal Sketch. Dissertation. Royal " + "Institute of Technology, Stockholm, Sweden. May 1991 \n" + "[2] Pietro Perona and Jitendra Malik, " + "Scale-space and edge detection using anisotropic diffusion, " + "IEEE Transactions on Pattern Analysis Machine Intelligence, vol. 12, pp. 629-639, 1990. \n" + "itk::MeanImageFilter (mean mode)\n" + "itk::DiscreteGaussianImageFilter (gaussian mode)\n" + "itk::GradientAnisotropicDiffusionImageFilter (anidif mode)." + ); AddDocTag(Tags::Filter); @@ -86,13 +96,21 @@ private: AddChoice("type.gaussian", "Gaussian"); - AddParameter(ParameterType_Float, "type.gaussian.radius", "Radius"); - SetParameterDescription("type.gaussian.radius", "Standard deviation of the gaussian kernel used to filter the image"); - SetDefaultParameterFloat("type.gaussian.radius", 2.0); - // TODO rename this parameter + AddParameter(ParameterType_Float, "type.gaussian.stdev", "Standard deviation"); + SetParameterDescription("type.gaussian.stdev", "Standard deviation of the gaussian kernel used to filter the image"); + SetDefaultParameterFloat("type.gaussian.stdev", 2.0); - AddChoice("type.anidif", "Anisotropic Diffusion"); + AddParameter(ParameterType_Float, "type.gaussian.maxerror", "Maximum error"); + SetParameterDescription("type.gaussian.maxerror", "The algorithm will size the discrete kernel so that the error " + "resulting from truncation of the kernel is no greater than maxerror."); + SetDefaultParameterFloat("type.gaussian.maxerror", 0.01); + + AddParameter(ParameterType_Int, "type.gaussian.maxwidth", "Maximum kernel width"); + SetParameterDescription("type.gaussian.maxwidth", "Set the kernel to be no wider than maxwidth pixels, " + "even if type.gaussian.maxerror demands it."); + SetDefaultParameterInt("type.gaussian.maxwidth", 32); + AddChoice("type.anidif", "Anisotropic Diffusion"); AddParameter(ParameterType_Float, "type.anidif.timestep", "Time Step"); SetParameterDescription("type.anidif.timestep", "Time step that will be used to discretize the diffusion equation"); @@ -139,79 +157,79 @@ private: void DoExecute() override { - GetLogger()->Debug("Entering DoExecute\n"); - - - FloatVectorImageType::Pointer inImage = GetParameterImage("in"); + const auto inImage = GetParameterImage("in"); switch (GetParameterInt("type")) { case Smoothing_Mean: { - GetLogger()->Debug("Using mean"); + otbAppLogINFO("Using mean smoothing"); typedef itk::MeanImageFilter<ImageType, ImageType> MeanFilterType; typedef otb::PerBandVectorImageFilter<FloatVectorImageType, FloatVectorImageType, MeanFilterType> PerBandMeanFilterType; - PerBandMeanFilterType::Pointer perBand = PerBandMeanFilterType::New(); + auto perBand = PerBandMeanFilterType::New(); perBand->SetInput(inImage); MeanFilterType::InputSizeType radius; radius.Fill(GetParameterInt("type.mean.radius")); perBand->GetFilter()->SetRadius(radius); - perBand->UpdateOutputInformation(); - m_FilterRef = perBand; + SetParameterOutputImage("out", perBand->GetOutput()); + + RegisterPipeline(); } break; case Smoothing_Gaussian: { - GetLogger()->Debug("Using gaussian"); + otbAppLogINFO("Using gaussian smoothing"); typedef itk::DiscreteGaussianImageFilter<ImageType, ImageType> DiscreteGaussianFilterType; typedef otb::PerBandVectorImageFilter<FloatVectorImageType, FloatVectorImageType, DiscreteGaussianFilterType> PerBandDiscreteGaussianFilterType; - PerBandDiscreteGaussianFilterType::Pointer perBand = PerBandDiscreteGaussianFilterType::New(); + auto perBand = PerBandDiscreteGaussianFilterType::New(); perBand->SetInput(inImage); - double radius = GetParameterFloat("type.gaussian.radius"); - double variance = radius * radius; + const auto stdev = GetParameterFloat("type.gaussian.stdev"); + const auto variance = stdev * stdev; + perBand->GetFilter()->SetVariance(variance); perBand->GetFilter()->SetUseImageSpacing(false); - perBand->UpdateOutputInformation(); - m_FilterRef = perBand; + perBand->GetFilter()->SetMaximumError(GetParameterFloat("type.gaussian.maxerror")); + perBand->GetFilter()->SetMaximumKernelWidth(GetParameterInt("type.gaussian.maxwidth")); + SetParameterOutputImage("out", perBand->GetOutput()); + + RegisterPipeline(); } break; case Smoothing_Anisotropic: { - GetLogger()->Debug("Using anisotropic diffusion"); + otbAppLogINFO("Using anisotropic diffusion smoothing"); typedef itk::GradientAnisotropicDiffusionImageFilter<ImageType, ImageType> GradientAnisotropicDiffusionFilterType; typedef otb::PerBandVectorImageFilter<FloatVectorImageType, FloatVectorImageType, GradientAnisotropicDiffusionFilterType> PerBandGradientAnisotropicDiffusionFilterType; - PerBandGradientAnisotropicDiffusionFilterType::Pointer perBand = PerBandGradientAnisotropicDiffusionFilterType::New(); + auto perBand = PerBandGradientAnisotropicDiffusionFilterType::New(); perBand->SetInput(inImage); - const int aniDifNbIter = GetParameterInt("type.anidif.nbiter"); + const auto aniDifNbIter = GetParameterInt("type.anidif.nbiter"); perBand->GetFilter()->SetNumberOfIterations(static_cast<unsigned int>(aniDifNbIter)); - const float aniDifTimeStep = GetParameterFloat("type.anidif.timestep"); + const auto aniDifTimeStep = GetParameterFloat("type.anidif.timestep"); perBand->GetFilter()->SetTimeStep(static_cast<double>(aniDifTimeStep)); perBand->GetFilter()->SetConductanceParameter(GetParameterFloat("type.anidif.conductance")); perBand->GetFilter()->SetUseImageSpacing(false); - perBand->UpdateOutputInformation(); - m_FilterRef = perBand; SetParameterOutputImage("out", perBand->GetOutput()); + + RegisterPipeline(); } break; } } - - itk::LightObject::Pointer m_FilterRef; }; } } diff --git a/Modules/Applications/AppFiltering/test/CMakeLists.txt b/Modules/Applications/AppFiltering/test/CMakeLists.txt index 84ce8527671b5e9ecf1540dd0d80216297cfa707..73fad582ae6d2870150d37b95da902c6761882ed 100644 --- a/Modules/Applications/AppFiltering/test/CMakeLists.txt +++ b/Modules/Applications/AppFiltering/test/CMakeLists.txt @@ -20,9 +20,20 @@ otb_module_test() #----------- Smoothing TESTS ---------------- + +otb_test_application(NAME apTvUtSmoothingTest_OutXML + APP Smoothing + OPTIONS -in ${INPUTDATA}/poupees.tif + -out ${TEMP}/apTvUtSmoothingTest_OutXML.tif + -type mean + -outxml ${TEMP}/apTvUtSmoothingTest_OutXML.xml + VALID --compare-image ${NOTOL} + ${BASELINE}/apTvUtSmoothingTest.tif + ${TEMP}/apTvUtSmoothingTest_OutXML.tif) + otb_test_application(NAME apTvUtSmoothingTest_InXML APP Smoothing - OPTIONS -inxml ${INPUTDATA}/apTvUtSmoothingTest_OutXML.xml + OPTIONS -inxml ${TEMP}/apTvUtSmoothingTest_OutXML.xml -in ${INPUTDATA}/poupees.tif -out ${TEMP}/apTvUtSmoothingTest_InXML.tif -type mean @@ -30,24 +41,32 @@ otb_test_application(NAME apTvUtSmoothingTest_InXML ${BASELINE}/apTvUtSmoothingTest.tif ${TEMP}/apTvUtSmoothingTest_InXML.tif) -otb_test_application(NAME apTvUtSmoothingTest +set_tests_properties( apTvUtSmoothingTest_InXML + PROPERTIES DEPENDS apTvUtSmoothingTest_OutXML) + +otb_test_application(NAME apTvUtSmoothingTestGaussian APP Smoothing OPTIONS -in ${INPUTDATA}/poupees.tif - -out ${TEMP}/apTvUtSmoothingTest.tif - -type mean + -out ${TEMP}/apTvUtSmoothingTestGaussian.tif + -type gaussian + -type.gaussian.stdev 2.0 + -type.gaussian.maxerror 0.1 + -type.gaussian.maxwidth 64 VALID --compare-image ${NOTOL} - ${BASELINE}/apTvUtSmoothingTest.tif - ${TEMP}/apTvUtSmoothingTest.tif) + ${BASELINE}/apTvUtSmoothingTestGaussian.tif + ${TEMP}/apTvUtSmoothingTestGaussian.tif) -otb_test_application(NAME apTvUtSmoothingTest_OutXML +otb_test_application(NAME apTvUtSmoothingTestAnisotropic APP Smoothing OPTIONS -in ${INPUTDATA}/poupees.tif - -out ${TEMP}/apTvUtSmoothingTest_OutXML.tif - -type mean - -outxml ${TEMP}/apTvUtSmoothingTest_OutXML.xml - VALID --compare-image ${NOTOL} - ${BASELINE}/apTvUtSmoothingTest.tif - ${TEMP}/apTvUtSmoothingTest_OutXML.tif) + -out ${TEMP}/apTvUtSmoothingTestAnisotropic.tif + -type anidif + -type.anidif.timestep 0.125 + -type.anidif.nbiter 10 + -type.anidif.conductance 1. + VALID --compare-image ${EPSILON_6} + ${BASELINE}/apTvUtSmoothingTestAnisotropic.tif + ${TEMP}/apTvUtSmoothingTestAnisotropic.tif) #----------- Contrast TESTS ---------------- @@ -115,7 +134,3 @@ otb_test_application(NAME nlMeansTest_base ${BASELINE}/GomaAvant_NLMeans.tif ${TEMP}/GomaAvant_NLMeans.tif) - - - -