diff --git a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx index f9ac0883b784ffe569542485c080cf9fc372dc50..ab24b34016151ad1a4de84fd4db363ccd097f373 100644 --- a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx +++ b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx @@ -91,7 +91,10 @@ private: struct StreamingInitializationData { - int nodata; + bool refhasnodata; + bool prodhasnodata; + int prodnodata; + int refnodata; unsigned long numberOfStreamDivisions; }; @@ -143,12 +146,17 @@ private: SetParameterDescription("ref.vector.field","Field name containing the label values"); SetListViewSingleSelectionMode("ref.vector.field",true); - AddParameter(ParameterType_Int,"nodatalabel","Value for nodata pixels"); - SetParameterDescription("nodatalabel", "Label for the NoData class. Such input pixels will be discarded from the " - "ground truth and from the input classification map. By default, 'nodatalabel = 0'."); - SetDefaultParameterInt("nodatalabel",0); - MandatoryOff("nodatalabel"); - DisableParameter("nodatalabel"); + AddParameter(ParameterType_Int,"refnodatalabel","Value for nodata pixels in ref"); + SetDefaultParameterInt("refnodatalabel",0); + SetParameterDescription("refnodatalabel","Label to be treated as no data in ref. Please note that this value is always used in vector mode, to generate default values. Please set it to a value that does not correspond to a class label."); + MandatoryOff("refnodatalabel"); + DisableParameter("refnodatalabel"); + AddParameter(ParameterType_Int,"prodnodatalabel","Value for nodata pixels in input image"); + SetParameterDescription("prodnodatalabel","Label to be treated as no data in input image"); + SetDefaultParameterInt("prodnodatalabel",0); + + MandatoryOff("prodnodatalabel"); + DisableParameter("prodnodatalabel"); AddRAMParameter(); @@ -158,7 +166,7 @@ private: SetDocExampleParameterValue("ref", "vector"); SetDocExampleParameterValue("ref.vector.in","VectorData_QB1_bis.shp"); SetDocExampleParameterValue("ref.vector.field","Class"); - SetDocExampleParameterValue("nodatalabel","255"); + SetDocExampleParameterValue("refnodatalabel","255"); } void DoUpdateParameters() ITK_OVERRIDE @@ -193,7 +201,7 @@ private: void LogContingencyTable(const ContingencyTableType& contingencyTable) { - otbAppLogINFO("Contingency table : :\n" << contingencyTable); + otbAppLogINFO("Contingency table: reference labels (rows) vs. produced labels (cols)\n" << contingencyTable); } void writeContingencyTable(const ContingencyTableType& contingencyTable) @@ -286,14 +294,22 @@ private: std::string field; rasterizeReference = RasterizeFilterType::New(); - sid.nodata = this->GetParameterInt("nodatalabel"); + sid.refnodata = this->GetParameterInt("refnodatalabel"); + sid.refhasnodata = this->IsParameterEnabled("refnodatalabel"); + sid.prodnodata = this->GetParameterInt("prodnodatalabel"); + sid.prodhasnodata = this->IsParameterEnabled("prodnodatalabel"); + + if (GetParameterString("ref") == "raster") { reference = this->GetParameterInt32Image("ref.raster.in"); } else { + // Force nodata to true since it will be generated during rasterization + sid.refhasnodata = true; + ogrRef = otb::ogr::DataSource::New(GetParameterString("ref.vector.in"), otb::ogr::DataSource::Modes::Read); // Get field name @@ -309,7 +325,7 @@ private: rasterizeReference->AddOGRDataSource(ogrRef); rasterizeReference->SetOutputParametersFromImage(input); - rasterizeReference->SetBackgroundValue(sid.nodata); + rasterizeReference->SetBackgroundValue(sid.refnodata); rasterizeReference->SetBurnAttribute(field.c_str()); reference = rasterizeReference->GetOutput(); @@ -371,7 +387,7 @@ private: ImageIteratorType itRef( reference, streamRegion ); itRef.GoToBegin(); - calculator->Compute( itRef, itInput ); + calculator->Compute( itRef, itInput,sid.refhasnodata,sid.refnodata,sid.prodhasnodata,sid.prodnodata); } ContingencyTableType contingencyTable = calculator->GetContingencyTable(); @@ -412,7 +428,7 @@ private: labelProd = static_cast<ClassLabelType> (itInput.Get()); // Extraction of the reference/produced class labels - if ((labelRef != sid.nodata) && (labelProd != sid.nodata)) + if ((!sid.refhasnodata || labelRef != sid.refnodata) && (!sid.prodhasnodata || labelProd != sid.prodnodata)) { // If the current labels have not been added to their respective mapOfClasses yet if (mapOfClassesRef.insert(MapOfClassesType::value_type(labelRef, itLabelRef)).second) diff --git a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h index e3d8e9355a3efdc7bb300486fd60ac8c306884bd..e9834d88ae36d8e7d225f960ae6f5f3be9cf9143 100644 --- a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h +++ b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.h @@ -60,7 +60,8 @@ public: /** Populate the confusion Matrix for a image iteration */ template<class TRefIterator, class TProdIterator> - void Compute(TRefIterator itRef, TProdIterator itProd); + void Compute(TRefIterator itRef, TProdIterator itProd, bool refHasNoData = false, typename TRefIterator::InternalPixelType refNoData = 0, + bool prodHasNoData = false, typename TProdIterator::InternalPixelType prodNoData = 0); /** Populate the confusion Matrix with input which provide GetMeasurementVector()[0] access */ template<class TRefIterator, class TProdIterator> @@ -86,8 +87,6 @@ private: unsigned long m_NumberOfRefClasses; unsigned long m_NumberOfProdClasses; unsigned long m_NumberOfSamples; - - }; } diff --git a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx index b9583c0e6d359655bd5043387d2e2b7086e63fad..49fdbc9df8ad0c9734e8e1105e402b6bc5d9af47 100644 --- a/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx +++ b/Modules/Learning/Unsupervised/include/otbContingencyTableCalculator.txx @@ -65,14 +65,19 @@ template<class TClassLabel> template<class TRefIterator, class TProdIterator> void ContingencyTableCalculator<TClassLabel> -::Compute(TRefIterator itRef, TProdIterator itProd) +::Compute(TRefIterator itRef, TProdIterator itProd, bool refHasNoData, typename TRefIterator::InternalPixelType refNoData, + bool prodHasNoData, typename TProdIterator::InternalPixelType prodNoData) { while( !itRef.IsAtEnd() && !itProd.IsAtEnd() ) { - ++m_LabelCount[itRef.Get()][itProd.Get()]; - ++itRef; + if((!prodHasNoData || itProd.Get()!=prodNoData) + &&(!refHasNoData || itRef.Get()!=refNoData)) + { + ++m_LabelCount[itRef.Get()][itProd.Get()]; + ++m_NumberOfSamples; + } + ++itRef; ++itProd; - ++m_NumberOfSamples; } }