diff --git a/Applications/Classification/otbFusionOfClassifications.cxx b/Applications/Classification/otbFusionOfClassifications.cxx index f8a48400b4da2322559a7a3ff6d36c182917fdb3..d20781258ccca4c88e70cdd790fe136518aa4243 100644 --- a/Applications/Classification/otbFusionOfClassifications.cxx +++ b/Applications/Classification/otbFusionOfClassifications.cxx @@ -20,8 +20,38 @@ #include "itkLabelVotingImageFilter.h" #include "otbMultiToMonoChannelExtractROI.h" +#include "otbDSFusionOfClassifiersImageFilter.h" +#include "otbImageListToVectorImageFilter.h" +#include "otbConfusionMatrixToMassOfBelief.h" + +#include <iostream> +#include <fstream> + +#include "otbVectorImage.h" +#include "otbImage.h" +#include "otbImageList.h" + + + + + namespace otb { + +enum +{ + Method_Majority_Voting, + Method_Dempster_Shafer +}; + +enum +{ + Mode_MOB_Precision, + Mode_MOB_Recall, + Mode_MOB_Accuracy, + Mode_MOB_Kappa +}; + namespace Wrapper { @@ -33,9 +63,31 @@ public: typedef Application Superclass; typedef itk::SmartPointer<Self> Pointer; typedef itk::SmartPointer<const Self> ConstPointer; - typedef otb::MultiToMonoChannelExtractROI<FloatVectorImageType::InternalPixelType, - UInt16ImageType::InternalPixelType> ConverterType; - typedef itk::LabelVotingImageFilter<UInt16ImageType,UInt16ImageType> LabelVotingFilterType; + + typedef UInt16VectorImageType VectorImageType; + typedef UInt16ImageType IOLabelImageType; + typedef IOLabelImageType::InternalPixelType LabelPixelType; + + typedef otb::MultiToMonoChannelExtractROI<FloatVectorImageType::InternalPixelType, LabelPixelType> ConverterType; + + // Majority Voting + typedef itk::LabelVotingImageFilter<IOLabelImageType, IOLabelImageType> LabelVotingFilterType; + + // Dempster Shafer + typedef itk::VariableSizeMatrix<double> ConfusionMatrixType; + typedef otb::ConfusionMatrixToMassOfBelief<ConfusionMatrixType, LabelPixelType> ConfusionMatrixToMassOfBeliefType; + typedef ConfusionMatrixToMassOfBeliefType::MapOfIndicesType MapOfIndicesType; + + typedef otb::ImageList<IOLabelImageType> ImageListType; + typedef otb::ImageListToVectorImageFilter<ImageListType, VectorImageType> ImageListToVectorImageFilterType; + + typedef ConfusionMatrixToMassOfBeliefType::MassOfBeliefDefinitionMethod MassOfBeliefDefinitionMethod; + + typedef otb::DSFusionOfClassifiersImageFilter<VectorImageType, IOLabelImageType> DSFusionOfClassifiersImageFilterType; + typedef DSFusionOfClassifiersImageFilterType::VectorOfMapOfMassesOfBeliefType VectorOfMapOfMassesOfBeliefType; + typedef DSFusionOfClassifiersImageFilterType::LabelMassMapType LabelMassMapType; + + /** Standard macro */ itkNewMacro(Self); @@ -59,9 +111,41 @@ private: AddParameter(ParameterType_InputImageList, "il", "Input classifications"); SetParameterDescription( "il", "List of input classification to fuse. Labels in each classification image must represent the same class." ); - AddParameter(ParameterType_Int,"undecided","Label for the undecided class"); - SetParameterDescription("undecided","Label for the undecided class. Pixels with more than 1 majority class are marked as undecided. Please note that the undecided value must be different from existing labels in the input classifications."); - SetDefaultParameterInt("undecided",0); + + /** GROUP FUSION METHOD */ + AddParameter(ParameterType_Choice, "method", "Fusion method"); + SetParameterDescription("method", "Selection of fusion methods and their parameters."); + + // Majority Voting + AddChoice("method.majorityvoting","Fusion from majority voting"); + SetParameterDescription("method.majorityvoting","Fusion of classification maps from majority voting for each output pixel."); + + // Dempster Shafer + AddChoice("method.dempstershafer","Fusion with Dempster Shafer"); + SetParameterDescription("method.dempstershafer","Fusion of classification maps with the Dempster Shafer method."); + + AddParameter(ParameterType_InputFilenameList, "method.dempstershafer.cmfl", "Confusion Matrices"); + SetParameterDescription("method.dempstershafer.cmfl", "A list of confusion matrix files (csv format) to define the masses of belief and the class labels."); + + AddParameter(ParameterType_Choice, "method.dempstershafer.mob", "Mass of belief measurement"); + SetParameterDescription("method.dempstershafer.mob","Confusion matrix measurement standing for the masses of belief of each classifier."); + AddChoice("method.dempstershafer.mob.precision","Precision"); + SetParameterDescription("method.dempstershafer.mob.precision","Masses of belief = Precision rates of each classifier (one rate per class label)."); + AddChoice("method.dempstershafer.mob.recall", "Recall"); + SetParameterDescription("method.dempstershafer.mob.recall", "Masses of belief = Recall rates of each classifier (one rate per class label)."); + AddChoice("method.dempstershafer.mob.accuracy", "Overall Accuracy"); + SetParameterDescription("method.dempstershafer.mob.accuracy", "Mass of belief = Overall Accuracy of each classifier (one unique rate for all the class labels)."); + AddChoice("method.dempstershafer.mob.kappa", "Kappa"); + SetParameterDescription("method.dempstershafer.mob.kappa", "Mass of belief = Kappa coefficient of each classifier (one unique rate for all the class labels)."); + + AddParameter(ParameterType_Int, "nodatalabel", "Label for the NoData class"); + SetParameterDescription("nodatalabel", "Label for the NoData class. Such input pixels keep their NoData label in the output image. By default, 'nodatalabel = 0'."); + SetDefaultParameterInt("nodatalabel", 0); + MandatoryOff("nodatalabel"); + + AddParameter(ParameterType_Int,"undecidedlabel","Label for the Undecided class"); + SetParameterDescription("undecidedlabel","Label for the Undecided class. Pixels with more than 1 fused class are marked as Undecided. Please note that the Undecided value must be different from existing labels in the input classifications. By default, 'undecidedlabel = 0'."); + SetDefaultParameterInt("undecidedlabel",0); AddParameter(ParameterType_OutputImage,"out","The output classification image"); SetParameterDescription("out","The output classification image resulting from the fusion of the input classification images"); @@ -69,7 +153,7 @@ private: // Doc example parameter settings SetDocExampleParameterValue("il", "classification1.tif classification2.tif"); SetDocExampleParameterValue("out","classification_fused.tif"); - SetDocExampleParameterValue("undecided","10"); + SetDocExampleParameterValue("undecidedlabel","10"); } void DoUpdateParameters() @@ -77,6 +161,61 @@ private: // Nothing to do here : all parameters are independent } + + + int CSVConfusionMatrixFileReader(const std::string fileName, MapOfIndicesType &mapOfIndicesClX, ConfusionMatrixType &confusionMatrixClX) + { + std::ifstream inFile; + inFile.open(fileName.c_str()); + + if (!inFile) + { + std::cerr << "Confusion Matrix File opening problem with file:" << std::endl; + std::cerr << fileName.c_str() << std::endl; + return EXIT_FAILURE; + } + else + { + std::string currentLine, labelsLine, currentValue; + const char commentChar = '#'; + const char separatorChar = ','; + const char eolChar = '\n'; + std::getline(inFile, labelsLine, commentChar); // Skips the comment char + std::getline(inFile, labelsLine, eolChar); // Gets the first line after the comment char until the End Of Line char + + std::istringstream issLabelsLine(labelsLine); + mapOfIndicesClX.clear(); + int itLab = 0; + while (issLabelsLine.good()) + { + std::getline(issLabelsLine, currentValue, separatorChar); + mapOfIndicesClX[itLab] = std::atoi(currentValue.c_str()); + ++itLab; + } + + unsigned int nbLabelsClk = mapOfIndicesClX.size(); + confusionMatrixClX = ConfusionMatrixType(nbLabelsClk, nbLabelsClk); + + for (unsigned int itLin = 0; itLin < nbLabelsClk; ++itLin) + { + //Gets the itLin^th line after the first header line with the labels + std::getline(inFile, currentLine, eolChar); + std::istringstream issCurrentLine(currentLine); + unsigned int itCol = 0; + while (issCurrentLine.good()) + { + std::getline(issCurrentLine, currentValue, separatorChar); + confusionMatrixClX(itLin, itCol) = std::atoi(currentValue.c_str()); + ++itCol; + } + } + } + inFile.close(); + return EXIT_SUCCESS; + } + + + void DoExecute() { // Clear any previous filter @@ -84,27 +223,141 @@ private: FloatVectorImageListType* imageList = GetParameterImageList("il"); - LabelVotingFilterType::Pointer labelVotingFilter = LabelVotingFilterType::New(); - labelVotingFilter->SetLabelForUndecidedPixels(GetParameterInt("undecided")); - - m_Filters.push_back(labelVotingFilter.GetPointer()); + if (GetParameterInt("method") == Method_Majority_Voting) + //if (IsParameterEnabled( "method.majorityvoting" ) == true) + { + otbAppLogINFO("Fusion by Majority Voting"); + + LabelVotingFilterType::Pointer labelVotingFilter = LabelVotingFilterType::New(); + labelVotingFilter->SetLabelForUndecidedPixels(GetParameterInt("undecidedlabel")); + + m_Filters.push_back(labelVotingFilter.GetPointer()); + + //Iterate over all input images + for (unsigned int imageId = 0; imageId < imageList->Size(); ++imageId) + { + FloatVectorImageType* image = imageList->GetNthElement(imageId); + + ConverterType::Pointer converter = ConverterType::New(); + converter->SetInput(image); + converter->SetChannel(1); + + labelVotingFilter->SetInput(imageId, converter->GetOutput()); - //Iterate over all input images - for (unsigned int imageId = 0; imageId < imageList->Size(); ++imageId) + // Register filter + m_Filters.push_back(converter.GetPointer()); + } + + SetParameterOutputImage("out", labelVotingFilter->GetOutput()); + }// END Fusion by Majority Voting + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// + else { - FloatVectorImageType* image = imageList->GetNthElement(imageId); + if (GetParameterInt("method") == Method_Dempster_Shafer) + { + otbAppLogINFO("Fusion with the Dempster Shafer method"); - ConverterType::Pointer converter = ConverterType::New(); - converter->SetInput(image); - converter->SetChannel(1); + ImageListType::Pointer imageListTemp = ImageListType::New(); + ConfusionMatrixToMassOfBeliefType::Pointer confusionMatrixToMassOfBeliefFilter = ConfusionMatrixToMassOfBeliefType::New(); - labelVotingFilter->SetInput(imageId,converter->GetOutput()); + DSFusionOfClassifiersImageFilterType::Pointer dsFusionOfClassifiersImageFilter = DSFusionOfClassifiersImageFilterType::New(); + dsFusionOfClassifiersImageFilter->SetLabelForUndecidedPixels(GetParameterInt("undecidedlabel")); - // Register filter - m_Filters.push_back(converter.GetPointer()); - } + m_Filters.push_back(confusionMatrixToMassOfBeliefFilter.GetPointer()); + m_Filters.push_back(dsFusionOfClassifiersImageFilter.GetPointer()); + + std::vector<std::string> confusionMatricesFilenameList = GetParameterStringList("method.dempstershafer.cmfl"); + + MassOfBeliefDefinitionMethod massOfBeliefDefMethod; + switch (GetParameterInt("method.dempstershafer.mob")) + { + case Mode_MOB_Precision: + { + otbAppLogINFO("Masses of belief = PRECISION rates of each classifier (one rate per class label)"); + massOfBeliefDefMethod = ConfusionMatrixToMassOfBeliefType::PRECISION; + } + break; + case Mode_MOB_Recall: + { + otbAppLogINFO("Masses of belief = RECALL rates of each classifier (one rate per class label)"); + massOfBeliefDefMethod = ConfusionMatrixToMassOfBeliefType::RECALL; + } + break; + case Mode_MOB_Accuracy: + { + otbAppLogINFO("Mass of belief = OVERALL ACCURACY of each classifier (one unique rate for all the class labels)"); + massOfBeliefDefMethod = ConfusionMatrixToMassOfBeliefType::ACCURACY; + } + break; + case Mode_MOB_Kappa: + { + otbAppLogINFO("Mass of belief = KAPPA coefficient of each classifier (one unique rate for all the class labels)"); + massOfBeliefDefMethod = ConfusionMatrixToMassOfBeliefType::KAPPA; + } + break; + } + + //Iterate over all input images + VectorOfMapOfMassesOfBeliefType vectorOfMapOfMassesOfBelief; + for (unsigned int imageId = 0; imageId < imageList->Size(); ++imageId) + { + FloatVectorImageType* image = imageList->GetNthElement(imageId); + + ConverterType::Pointer converter = ConverterType::New(); + converter->SetInput(image); + converter->SetChannel(1); + + imageListTemp->PushBack(converter->GetOutput()); - SetParameterOutputImage("out", labelVotingFilter->GetOutput()); + MapOfIndicesType mapOfIndicesClk; + ConfusionMatrixType confusionMatrixClk; + CSVConfusionMatrixFileReader(confusionMatricesFilenameList[imageId], mapOfIndicesClk, confusionMatrixClk); + + confusionMatrixToMassOfBeliefFilter->SetMapOfIndices(mapOfIndicesClk); + confusionMatrixToMassOfBeliefFilter->SetConfusionMatrix(confusionMatrixClk); + confusionMatrixToMassOfBeliefFilter->SetDefinitionMethod(massOfBeliefDefMethod); + confusionMatrixToMassOfBeliefFilter->Update(); + + // Vector containing ALL the K (= nbClassifiers) std::map<Label, MOB> of Masses of Belief + vectorOfMapOfMassesOfBelief.push_back(confusionMatrixToMassOfBeliefFilter->GetMapMassOfBelief()); + // Register filter + m_Filters.push_back(converter.GetPointer()); + } + + // ********************************************** + // Image List To VectorImage + // ********************************************** + ImageListToVectorImageFilterType::Pointer imageListToVectorImageFilter = ImageListToVectorImageFilterType::New(); + imageListToVectorImageFilter->SetInput(imageListTemp); + imageListToVectorImageFilter->Update(); + + otbAppLogINFO("Number of input classification maps: " << imageListToVectorImageFilter->GetOutput()->GetNumberOfComponentsPerPixel()); + otbAppLogINFO("Number of input confusion matrix files: " << vectorOfMapOfMassesOfBelief.size()); + LabelMassMapType::iterator itMap; + for (unsigned int k = 0; k < vectorOfMapOfMassesOfBelief.size(); ++k) + { + LabelMassMapType mapOfMassesOfBelief = vectorOfMapOfMassesOfBelief[k]; + otbAppLogINFO("Classifier[" << k << "]: "); + otbAppLogINFO(" Confusion Matrix file_" << k << ": " << confusionMatricesFilenameList[k]); + for (itMap = mapOfMassesOfBelief.begin(); itMap != mapOfMassesOfBelief.end(); ++itMap) + { + otbAppLogINFO(" MassOfBelief_Cl_" << k << "[label_" << itMap->first << "] = " << itMap->second ); + } + otbAppLogINFO(""); + } + + // DSFusionOfClassifiersImageFilter Inputs + dsFusionOfClassifiersImageFilter->SetInput(imageListToVectorImageFilter->GetOutput()); + dsFusionOfClassifiersImageFilter->SetInputMapsOfMassesOfBelief(&vectorOfMapOfMassesOfBelief); + dsFusionOfClassifiersImageFilter->SetLabelForNoDataPixels(GetParameterInt("nodatalabel")); + dsFusionOfClassifiersImageFilter->SetLabelForUndecidedPixels(GetParameterInt("undecidedlabel")); + //dsFusionOfClassifiersImageFilter->Update(); + + SetParameterOutputImage("out", dsFusionOfClassifiersImageFilter->GetOutput()); + }// END Fusion with the Dempster Shafer method + + } } std::vector<itk::LightObject::Pointer> m_Filters; diff --git a/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.cxx b/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.cxx index 63b27138fcdf292b059de2535f0876f50dceb21e..226a412a2d1a7bd17a60f7ce1a0f7b9dc77ad6fe 100644 --- a/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.cxx +++ b/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.cxx @@ -187,6 +187,12 @@ InputFilenameListParameter::GetNthFileName( unsigned int i ) const } +InputFilenameListParameter::StringParameterListPointerType +InputFilenameListParameter::GetFileList() const +{ + return m_FilenameList; +} + bool InputFilenameListParameter::HasValue() const { diff --git a/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.h b/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.h index 9dff39104b58d5da1674201c746885c63940dcab..acbb17cf63319829f689889f6afaa0121c8b906c 100644 --- a/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.h +++ b/Code/ApplicationEngine/otbWrapperInputFilenameListParameter.h @@ -42,6 +42,7 @@ public: typedef itk::SmartPointer<const Self> ConstPointer; typedef otb::ObjectList<StringParameter> StringParameterListType; + typedef StringParameterListType* StringParameterListPointerType; /** Defining ::New() static method */ @@ -68,6 +69,9 @@ public: /** Get one specific stored filename. */ std::string GetNthFileName( unsigned int i ) const; + /** Get one list of the stored files. */ + StringParameterListPointerType GetFileList() const; + bool HasValue() const; diff --git a/Code/Wrappers/QtWidget/otbQtFileSelectionWidget.h b/Code/Wrappers/QtWidget/otbQtFileSelectionWidget.h index 164adc42eab94f9f26f4ce26af008acf60c89a48..afdfbfa79e28e7e9256150f0a6eb8edeb8e747ef 100644 --- a/Code/Wrappers/QtWidget/otbQtFileSelectionWidget.h +++ b/Code/Wrappers/QtWidget/otbQtFileSelectionWidget.h @@ -20,6 +20,7 @@ #include <QtGui> #include "otbWrapperInputImageListParameter.h" +#include "otbWrapperInputFilenameListParameter.h" #include "otbWrapperQtWidgetParameterBase.h" diff --git a/Code/Wrappers/QtWidget/otbWrapperQtWidgetInputFilenameListParameter.cxx b/Code/Wrappers/QtWidget/otbWrapperQtWidgetInputFilenameListParameter.cxx index 57d948dd4b389f9f830fad40cb609cc589f86bb8..8497efd95e7c89e63cdcf1fe62ecd16055b8c569 100644 --- a/Code/Wrappers/QtWidget/otbWrapperQtWidgetInputFilenameListParameter.cxx +++ b/Code/Wrappers/QtWidget/otbWrapperQtWidgetInputFilenameListParameter.cxx @@ -137,7 +137,7 @@ void QtWidgetInputFilenameListParameter::DoCreateWidget() void QtWidgetInputFilenameListParameter::UpdateFilenameList() { - for(unsigned int j = 0; j < m_InputFilenameListParam->GetFileNameList().size(); j++) + for(unsigned int j = 0; j < m_InputFilenameListParam->GetFileList()->Size(); j++) { if(m_InputFilenameListParam->SetNthFileName(j, m_FileSelectionList[j]->GetFilename()) == false) { diff --git a/Testing/Applications/Classification/CMakeLists.txt b/Testing/Applications/Classification/CMakeLists.txt index 88d2f64e95e422d4feadce9995c7ed0afee29048..9a7b60fa39dea8a07fec6fed3fbdb36505cd2cd7 100644 --- a/Testing/Applications/Classification/CMakeLists.txt +++ b/Testing/Applications/Classification/CMakeLists.txt @@ -356,27 +356,125 @@ OTB_TEST_APPLICATION(NAME apTvClSOMClassificationFull ${TEMP}/apTvClSOMClassificationMap.hdr) # --- Fusion of classifications --- -OTB_TEST_APPLICATION(NAME apTvFusionOfClassifications2Inputs +OTB_TEST_APPLICATION(NAME apTvFusionOfClassificationsMV2Inputs APP FusionOfClassifications OPTIONS -il ${OTBAPP_BASELINE}/clLabeledImageQB123_1.tif ${OTBAPP_BASELINE}/clLabeledImageQB456_1.tif - -undecided 100 - -out ${TEMP}/apTvFusionOfClassifications2InputsOutput.tif uint16 + -method majorityvoting + -undecidedlabel 100 + -out ${TEMP}/apTvFusionOfClassificationsMV2InputsOutput.tif uint16 VALID --compare-image ${NOTOL} ${OTBAPP_BASELINE}/apTvFusionOfClassifications2InputsOutput.tif - ${TEMP}/apTvFusionOfClassifications2InputsOutput.tif + ${TEMP}/apTvFusionOfClassificationsMV2InputsOutput.tif ) -OTB_TEST_APPLICATION(NAME apTvFusionOfClassifications3Inputs +OTB_TEST_APPLICATION(NAME apTvFusionOfClassificationsMV3Inputs APP FusionOfClassifications OPTIONS -il ${OTBAPP_BASELINE}/clLabeledImageQB123_1.tif ${OTBAPP_BASELINE}/clLabeledImageQB456_1.tif ${OTBAPP_BASELINE}/clLabeledImageQB1.tif - -undecided 100 - -out ${TEMP}/apTvFusionOfClassifications3InputsOutput.tif uint16 + -method majorityvoting + -undecidedlabel 100 + -out ${TEMP}/apTvFusionOfClassificationsMV3InputsOutput.tif uint16 VALID --compare-image ${NOTOL} ${OTBAPP_BASELINE}/apTvFusionOfClassifications3InputsOutput.tif - ${TEMP}/apTvFusionOfClassifications3InputsOutput.tif + ${TEMP}/apTvFusionOfClassificationsMV3InputsOutput.tif +) + +OTB_TEST_APPLICATION(NAME apTvFusionOfClassificationsDSPrecision6Inputs + APP FusionOfClassifications + OPTIONS -il ${INPUTDATA}/Classification/QB_1_ortho_C1.tif + ${INPUTDATA}/Classification/QB_1_ortho_C2.tif + ${INPUTDATA}/Classification/QB_1_ortho_C3.tif + ${INPUTDATA}/Classification/QB_1_ortho_C4.tif + ${INPUTDATA}/Classification/QB_1_ortho_C5.tif + ${INPUTDATA}/Classification/QB_1_ortho_C6.tif + -method dempstershafer + -method.dempstershafer.cmfl ${INPUTDATA}/Classification/QB_1_ortho_C1.csv + ${INPUTDATA}/Classification/QB_1_ortho_C2.csv + ${INPUTDATA}/Classification/QB_1_ortho_C3.csv + ${INPUTDATA}/Classification/QB_1_ortho_C4.csv + ${INPUTDATA}/Classification/QB_1_ortho_C5.csv + ${INPUTDATA}/Classification/QB_1_ortho_C6.csv + -method.dempstershafer.mob precision + -nodatalabel 10 + -undecidedlabel 7 + -out ${TEMP}/apTvFusionOfClassificationsDS6InputsPrecisionOutput.tif uint8 + VALID --compare-image ${NOTOL} + ${BASELINE}/QB_1_ortho_DS_FUSED_PRECISION.tif + ${TEMP}/apTvFusionOfClassificationsDS6InputsPrecisionOutput.tif +) + +OTB_TEST_APPLICATION(NAME apTvFusionOfClassificationsDSRecall6Inputs + APP FusionOfClassifications + OPTIONS -il ${INPUTDATA}/Classification/QB_1_ortho_C1.tif + ${INPUTDATA}/Classification/QB_1_ortho_C2.tif + ${INPUTDATA}/Classification/QB_1_ortho_C3.tif + ${INPUTDATA}/Classification/QB_1_ortho_C4.tif + ${INPUTDATA}/Classification/QB_1_ortho_C5.tif + ${INPUTDATA}/Classification/QB_1_ortho_C6.tif + -method dempstershafer + -method.dempstershafer.cmfl ${INPUTDATA}/Classification/QB_1_ortho_C1.csv + ${INPUTDATA}/Classification/QB_1_ortho_C2.csv + ${INPUTDATA}/Classification/QB_1_ortho_C3.csv + ${INPUTDATA}/Classification/QB_1_ortho_C4.csv + ${INPUTDATA}/Classification/QB_1_ortho_C5.csv + ${INPUTDATA}/Classification/QB_1_ortho_C6.csv + -method.dempstershafer.mob recall + -nodatalabel 10 + -undecidedlabel 7 + -out ${TEMP}/apTvFusionOfClassificationsDS6InputsRecallOutput.tif uint8 + VALID --compare-image ${NOTOL} + ${BASELINE}/QB_1_ortho_DS_FUSED_RECALL.tif + ${TEMP}/apTvFusionOfClassificationsDS6InputsRecallOutput.tif +) + +OTB_TEST_APPLICATION(NAME apTvFusionOfClassificationsDSAccuracy6Inputs + APP FusionOfClassifications + OPTIONS -il ${INPUTDATA}/Classification/QB_1_ortho_C1.tif + ${INPUTDATA}/Classification/QB_1_ortho_C2.tif + ${INPUTDATA}/Classification/QB_1_ortho_C3.tif + ${INPUTDATA}/Classification/QB_1_ortho_C4.tif + ${INPUTDATA}/Classification/QB_1_ortho_C5.tif + ${INPUTDATA}/Classification/QB_1_ortho_C6.tif + -method dempstershafer + -method.dempstershafer.cmfl ${INPUTDATA}/Classification/QB_1_ortho_C1.csv + ${INPUTDATA}/Classification/QB_1_ortho_C2.csv + ${INPUTDATA}/Classification/QB_1_ortho_C3.csv + ${INPUTDATA}/Classification/QB_1_ortho_C4.csv + ${INPUTDATA}/Classification/QB_1_ortho_C5.csv + ${INPUTDATA}/Classification/QB_1_ortho_C6.csv + -method.dempstershafer.mob accuracy + -nodatalabel 10 + -undecidedlabel 7 + -out ${TEMP}/apTvFusionOfClassificationsDS6InputsAccuracyOutput.tif uint8 + VALID --compare-image ${NOTOL} + ${BASELINE}/QB_1_ortho_DS_FUSED_ACCURACY.tif + ${TEMP}/apTvFusionOfClassificationsDS6InputsAccuracyOutput.tif +) + +OTB_TEST_APPLICATION(NAME apTvFusionOfClassificationsDSKappa6Inputs + APP FusionOfClassifications + OPTIONS -il ${INPUTDATA}/Classification/QB_1_ortho_C1.tif + ${INPUTDATA}/Classification/QB_1_ortho_C2.tif + ${INPUTDATA}/Classification/QB_1_ortho_C3.tif + ${INPUTDATA}/Classification/QB_1_ortho_C4.tif + ${INPUTDATA}/Classification/QB_1_ortho_C5.tif + ${INPUTDATA}/Classification/QB_1_ortho_C6.tif + -method dempstershafer + -method.dempstershafer.cmfl ${INPUTDATA}/Classification/QB_1_ortho_C1.csv + ${INPUTDATA}/Classification/QB_1_ortho_C2.csv + ${INPUTDATA}/Classification/QB_1_ortho_C3.csv + ${INPUTDATA}/Classification/QB_1_ortho_C4.csv + ${INPUTDATA}/Classification/QB_1_ortho_C5.csv + ${INPUTDATA}/Classification/QB_1_ortho_C6.csv + -method.dempstershafer.mob kappa + -nodatalabel 10 + -undecidedlabel 7 + -out ${TEMP}/apTvFusionOfClassificationsDS6InputsKappaOutput.tif uint8 + VALID --compare-image ${NOTOL} + ${BASELINE}/QB_1_ortho_DS_FUSED_KAPPA.tif + ${TEMP}/apTvFusionOfClassificationsDS6InputsKappaOutput.tif )