Commit a3480e41 authored by Charles Peyrega's avatar Charles Peyrega

ENH: Classification Map Regularization by Majority Voting, new parameter names...

ENH: Classification Map Regularization by Majority Voting, new parameter names in accordance with itkLabelVotingImageFilter
parent 5b6cf21d
......@@ -30,6 +30,6 @@ OTB_CREATE_APPLICATION(NAME ComputeConfusionMatrix
LINK_LIBRARIES OTBIO;OTBCommon;OTBBasicFilters)
OTB_CREATE_APPLICATION(NAME ClassificationRegularisationMajorityVoting
SOURCES otbClassificationRegularisationMajorityVoting.cxx
OTB_CREATE_APPLICATION(NAME ClassificationMapRegularization
SOURCES otbClassificationMapRegularization.cxx
LINK_LIBRARIES OTBIO;OTBCommon;OTBBasicFilters)
......@@ -28,11 +28,11 @@ namespace otb
namespace Wrapper
{
class ClassificationRegularisationMajorityVoting : public Application
class ClassificationMapRegularization : public Application
{
public:
/** Standard class typedefs. */
typedef ClassificationRegularisationMajorityVoting Self;
typedef ClassificationMapRegularization Self;
typedef Application Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
......@@ -40,7 +40,7 @@ public:
/** Standard macro */
itkNewMacro(Self);
itkTypeMacro(ClassificationRegularisationMajorityVoting, otb::Application);
itkTypeMacro(ClassificationMapRegularization, otb::Application);
/** Filters typedef */
typedef unsigned char InputLabelPixelType;
......@@ -61,13 +61,15 @@ public:
private:
void DoInit()
{
SetName("ClassificationRegularisationMajorityVoting");
SetName("ClassificationMapRegularization");
SetDescription("Filters the input labeled image using Majority Voting in a Ball shaped neighbordhood.");
SetDocName("Regularisation of a labeled image by Majority Voting");
SetDocLongDescription("This application filters the input labeled image using Majority Voting in a Ball shaped neighbordhood. Majority Voting takes the more representative value of all the pixels identified by the Ball shaped structuring element and then sets the center pixel to this majority label value.\n-'NoDataValue' is the label of the NOT classified pixels of the input image. These input pixels keep their 'NoDataValue' label in the output image.\n-If the 'UnDefinedValue if multiple majority labels' option is chosen, then 'UnDefinedValue' is the label of the output pixels, for which there are NOT unique majority labels. Otherwise, these output label pixels keep their Original values in the input image.");
SetDocLimitations("The input image must be a single band labeled image. Both radii along Ox and Oy must have a minimum value equal to 1.");
SetDocName("Classification Map Regularization");
SetDocLongDescription("This application filters the input labeled image using Majority Voting in a Ball shaped neighbordhood. Majority Voting takes the more representative value of all the pixels identified by the Ball shaped structuring element and then sets the center pixel to this majority label value.\n\
-NoData is the label of the NOT classified pixels in the input image. These input pixels keep their NoData label in the output image.\n\
-Pixels with more than 1 majority class are marked as Undecided if the parameter 'ip.suvbool == true', or keep their Original labels otherwise.");
SetDocLimitations("The input image must be a single band labeled image. Both structuring element X and Y radii must have a minimum value equal to 1. Please note that the Undecided value must be different from existing labels in the input labeled image.");
SetDocAuthors("OTB-Team");
SetDocSeeAlso("Documentation of the ClassificationRegularisationMajorityVoting application.");
SetDocSeeAlso("Documentation of the ClassificationMapRegularization application.");
AddDocTag(Tags::Learning);
AddDocTag(Tags::Analysis);
......@@ -75,32 +77,38 @@ private:
/** GROUP IO CLASSIFICATION */
AddParameter(ParameterType_Group,"io","Input and output images");
SetParameterDescription("io","This group of parameters allows to set input and output images for Majority Voting regularisation.");
SetParameterDescription("io","This group of parameters allows to set input and output images for classification map regularization by Majority Voting.");
AddParameter(ParameterType_InputImage, "io.in", "Input Image to REGULARIZE");
AddParameter(ParameterType_InputImage, "io.in", "Input classification image");
SetParameterDescription( "io.in", "The input labeled image to regularize.");
AddParameter(ParameterType_OutputImage, "io.out", "Output REGULARIZED Image");
SetParameterDescription( "io.out", "Output regularized labeled image.");
AddParameter(ParameterType_OutputImage, "io.out", "Output regularized image");
SetParameterDescription( "io.out", "The output regularized labeled image.");
SetParameterOutputImagePixelType( "io.out", ImagePixelType_uint8);
AddParameter(ParameterType_Group,"ip","Input parameters");
SetParameterDescription("ip","This group of parameters allows to set input parameters for Majority Voting regularisation.");
AddParameter(ParameterType_Group,"ip","Regularization parameters");
SetParameterDescription("ip","This group allows to set parameters for classification map regularization by Majority Voting.");
AddParameter(ParameterType_Int, "ip.radiusx", "Radius along Ox");
AddParameter(ParameterType_Int, "ip.radiusx", "Structuring Element X Radius");
SetParameterDescription("ip.radiusx", "The Structuring Element X Radius.");
SetDefaultParameterInt("ip.radiusx", 1.0);
AddParameter(ParameterType_Int, "ip.radiusy", "Radius along Oy");
AddParameter(ParameterType_Int, "ip.radiusy", "Structuring Element Y Radius");
SetParameterDescription("ip.radiusy", "The Structuring Element Y Radius.");
SetDefaultParameterInt("ip.radiusy", 1.0);
AddParameter(ParameterType_Empty, "ip.suvbool", "UnDefinedValue if multiple majority labels");
AddParameter(ParameterType_Empty, "ip.suvbool", "Multiple majority: Undecided(X)/Original");
SetParameterDescription("ip.suvbool", "Pixels with more than 1 majority class are marked as Undecided if parameter is checked (true), or keep their Original labels otherwise (false). Please note that the Undecided value must be different from existing labels in the input labeled image.");
AddParameter(ParameterType_Int, "ip.nodatavalue", "Value of the NoDataValue input label");
SetDefaultParameterInt("ip.nodatavalue", 0.0);
AddParameter(ParameterType_Int, "ip.nodatalabel", "Label for the NoData class");
SetParameterDescription("ip.nodatalabel", "Label for the NoData class. Such input pixels keep their NoData label in the output image.");
SetDefaultParameterInt("ip.nodatalabel", 0.0);
AddParameter(ParameterType_Int, "ip.undefinedvalue", "Value of the UnDefinedValue output label");
SetDefaultParameterInt("ip.undefinedvalue", 0.0);
AddParameter(ParameterType_Int, "ip.undecidedlabel", "Label for the Undecided class");
SetParameterDescription("ip.undecidedlabel", "Label for the Undecided class.");
SetDefaultParameterInt("ip.undecidedlabel", 0.0);
AddRAMParameter();
......@@ -110,8 +118,8 @@ private:
SetDocExampleParameterValue("ip.radiusx", "2");
SetDocExampleParameterValue("ip.radiusy", "5");
SetDocExampleParameterValue("ip.suvbool", "true");
SetDocExampleParameterValue("ip.nodatavalue", "10");
SetDocExampleParameterValue("ip.undefinedvalue", "7");
SetDocExampleParameterValue("ip.nodatalabel", "10");
SetDocExampleParameterValue("ip.undecidedlabel", "7");
}
void DoUpdateParameters()
......@@ -138,15 +146,15 @@ private:
m_NeighMajVotingFilter->SetKernel(seBall);
m_NeighMajVotingFilter->SetInput(inImage);
m_NeighMajVotingFilter->SetNoDataValue(GetParameterInt("ip.nodatavalue"));
m_NeighMajVotingFilter->SetUndefinedValue(GetParameterInt("ip.undefinedvalue"));
m_NeighMajVotingFilter->SetLabelForNoDataPixels(GetParameterInt("ip.nodatalabel"));
m_NeighMajVotingFilter->SetLabelForUndecidedPixels(GetParameterInt("ip.undecidedlabel"));
// Set to UnDefinedValue if NOT unique Majority Voting
// Set to Undecided label if NOT unique Majority Voting
if (IsParameterEnabled("ip.suvbool"))
{
m_NeighMajVotingFilter->SetKeepOriginalLabelBool(false);
}
// Keep original label value if NOT unique Majority Voting
// Keep Original label value if NOT unique Majority Voting
else
{
m_NeighMajVotingFilter->SetKeepOriginalLabelBool(true);
......@@ -159,10 +167,10 @@ private:
NeighborhoodMajorityVotingFilterType::Pointer m_NeighMajVotingFilter;
}; //END class ClassificationRegularisationMajorityVoting
}; //END class ClassificationMapRegularization
}//END namespace wrapper
}//END namespace otb
OTB_APPLICATION_EXPORT(otb::Wrapper::ClassificationRegularisationMajorityVoting)
OTB_APPLICATION_EXPORT(otb::Wrapper::ClassificationMapRegularization)
......@@ -25,7 +25,8 @@
#include "itkMorphologyImageFilter.h"
namespace otb {
namespace otb
{
/**
* \class NeighborhoodMajorityVotingImageFilter
......@@ -34,6 +35,13 @@ namespace otb {
* Filters a labeled image using Majority Voting in a specified neighbordhood. Majority Voting takes the
* more representative value of all the pixels identified by the structuring element and then sets the
* center pixel to this label value.
*
* If the maximum number of votes is not unique, i.e., if more than one label have a maximum number of
* votes, AND if the Boolean m_KeepOriginalLabelBool == false, then an "Undecided" label is assigned to that output pixel.
* Otherwise, if m_KeepOriginalLabelBool == true, this output pixel keeps its Original value.
*
* NOT classified input pixels are assumed to belong to the m_LabelForNoDataPixels labeled class.
* Those pixels keep their Original m_LabelForNoDataPixels label in the output image.
*
* The structuring element is assumed to be composed of binary
* values (zero or one). Only elements of the structuring element
......@@ -113,23 +121,23 @@ public:
#endif
//Creates a SetNoDataValue method
virtual void SetNoDataValue(const PixelType _arg)
//Creates a SetLabelForNoDataPixels method
virtual void SetLabelForNoDataPixels(const PixelType _arg)
{
itkDebugMacro("setting NoDataValue to " << _arg);
if (this->m_NoDataValue != _arg)
{
this->m_NoDataValue = _arg;
itkDebugMacro("setting LabelForNoDataPixels to " << _arg);
if (this->m_LabelForNoDataPixels != _arg)
{
this->m_LabelForNoDataPixels = _arg;
m_MajorityVotingBoundaryCondition.SetConstant(m_NoDataValue);
this->OverrideBoundaryCondition(&m_MajorityVotingBoundaryCondition);
m_MajorityVotingBoundaryCondition.SetConstant(m_LabelForNoDataPixels);
this->OverrideBoundaryCondition(&m_MajorityVotingBoundaryCondition);
this->Modified();
}
this->Modified();
}
}
//Creates a SetUndefinedValue method
itkSetMacro(UndefinedValue, PixelType);
//Creates a SetLabelForUndecidedPixels method
itkSetMacro(LabelForUndecidedPixels, PixelType);
//Creates a SetKeepOriginalLabelBool method
itkSetMacro(KeepOriginalLabelBool, bool);
......@@ -158,8 +166,8 @@ private:
// Default boundary condition for majority voting filter, defaults to
DefaultBoundaryConditionType m_MajorityVotingBoundaryCondition;
PixelType m_NoDataValue;
PixelType m_UndefinedValue;
PixelType m_LabelForNoDataPixels;
PixelType m_LabelForUndecidedPixels;
bool m_KeepOriginalLabelBool;
}; // end of class
......
......@@ -33,8 +33,8 @@ namespace otb
template<class TInputImage, class TOutputImage, class TKernel>
NeighborhoodMajorityVotingImageFilter<TInputImage, TOutputImage, TKernel>::NeighborhoodMajorityVotingImageFilter()
{
this->SetNoDataValue(itk::NumericTraits<PixelType>::NonpositiveMin()); //m_NoDataValue = 0
this->SetUndefinedValue(itk::NumericTraits<PixelType>::NonpositiveMin()); //m_UndefinedValue = 0
this->SetLabelForNoDataPixels(itk::NumericTraits<PixelType>::NonpositiveMin()); //m_LabelForNoDataPixels = 0
this->SetLabelForUndecidedPixels(itk::NumericTraits<PixelType>::NonpositiveMin()); //m_LabelForUndecidedPixels = 0
this->SetKeepOriginalLabelBool(true); //m_KeepOriginalLabelBool = true
}
......@@ -56,7 +56,7 @@ const KernelIteratorType kernelEnd)
PixelType centerPixel = nit.GetCenterPixel();
if (centerPixel != m_NoDataValue)
if (centerPixel != m_LabelForNoDataPixels)
{
for (i = 0, kernel_it = kernelBegin; kernel_it < kernelEnd; ++kernel_it, ++i)
{
......@@ -64,13 +64,13 @@ const KernelIteratorType kernelEnd)
// in the image
PixelType label = nit.GetPixel(i);
if ((*kernel_it > itk::NumericTraits<KernelPixelType>::Zero) && (label != m_NoDataValue))
if ((*kernel_it > itk::NumericTraits<KernelPixelType>::Zero) && (label != m_LabelForNoDataPixels))
{
// note we use GetPixel() on the SmartNeighborhoodIterator to
// respect boundary conditions
//If the current label has already been added to the histogram histoNeigh
if(histoNeigh.count(label) > 0)
if (histoNeigh.count(label) > 0)
{
histoNeigh[label]++;
}
......@@ -97,23 +97,23 @@ const KernelIteratorType kernelEnd)
{
if ( (histoIt->second == majorityFreq) && (histoIt->first != majorityLabel) )
{
if(m_KeepOriginalLabelBool == true)
if (m_KeepOriginalLabelBool == true)
{
majorityLabel = centerPixel;
}
else
{
majorityLabel = m_UndefinedValue;
majorityLabel = m_LabelForUndecidedPixels;
}
break;
}
}
}//END if (centerPixel != m_NoDataValue)
}//END if (centerPixel != m_LabelForNoDataPixels)
//If (centerPixel == m_NoDataValue)
//If (centerPixel == m_LabelForNoDataPixels)
else
{
majorityLabel = m_NoDataValue;
majorityLabel = m_LabelForNoDataPixels;
}
return majorityLabel;
......
......@@ -420,15 +420,15 @@ OTB_TEST_APPLICATION(NAME apTvComputeConfusionMatrixR
# ${TEMP}/apTvComputeConfusionMatrixTconfusionROut.txt
#)
OTB_TEST_APPLICATION(NAME apTvClassificationRegMajorityVoting
APP ClassificationRegularisationMajorityVoting
OTB_TEST_APPLICATION(NAME apTvClassificationMapRegularization
APP ClassificationMapRegularization
OPTIONS -io.in ${INPUTDATA}/Classification/QB_1_ortho_4Cls_N_Classified_OTB.tif
-io.out ${TEMP}/QB_1_ortho_4Cls_N_Classified_OTB_NMV_x2_y5_nodv10_undv7_APP.tif
-ip.radiusx 2
-ip.radiusy 5
-ip.suvbool true
-ip.nodatavalue 10
-ip.undefinedvalue 7
-ip.nodatalabel 10
-ip.undecidedlabel 7
VALID --compare-image ${NOTOL}
${BASELINE}/QB_1_ortho_4Cls_N_Classified_OTB_NMV_x2_y5_nodv10_undv7.tif
${TEMP}/QB_1_ortho_4Cls_N_Classified_OTB_NMV_x2_y5_nodv10_undv7_APP.tif
......
......@@ -657,8 +657,8 @@ otbNeighborhoodMajorityVotingImageFilterTest
false #KeepOriginalLabelBool
2 #xRadius
5 #yRadius
10 #NoDataValue
7 #UndefinedValue
10 #LabelForNoDataPixels
7 #LabelForUndecidedPixels
)
......
......@@ -68,39 +68,39 @@ int otbNeighborhoodMajorityVotingImageFilterTest(int argc, char* argv[])
BallStructuringType seBall;
RadiusType rad;
if (argc >= 3)
std::string KeepOriginalLabelBoolStr = argv[3];
if (KeepOriginalLabelBoolStr.compare("true") == 0)
{
std::string KeepOriginalLabelBoolStr = argv[3];
if (KeepOriginalLabelBoolStr.compare("true") == 0)
{
NeighMajVotingFilter->SetKeepOriginalLabelBool(true);
}
else
{
NeighMajVotingFilter->SetKeepOriginalLabelBool(false);
}
NeighMajVotingFilter->SetKeepOriginalLabelBool(true);
}
else
{
NeighMajVotingFilter->SetKeepOriginalLabelBool(false);
}
if (argc >= 5)
{
rad[0] = atoi(argv[4]);
rad[1] = atoi(argv[5]);
if (argc >= 5)
if (argc >= 6)
{
rad[0] = atoi(argv[4]);
rad[1] = atoi(argv[5]);
NeighMajVotingFilter->SetLabelForNoDataPixels(atoi(argv[6]));
if (argc >= 6)
if (argc >= 7)
{
NeighMajVotingFilter->SetNoDataValue(atoi(argv[6]));
if (argc >= 7)
{
NeighMajVotingFilter->SetUndefinedValue(atoi(argv[7]));
}
NeighMajVotingFilter->SetLabelForUndecidedPixels(atoi(argv[7]));
}
}
else
{
rad[0] = 1;
rad[1] = 1;
}
}
else
{
rad[0] = 1;
rad[1] = 1;
}
seBall.SetRadius(rad);
seBall.CreateStructuringElement();
......
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