From 99afedee7b3cd032bf2b42a30c15b70f39097b34 Mon Sep 17 00:00:00 2001
From: Jordi Inglada <jordi.inglada@cesbio.cnes.fr>
Date: Tue, 8 Jun 2010 15:41:18 +0200
Subject: [PATCH] BUG: OverallAccuracy is null

---
 Code/Learning/otbConfusionMatrixCalculator.h  |  8 ++--
 .../Learning/otbConfusionMatrixCalculator.txx | 44 +++++++++++++++++++
 .../otbConfusionMatrixCalculatorTest.cxx      | 24 +++++++++-
 3 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/Code/Learning/otbConfusionMatrixCalculator.h b/Code/Learning/otbConfusionMatrixCalculator.h
index 76108653d1..87a93726b0 100644
--- a/Code/Learning/otbConfusionMatrixCalculator.h
+++ b/Code/Learning/otbConfusionMatrixCalculator.h
@@ -67,9 +67,10 @@ public:
   itkGetConstObjectMacro(ReferenceLabels, RefListLabelType);
   itkSetObjectMacro(ProducedLabels, ProdListLabelType);
   itkGetConstObjectMacro(ProducedLabels, ProdListLabelType);
-  itkGetConstMacro(KappaIndex, double);
-  itkGetConstMacro(OverallAccuracy, double);
-  itkGetConstMacro(NumberOfClasses, unsigned short);
+  itkGetMacro(KappaIndex, double);
+  itkGetMacro(OverallAccuracy, double);
+  itkGetMacro(NumberOfClasses, unsigned short);
+  itkGetMacro(NumberOfSamples, unsigned long);
   itkGetMacro(ConfusionMatrix, ConfusionMatrixType);
   
 protected:
@@ -90,6 +91,7 @@ private:
   std::map<int,int>         m_MapOfClasses;
 
   unsigned short            m_NumberOfClasses;
+  unsigned long             m_NumberOfSamples;
 
   ConfusionMatrixType       m_ConfusionMatrix;
 
diff --git a/Code/Learning/otbConfusionMatrixCalculator.txx b/Code/Learning/otbConfusionMatrixCalculator.txx
index 0f8cb8d219..a5e9eaf127 100644
--- a/Code/Learning/otbConfusionMatrixCalculator.txx
+++ b/Code/Learning/otbConfusionMatrixCalculator.txx
@@ -64,6 +64,8 @@ ConfusionMatrixCalculator<TRefListLabel,TProdListLabel>
         throw itk::ExceptionObject(__FILE__, __LINE__, "ListSample size missmatch", ITK_LOCATION);
     }
 
+  m_NumberOfSamples = m_ReferenceLabels->Size();
+  
   // count de number of classes
 
   int countClasses = 0;
@@ -82,6 +84,11 @@ ConfusionMatrixCalculator<TRefListLabel,TProdListLabel>
 
   m_NumberOfClasses = countClasses;
 
+  std::vector< long int > samplesPerClass;
+
+  for(unsigned int i=0; i<m_NumberOfClasses; i++)
+    samplesPerClass.push_back(0);
+
   m_ConfusionMatrix = ConfusionMatrixType(m_NumberOfClasses, m_NumberOfClasses);
   m_ConfusionMatrix.Fill(0);
 
@@ -96,12 +103,49 @@ ConfusionMatrixCalculator<TRefListLabel,TProdListLabel>
     int refPos = m_MapOfClasses[refLabel];
     int prodPos = m_MapOfClasses[prodLabel];
 
+    ++samplesPerClass[refPos];
     m_ConfusionMatrix( refPos,prodPos )+=1;
 
     ++refIterator;
     ++prodIterator;
 
     }
+
+
+  otbGenericMsgDebugMacro(<<"Confusion matrix " << m_ConfusionMatrix);
+  
+  for(unsigned int i=0; i<m_NumberOfClasses; i++)
+    otbGenericMsgDebugMacro(<<"Samples per class " << samplesPerClass[i]);
+  
+  this->m_OverallAccuracy  = 0.;
+  for (unsigned int i = 0;i<m_NumberOfClasses;++i)
+  {
+    this->m_OverallAccuracy += m_ConfusionMatrix(i,i);
+  }
+
+  this->m_OverallAccuracy/=static_cast<double>(m_NumberOfSamples);
+
+  otbGenericMsgDebugMacro(<<"OA " << this->m_OverallAccuracy);
+
+  
+  double luckyRate = 0.;
+  for (unsigned int i = 0;i<m_NumberOfClasses;++i)
+  {
+    double sum_ij = 0.;
+    double sum_ji = 0.;
+    for (unsigned int j = 0;j<m_NumberOfClasses;++j)
+    {
+      sum_ij +=m_ConfusionMatrix(i,j);
+      sum_ji +=m_ConfusionMatrix(j,i);
+    }
+    luckyRate+=sum_ij*sum_ji;
+  }
+
+
+  luckyRate/=vcl_pow(m_NumberOfSamples,2.0);
+
+  double m_KappaIndex = (m_OverallAccuracy-luckyRate)/(1-luckyRate);
+
   
 }
 
diff --git a/Testing/Code/Learning/otbConfusionMatrixCalculatorTest.cxx b/Testing/Code/Learning/otbConfusionMatrixCalculatorTest.cxx
index b61df7d81c..e5c16ad8a0 100644
--- a/Testing/Code/Learning/otbConfusionMatrixCalculatorTest.cxx
+++ b/Testing/Code/Learning/otbConfusionMatrixCalculatorTest.cxx
@@ -177,6 +177,11 @@ int otbConfusionMatrixCalculatorUpdate(int argc, char* argv[])
     std::cerr << "Wrong number of classes" << std::endl;
     return EXIT_FAILURE;
     }
+  if( calculator->GetNumberOfSamples() != nbSamples )
+    {
+    std::cerr << "Wrong number of samples" << std::endl;
+    return EXIT_FAILURE;
+    }
 
   CalculatorType::ConfusionMatrixType confmat = calculator->GetConfusionMatrix();
 
@@ -186,8 +191,11 @@ int otbConfusionMatrixCalculatorUpdate(int argc, char* argv[])
     for (int j = 0; j < nbClasses; j++)
       {
       double goodValue = 0.0;
-      if (i == j) goodValue = nbSamples / nbClasses;
-      if (confmat(i, j) != goodValue) totalError += confmat(i, j);
+      if (i == j)
+	goodValue = nbSamples / nbClasses;
+      else
+	if (confmat(i, j) != goodValue)
+	  totalError += confmat(i, j);
       }
 
   if( totalError > 0.001 )
@@ -197,6 +205,18 @@ int otbConfusionMatrixCalculatorUpdate(int argc, char* argv[])
     return EXIT_FAILURE;
     }
 
+  if( calculator->GetOverallAccuracy() != 1.0 )
+    {
+    std::cerr<< "OA = " << calculator->GetOverallAccuracy() << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  if( calculator->GetKappaIndex() != 1.0 )
+    {
+    std::cerr<< "OA = " << calculator->GetKappaIndex() << std::endl;
+    return EXIT_FAILURE;
+    }
+
   
   return EXIT_SUCCESS;
 }
-- 
GitLab