diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt index 7f38866ae252ad4207f2e48624f125772e5e50b2..94e558f6e59ac549e7d84ba6614027b607781661 100644 --- a/Modules/Applications/AppClassification/test/CMakeLists.txt +++ b/Modules/Applications/AppClassification/test/CMakeLists.txt @@ -527,6 +527,18 @@ otb_test_application(NAME apTvComputeConfusionMatrixExtraProducedLabelsR ${OTBAPP_BASELINE_FILES}/apTvComputeConfusionMatrixExtraProdLabelsROut.csv ${TEMP}/apTvComputeConfusionMatrixExtraProdLabelsROut.csv) +#----------- ComputeContingencyTable TESTS ---------------- + +otb_test_application(NAME apTvComputeContingencyTableExtraProducedLabelsR + APP ComputeConfusionMatrix + OPTIONS -in ${INPUTDATA}/Classification/clLabeledImageQB456_1_NoData_255.tif + -ref raster + -ref.raster.in ${INPUTDATA}/Classification/QB_1_ortho_C8.tif + -format contingencytable + -out ${TEMP}/apTvComputeContingencyTableExtraProdLabelsROut.csv + VALID --compare-ascii ${NOTOL} + ${OTBAPP_BASELINE_FILES}/apTvComputeContingencyTableExtraProdLabelsROut.csv + ${TEMP}/apTvComputeContingencyTableExtraProdLabelsROut.csv) #----------- FusionOfClassifications TESTS ---------------- otb_test_application(NAME apTvFusionOfClassificationsDSPrecision6Inputs diff --git a/Modules/Learning/Unsupervised/test/otbContingencyTableCalculatorTest.cxx b/Modules/Learning/Unsupervised/test/otbContingencyTableCalculatorTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..41d2aa45a40766a9e5ffb981dba108b54f662130 --- /dev/null +++ b/Modules/Learning/Unsupervised/test/otbContingencyTableCalculatorTest.cxx @@ -0,0 +1,244 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "itkListSample.h" +#include "otbContingencyTableCalculator.h" + +int otbContingencyTableCalculatorNew(int itkNotUsed(argc), char * itkNotUsed(argv) []) +{ + + typedef int ClassLabelType; + typedef otb::ContingencyTableCalculator<ClassLabelType> CalculatorType; + + CalculatorType::Pointer calculator = CalculatorType::New(); + + return EXIT_SUCCESS; +} + + + +int otbContingencyTableCalculatorSetListSamples(int argc, char* argv[]) +{ + + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " nbSamples nbClasses " << std::endl; + return EXIT_FAILURE; + } + + typedef int ClassLabelType; + typedef itk::VariableLengthVector<ClassLabelType> PLabelType; + typedef itk::Statistics::ListSample<PLabelType> PListLabelType; + typedef itk::FixedArray<ClassLabelType, 1> RLabelType; + typedef itk::Statistics::ListSample<RLabelType> RListLabelType; + typedef otb::ContingencyTableCalculator<ClassLabelType> CalculatorType; + + CalculatorType::Pointer calculator = CalculatorType::New(); + + RListLabelType::Pointer refLabels = RListLabelType::New(); + PListLabelType::Pointer prodLabels = PListLabelType::New(); + + // Set the measurement vector size for the list sample labels + refLabels->SetMeasurementVectorSize(1); + prodLabels->SetMeasurementVectorSize(1); + + int nbSamples = atoi(argv[1]); + int nbClasses = atoi(argv[2]); + + for (int i = 0; i < nbSamples; ++i) + { + ClassLabelType label = (i % nbClasses) + 1; + PLabelType plab; + plab.SetSize(1); + plab[0] = label; + refLabels->PushBack(label); + prodLabels->PushBack(plab); + } + + calculator->Compute( refLabels->Begin(), refLabels->End(), prodLabels->Begin(), prodLabels->End() ); + + return EXIT_SUCCESS; +} + +int otbContingencyTableCalculatorCompute(int argc, char* argv[]) +{ + + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " nbSamples nbRefClasses " << std::endl; + return EXIT_FAILURE; + } + + + typedef int ClassLabelType; + typedef itk::VariableLengthVector<ClassLabelType> PLabelType; + typedef itk::Statistics::ListSample<PLabelType> PListLabelType; + typedef itk::FixedArray<ClassLabelType, 1> RLabelType; + typedef itk::Statistics::ListSample<RLabelType> RListLabelType; + typedef otb::ContingencyTableCalculator<ClassLabelType> CalculatorType; + typedef CalculatorType::ContingencyTableType ContingencyTableType; + + CalculatorType::Pointer calculator = CalculatorType::New(); + + RListLabelType::Pointer refLabels = RListLabelType::New(); + PListLabelType::Pointer prodLabels = PListLabelType::New(); + + // Set the measurement vector size for the list sample labels + refLabels->SetMeasurementVectorSize(1); + prodLabels->SetMeasurementVectorSize(1); + + int nbSamples = atoi(argv[1]); + int nbRefClasses = atoi(argv[2]); + int nbProdClasses = nbSamples; + + for (int i = 0; i < nbSamples; ++i) + { + int label; + + label = (i % nbProdClasses) + 1; + + PLabelType plab; + RLabelType rlab; + plab.SetSize(1); + + plab[0] = label > nbProdClasses ? nbProdClasses : label; + rlab[0] = label > nbRefClasses ? nbRefClasses : label; + + refLabels->PushBack(rlab); + prodLabels->PushBack(plab); + } + + calculator->Compute( refLabels->Begin(), refLabels->End(), prodLabels->Begin(), prodLabels->End() ); + ContingencyTableType confmat = calculator->GetContingencyTable(); + + + if( static_cast<int>(calculator->GetNumberOfRefClasses()) != nbRefClasses ) + { + std::cerr << "Wrong number of reference classes " << calculator->GetNumberOfRefClasses() << " != " << nbRefClasses + << std::endl; + return EXIT_FAILURE; + } + if( static_cast<int>(calculator->GetNumberOfProdClasses()) != nbProdClasses ) + { + std::cerr << "Wrong number of produced classes " << calculator->GetNumberOfProdClasses() << " != " << nbProdClasses + << std::endl; + return EXIT_FAILURE; + } + if( static_cast<int>(calculator->GetNumberOfSamples()) != nbSamples ) + { + std::cerr << "Wrong number of samples" << std::endl; + return EXIT_FAILURE; + } + + + std::cout << "contingency table" << std::endl << confmat << std::endl; + + return EXIT_SUCCESS; +} + + + +int otbContingencyTableCalculatorComputeWithBaseline(int itkNotUsed(argc), char* itkNotUsed(argv) []) +{ + typedef int ClassLabelType; + typedef itk::VariableLengthVector<ClassLabelType> PLabelType; + typedef itk::Statistics::ListSample<PLabelType> PListLabelType; + typedef itk::FixedArray<ClassLabelType, 1> RLabelType; + typedef itk::Statistics::ListSample<RLabelType> RListLabelType; + typedef otb::ContingencyTableCalculator<ClassLabelType> CalculatorType; + + CalculatorType::Pointer calculator = CalculatorType::New(); + + RListLabelType::Pointer refLabels = RListLabelType::New(); + PListLabelType::Pointer prodLabels = PListLabelType::New(); + + unsigned int nbSamples = 12; + + // Reference samples: a b c d a b c d a b c d + // Classified reference samples: a c c d d b c d d d d c + std::vector<ClassLabelType> labelsUniverse, labelsClassified; + + labelsUniverse.push_back( 'a' ); + labelsUniverse.push_back( 'b' ); + labelsUniverse.push_back( 'b' ); + labelsUniverse.push_back( 'b' ); + labelsUniverse.push_back( 'c' ); + labelsUniverse.push_back( 'd' ); + labelsUniverse.push_back( 'd' ); + labelsUniverse.push_back( 'd' ); + labelsUniverse.push_back( 'd' ); + labelsUniverse.push_back( 'c' ); + labelsUniverse.push_back( 'c' ); + labelsUniverse.push_back( 'z' ); + + labelsClassified.push_back( 'a' ); + labelsClassified.push_back( 'b' ); + labelsClassified.push_back( 'c' ); + labelsClassified.push_back( 'd' ); + labelsClassified.push_back( 'd' ); + labelsClassified.push_back( 'y' ); + labelsClassified.push_back( 'c' ); + labelsClassified.push_back( 'u' ); + labelsClassified.push_back( 'd' ); + labelsClassified.push_back( 'k' ); + labelsClassified.push_back( 'd' ); + labelsClassified.push_back( 'c' ); + + for( unsigned int i = 0; i < nbSamples; ++i ) + { + ClassLabelType label = labelsUniverse[i]; + PLabelType plab; + plab.SetSize( 1 ); + plab[0] = labelsClassified[i]; + if( i == 0 ) + { + prodLabels->SetMeasurementVectorSize( itk::NumericTraits<PLabelType>::GetLength( plab ) ); + } + refLabels->PushBack( label ); + prodLabels->PushBack( plab ); + } + + calculator->Compute( refLabels->Begin(), refLabels->End(), prodLabels->Begin(), prodLabels->End() ); + CalculatorType::ContingencyTableType confmat = calculator->GetContingencyTable(); + + std::cout << std::endl; + std::cout << "contingency Table" << std::endl << confmat << std::endl; + unsigned int nbRefClasses = 5; + unsigned int nbProdClasses = 7; + + if( calculator->GetNumberOfRefClasses() != nbRefClasses ) + { + std::cerr << "Wrong number of reference classes " << calculator->GetNumberOfRefClasses() << " != " << nbRefClasses + << std::endl; + return EXIT_FAILURE; + } + if( calculator->GetNumberOfProdClasses() != nbProdClasses ) + { + std::cerr << "Wrong number of produced classes " << calculator->GetNumberOfProdClasses() << " != " << nbProdClasses + << std::endl; + return EXIT_FAILURE; + } + if( calculator->GetNumberOfSamples() != nbSamples ) + { + std::cerr << "Wrong number of samples" << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + diff --git a/Modules/Learning/Unsupervised/test/otbUnsupervisedTestDriver.cxx b/Modules/Learning/Unsupervised/test/otbUnsupervisedTestDriver.cxx index 14ca633f1cfaecbd96a348b26c7c37df1fc46f7c..30b0b20f1904a20aad0865ceae4e944d9c391dc8 100644 --- a/Modules/Learning/Unsupervised/test/otbUnsupervisedTestDriver.cxx +++ b/Modules/Learning/Unsupervised/test/otbUnsupervisedTestDriver.cxx @@ -1,6 +1,12 @@ #include "otbTestMain.h" void RegisterTests() { + + REGISTER_TEST(otbContingencyTableCalculatorNew); + REGISTER_TEST(otbContingencyTableCalculatorSetListSamples); + REGISTER_TEST(otbContingencyTableCalculatorCompute); + REGISTER_TEST(otbContingencyTableCalculatorComputeWithBaseline); + #ifdef OTB_USE_SHARK REGISTER_TEST(otbSharkKMeansMachineLearningModelCanRead); REGISTER_TEST(otbSharkKMeansMachineLearningModelNew);