Commit f6d4e7bb authored by Cédric Traizet's avatar Cédric Traizet

Merge branch 'smoothing_app_enhancement' into 'develop'

Smoothing application enhancement

Closes #1961

See merge request !673
parents 6c2850fc c0f61f42
Pipeline #3678 passed with stages
in 61 minutes and 17 seconds
<?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>
......@@ -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
......
......@@ -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;
};
}
}
......
......@@ -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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment