Commit fbc29e9e authored by Charles Peyrega's avatar Charles Peyrega

ENH: Renaming TrainImagesClassifier applications and add a confusion matrix output file

parent 2e348653
......@@ -35,8 +35,8 @@ OTB_CREATE_APPLICATION(NAME ClassificationMapRegularization
LINK_LIBRARIES OTBIO;OTBCommon;OTBBasicFilters)
IF(OTB_USE_OPENCV)
OTB_CREATE_APPLICATION(NAME TrainMachineLearningImagesClassifier
SOURCES otbTrainMachineLearningImagesClassifier.cxx otbTrainSVM.cxx otbTrainLibSVM.cxx otbTrainBoost.cxx
OTB_CREATE_APPLICATION(NAME TrainImagesClassifier
SOURCES otbTrainImagesClassifier.cxx otbTrainSVM.cxx otbTrainLibSVM.cxx otbTrainBoost.cxx
otbTrainDecisionTree.cxx otbTrainGradientBoostedTree.cxx otbTrainNeuralNetwork.cxx otbTrainNormalBayes.cxx
otbTrainRandomForests.cxx otbTrainKNN.cxx
LINK_LIBRARIES OTBIO;OTBCommon;OTBBasicFilters;OTBFeatureExtraction;OTBLearning;OTBMachineLearning)
......
......@@ -15,14 +15,14 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitBoostParams()
void TrainImagesClassifier::InitBoostParams()
{
AddChoice("classifier.boost", "Boost classifier");
SetParameterDescription("classifier.boost", "This group of parameters allows to set Boost classifier parameters."
......@@ -55,7 +55,7 @@ namespace Wrapper
}
void TrainMachineLearningImagesClassifier::TrainBoost(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
void TrainImagesClassifier::TrainBoost(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
{
BoostType::Pointer boostClassifier = BoostType::New();
boostClassifier->SetInputListSample(trainingListSample);
......
......@@ -15,13 +15,13 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitDecisionTreeParams()
void TrainImagesClassifier::InitDecisionTreeParams()
{
AddChoice("classifier.dt", "Decision Tree classifier");
SetParameterDescription("classifier.dt",
......@@ -80,7 +80,7 @@ void TrainMachineLearningImagesClassifier::InitDecisionTreeParams()
}
void TrainMachineLearningImagesClassifier::TrainDecisionTree(ListSampleType::Pointer trainingListSample,
void TrainImagesClassifier::TrainDecisionTree(ListSampleType::Pointer trainingListSample,
LabelListSampleType::Pointer trainingLabeledListSample)
{
DecisionTreeType::Pointer classifier = DecisionTreeType::New();
......
......@@ -15,13 +15,13 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitGradientBoostedTreeParams()
void TrainImagesClassifier::InitGradientBoostedTreeParams()
{
AddChoice("classifier.gbt", "Gradient Boosted Tree classifier");
SetParameterDescription(
......@@ -65,7 +65,7 @@ void TrainMachineLearningImagesClassifier::InitGradientBoostedTreeParams()
}
void TrainMachineLearningImagesClassifier::TrainGradientBoostedTree(
void TrainImagesClassifier::TrainGradientBoostedTree(
ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
{
GradientBoostedTreeType::Pointer classifier = GradientBoostedTreeType::New();
......
......@@ -15,26 +15,35 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::DoInit()
void TrainImagesClassifier::DoInit()
{
SetName("TrainMachineLearningImagesClassifier");
SetName("TrainImagesClassifier");
SetDescription(
"Train a classifier (available in OpenCV machine learning) from multiple pairs of images and training vector data.");
// Documentation
SetDocName("Train an OpenCV classifier from multiple images");
SetDocLongDescription(
"This application performs a classifier training from multiple pairs of input images and training vector data. Samples are composed of pixel values in each band optionally centered and reduced using XML statistics file produced by the ComputeImagesStatistics application.\n The training vector data must contain polygons with a positive integer field representing the class label. Name of the field can be set using the \"Class label field\" parameter. Training and validation sample lists are built such that each class is equally represented in both lists. One parameter allows to control the ratio between the number of samples in training and validation sets. Two parameters allow to manage the size of the training and validation sets per class and per image.\n Several classifier parameters can be set depending on the classifier. In the validation process, the confusion matrix is organized the following way: rows = reference labels, columns = produced labels.");
"This application performs a classifier training from multiple pairs of input images and training vector data. "
"Samples are composed of pixel values in each band optionally centered and reduced using XML statistics file produced by "
"the ComputeImagesStatistics application.\n The training vector data must contain polygons with a positive integer field "
"representing the class label. Name of the field can be set using the \"Class label field\" parameter. Training and validation "
"sample lists are built such that each class is equally represented in both lists. One parameter allows to control the ratio "
"between the number of samples in training and validation sets. Two parameters allow to manage the size of the training and "
"validation sets per class and per image.\n Several classifier parameters can be set depending on the classifier. In the "
"validation process, the confusion matrix is organized the following way: rows = reference labels, columns = produced labels. "
"In the header of the optional confusion matrix output file, the validation (reference) and predicted (produced) class labels"
" are ordered according to the rows/columns of the confusion matrix.");
SetDocLimitations("None");
SetDocAuthors("OTB-Team");
SetDocSeeAlso(" OpenCV documentation for machine learning http://docs.opencv.org/modules/ml/doc/ml.html ");
SetDocSeeAlso("OpenCV documentation for machine learning http://docs.opencv.org/modules/ml/doc/ml.html ");
AddDocTag(Tags::Learning);
......@@ -52,6 +61,10 @@ namespace Wrapper
AddParameter(ParameterType_OutputFilename, "io.out", "Output model");
SetParameterDescription("io.out", "Output file containing the model estimated");
AddParameter(ParameterType_OutputFilename, "io.confmatout", "Confusion matrix output");
SetParameterDescription("io.confmatout", "Filename to store the output confusion matrix (csv format)");
MandatoryOff("io.confmatout");
// Elevation
ElevationParametersHandler::AddElevationParameters(this, "elev");
......@@ -125,14 +138,16 @@ namespace Wrapper
SetDocExampleParameterValue("sample.vtr", "0.5");
SetDocExampleParameterValue("svm.opt", "true");
SetDocExampleParameterValue("io.out", "svmModelQB1.svm");
SetDocExampleParameterValue("io.confmatout", "svmConfusionMatrixQB1.csv");
}
void TrainMachineLearningImagesClassifier::DoUpdateParameters()
void TrainImagesClassifier::DoUpdateParameters()
{
// Nothing to do here : all parameters are independent
}
void TrainMachineLearningImagesClassifier::LogConfusionMatrix(ConfusionMatrixCalculatorType* confMatCalc)
void TrainImagesClassifier::LogConfusionMatrix(ConfusionMatrixCalculatorType* confMatCalc)
{
ConfusionMatrixCalculatorType::ConfusionMatrixType matrix = confMatCalc->GetConfusionMatrix();
......@@ -204,7 +219,7 @@ namespace Wrapper
otbAppLogINFO("Confusion matrix (rows = reference labels, columns = produced labels):\n" << os.str());
}
void TrainMachineLearningImagesClassifier::Classify(ListSampleType::Pointer validationListSample, LabelListSampleType::Pointer predictedList)
void TrainImagesClassifier::Classify(ListSampleType::Pointer validationListSample, LabelListSampleType::Pointer predictedList)
{
//Classification
ModelPointerType model = MachineLearningModelFactoryType::CreateMachineLearningModel(GetParameterString("io.out"),
......@@ -215,7 +230,7 @@ namespace Wrapper
model->PredictAll();
}
void TrainMachineLearningImagesClassifier::DoExecute()
void TrainImagesClassifier::DoExecute()
{
GetLogger()->Debug("Entering DoExecute\n");
//Create training and validation for list samples and label list samples
......@@ -436,7 +451,94 @@ namespace Wrapper
"F-score of class [" << classLabel << "] vs all: " << confMatCalc->GetFScores()[itClasses] << "\n");
}
otbAppLogINFO("Global performance, Kappa index: " << confMatCalc->GetKappaIndex());
// TODO: implement hyperplan distance classifier and performance validation (cf. object detection) ?
if (this->HasValue("io.confmatout"))
{
// Writing the confusion matrix in the output .CSV file
MapOfClassesType::iterator itMapOfClassesValid, itMapOfClassesPred;
ClassLabelType labelValid = 0;
ConfusionMatrixType confusionMatrix = confMatCalc->GetConfusionMatrix();
MapOfClassesType mapOfClassesValid = confMatCalc->GetMapOfClasses();
unsigned int nbClassesPred = mapOfClassesValid.size();
/////////////////////////////////////////////
// Filling the 2 headers for the output file
const std::string commentValidStr = "#Reference labels (rows):";
const std::string commentPredStr = "#Produced labels (columns):";
const char separatorChar = ',';
std::ostringstream ossHeaderValidLabels, ossHeaderPredLabels;
// Filling ossHeaderValidLabels and ossHeaderPredLabels for the output file
ossHeaderValidLabels << commentValidStr;
ossHeaderPredLabels << commentPredStr;
itMapOfClassesValid = mapOfClassesValid.begin();
while (itMapOfClassesValid != mapOfClassesValid.end())
{
// labels labelValid of mapOfClassesValid are already sorted
labelValid = itMapOfClassesValid->first;
otbAppLogINFO("mapOfClassesValid[" << labelValid << "] = " << itMapOfClassesValid->second);
ossHeaderValidLabels << labelValid;
ossHeaderPredLabels << labelValid;
++itMapOfClassesValid;
if (itMapOfClassesValid != mapOfClassesValid.end())
{
ossHeaderValidLabels << separatorChar;
ossHeaderPredLabels << separatorChar;
}
else
{
ossHeaderValidLabels << std::endl;
ossHeaderPredLabels << std::endl;
}
}
std::ofstream outFile;
outFile.open(this->GetParameterString("io.confmatout").c_str());
outFile << std::fixed;
outFile.precision(10);
/////////////////////////////////////
// Writing the 2 headers
outFile << ossHeaderValidLabels.str();
outFile << ossHeaderPredLabels.str();
/////////////////////////////////////
int indiceLabelValid = 0, indiceLabelPred = 0;
for (itMapOfClassesValid = mapOfClassesValid.begin(); itMapOfClassesValid != mapOfClassesValid.end(); ++itMapOfClassesValid)
{
// labels labelValid = itMapOfClassesValid->first of mapOfClassesRef are already sorted
indiceLabelPred = 0;
for (itMapOfClassesPred = mapOfClassesValid.begin(); itMapOfClassesPred != mapOfClassesValid.end(); ++itMapOfClassesPred)
{
// Writing the ordered confusion matrix in the output file
outFile << confusionMatrix(indiceLabelValid, indiceLabelPred);
if (indiceLabelPred < (nbClassesPred - 1))
{
outFile << separatorChar;
}
else
{
outFile << std::endl;
}
++indiceLabelPred;
}
++indiceLabelValid;
}
outFile.close();
} // END if (this->HasValue("io.confmatout"))
// TODO: implement hyperplane distance classifier and performance validation (cf. object detection) ?
}
......@@ -444,4 +546,4 @@ namespace Wrapper
}
}
OTB_APPLICATION_EXPORT(otb::Wrapper::TrainMachineLearningImagesClassifier)
OTB_APPLICATION_EXPORT(otb::Wrapper::TrainImagesClassifier)
......@@ -76,11 +76,11 @@ namespace otb
namespace Wrapper
{
class TrainMachineLearningImagesClassifier: public Application
class TrainImagesClassifier: public Application
{
public:
/** Standard class typedefs. */
typedef TrainMachineLearningImagesClassifier Self;
typedef TrainImagesClassifier Self;
typedef Application Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
......@@ -88,7 +88,7 @@ public:
/** Standard macro */
itkNewMacro(Self)
itkTypeMacro(TrainMachineLearningImagesClassifier, otb::Application)
itkTypeMacro(TrainImagesClassifier, otb::Application)
typedef otb::Image<FloatVectorImageType::InternalPixelType, 2> ImageReaderType;
......@@ -129,6 +129,10 @@ public:
// Estimate performance on validation sample
typedef otb::ConfusionMatrixCalculator<LabelListSampleType, LabelListSampleType> ConfusionMatrixCalculatorType;
typedef ConfusionMatrixCalculatorType::ConfusionMatrixType ConfusionMatrixType;
typedef ConfusionMatrixCalculatorType::MapOfClassesType MapOfClassesType;
typedef ConfusionMatrixCalculatorType::ClassLabelType ClassLabelType;
// VectorData projection filter
typedef otb::VectorDataProjectionFilter<VectorDataType, VectorDataType> VectorDataProjectionFilterType;
......@@ -138,7 +142,7 @@ public:
protected:
using Superclass::AddParameter;
friend void InitSVMParams(TrainMachineLearningImagesClassifier & app);
friend void InitSVMParams(TrainImagesClassifier & app);
private:
void DoInit();
......
......@@ -15,14 +15,14 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitKNNParams()
void TrainImagesClassifier::InitKNNParams()
{
AddChoice("classifier.knn", "KNN classifier");
SetParameterDescription("classifier.knn", "This group of parameters allows to set KNN classifier parameters."
......@@ -36,7 +36,7 @@ namespace Wrapper
}
void TrainMachineLearningImagesClassifier::TrainKNN(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
void TrainImagesClassifier::TrainKNN(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
{
KNNType::Pointer knnClassifier = KNNType::New();
knnClassifier->SetInputListSample(trainingListSample);
......
......@@ -15,14 +15,14 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitLibSVMParams()
void TrainImagesClassifier::InitLibSVMParams()
{
AddChoice("classifier.libsvm", "LibSVM classifier");
SetParameterDescription("classifier.libsvm", "This group of parameters allows to set SVM classifier parameters.");
......@@ -44,7 +44,7 @@ namespace Wrapper
}
void TrainMachineLearningImagesClassifier::TrainLibSVM(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
void TrainImagesClassifier::TrainLibSVM(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
{
LibSVMType::Pointer libSVMClassifier = LibSVMType::New();
libSVMClassifier->SetInputListSample(trainingListSample);
......
......@@ -16,13 +16,13 @@
=========================================================================*/
#include <boost/lexical_cast.hpp>
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitNeuralNetworkParams()
void TrainImagesClassifier::InitNeuralNetworkParams()
{
AddChoice("classifier.ann", "Artificial Neural Network classifier");
SetParameterDescription("classifier.ann",
......@@ -118,7 +118,7 @@ void TrainMachineLearningImagesClassifier::InitNeuralNetworkParams()
}
void TrainMachineLearningImagesClassifier::TrainNeuralNetwork(ListSampleType::Pointer trainingListSample,
void TrainImagesClassifier::TrainNeuralNetwork(ListSampleType::Pointer trainingListSample,
LabelListSampleType::Pointer trainingLabeledListSample)
{
NeuralNetworkType::Pointer classifier = NeuralNetworkType::New();
......
......@@ -15,14 +15,14 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitNormalBayesParams()
void TrainImagesClassifier::InitNormalBayesParams()
{
AddChoice("classifier.bayes", "Normal Bayes classifier");
SetParameterDescription("classifier.bayes", "Use a Normal Bayes Classifier."
......@@ -31,7 +31,7 @@ namespace Wrapper
}
void TrainMachineLearningImagesClassifier::TrainNormalBayes(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
void TrainImagesClassifier::TrainNormalBayes(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
{
NormalBayesType::Pointer classifier = NormalBayesType::New();
classifier->SetInputListSample(trainingListSample);
......
......@@ -15,13 +15,13 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitRandomForestsParams()
void TrainImagesClassifier::InitRandomForestsParams()
{
AddChoice("classifier.rf", "Random forests classifier");
SetParameterDescription("classifier.rf",
......@@ -94,7 +94,7 @@ void TrainMachineLearningImagesClassifier::InitRandomForestsParams()
//TerminationCriteria not exposed
}
void TrainMachineLearningImagesClassifier::TrainRandomForests(ListSampleType::Pointer trainingListSample,
void TrainImagesClassifier::TrainRandomForests(ListSampleType::Pointer trainingListSample,
LabelListSampleType::Pointer trainingLabeledListSample)
{
RandomForestType::Pointer classifier = RandomForestType::New();
......
......@@ -15,14 +15,14 @@
=========================================================================*/
#include "otbTrainMachineLearningImagesClassifier.h"
#include "otbTrainImagesClassifier.h"
namespace otb
{
namespace Wrapper
{
void TrainMachineLearningImagesClassifier::InitSVMParams()
void TrainImagesClassifier::InitSVMParams()
{
AddChoice("classifier.svm", "SVM classifier (OpenCV)");
SetParameterDescription("classifier.svm", "This group of parameters allows to set SVM classifier parameters."
......@@ -70,7 +70,7 @@ namespace Wrapper
}
void TrainMachineLearningImagesClassifier::TrainSVM(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
void TrainImagesClassifier::TrainSVM(ListSampleType::Pointer trainingListSample, LabelListSampleType::Pointer trainingLabeledListSample)
{
SVMType::Pointer SVMClassifier = SVMType::New();
SVMClassifier->SetInputListSample(trainingListSample);
......
......@@ -79,7 +79,7 @@ public:
typedef std::map<int, ClassLabelType> MapOfIndicesType;
/** Type for the confusion matrix */
typedef itk::VariableSizeMatrix<double> ConfusionMatrixType;
typedef itk::VariableSizeMatrix<unsigned long> ConfusionMatrixType;
/** Type for the confusion matrix measurements calculator*/
typedef otb::ConfusionMatrixMeasurements<ConfusionMatrixType, ClassLabelType> ConfusionMatrixMeasurementsType;
......
......@@ -44,7 +44,7 @@ namespace otb
* Moreover overall accuracy and \f[ \kappa \f] index are computed.
*
*/
template <class TConfusionMatrix = itk::VariableSizeMatrix<double>, class TLabel = int >
template <class TConfusionMatrix = itk::VariableSizeMatrix<unsigned long>, class TLabel = int >
class ITK_EXPORT ConfusionMatrixMeasurements :
public itk::Object
{
......
......@@ -22,8 +22,9 @@
int otbConfusionMatrixToMassOfBeliefNew(int argc, char* argv[])
{
typedef itk::VariableSizeMatrix<double> ConfusionMatrixType;
typedef unsigned char LabelType;
typedef unsigned long ConfusionMatrixEltType;
typedef itk::VariableSizeMatrix<ConfusionMatrixEltType> ConfusionMatrixType;
typedef int LabelType;
// filter types
typedef otb::ConfusionMatrixToMassOfBelief<ConfusionMatrixType, LabelType>
......@@ -52,8 +53,9 @@ int otbConfusionMatrixToMassOfBeliefNew(int argc, char* argv[])
int otbConfusionMatrixToMassOfBeliefTest(int argc, char* argv[])
{
typedef itk::VariableSizeMatrix<double> ConfusionMatrixType;
typedef unsigned char LabelType;
typedef unsigned long ConfusionMatrixEltType;
typedef itk::VariableSizeMatrix<ConfusionMatrixEltType> ConfusionMatrixType;
typedef int LabelType;
// filter type
typedef otb::ConfusionMatrixToMassOfBelief<ConfusionMatrixType, LabelType> ConfusionMatrixToMassOfBeliefType;
......
......@@ -22,8 +22,9 @@
int otbConfusionMatrixMeasurementsNew(int argc, char* argv[])
{
typedef itk::VariableSizeMatrix<double> ConfusionMatrixType;
typedef unsigned char LabelType;
typedef unsigned long ConfusionMatrixEltType;
typedef itk::VariableSizeMatrix<ConfusionMatrixEltType> ConfusionMatrixType;
typedef unsigned char LabelType;
// filter types
typedef otb::ConfusionMatrixMeasurements<ConfusionMatrixType, LabelType> ConfusionMatrixMeasurements2TemplatesType;
......@@ -51,8 +52,9 @@ int otbConfusionMatrixMeasurementsNew(int argc, char* argv[])
int otbConfusionMatrixMeasurementsTest(int argc, char* argv[])
{
typedef itk::VariableSizeMatrix<double> ConfusionMatrixType;
typedef unsigned char ClassLabelType;
typedef unsigned long ConfusionMatrixEltType;
typedef itk::VariableSizeMatrix<ConfusionMatrixEltType> ConfusionMatrixType;
typedef unsigned char ClassLabelType;
// filter type
typedef otb::ConfusionMatrixMeasurements<ConfusionMatrixType, ClassLabelType> ConfusionMatrixMeasurementsType;
......
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