Implemented Kullback-Leibler divergence
authorpradeep <pradeep.pyro@gmail.com>
Sat, 17 May 2014 15:44:31 +0000 (23:44 +0800)
committerpradeep <pradeep.pyro@gmail.com>
Sat, 17 May 2014 15:44:31 +0000 (23:44 +0800)
modules/imgproc/doc/histograms.rst
modules/imgproc/include/opencv2/imgproc.hpp
modules/imgproc/include/opencv2/imgproc/types_c.h
modules/imgproc/src/histogram.cpp
modules/imgproc/test/test_histograms.cpp

index 91199f3..5ebf168 100644 (file)
@@ -181,6 +181,8 @@ Compares two histograms.
 
             * **CV_COMP_HELLINGER**     Synonym for ``CV_COMP_BHATTACHARYYA``
 
+            * **CV_COMP_KL_DIV**     Kullback-Leibler divergence
+
 The functions ``compareHist`` compare two dense or two sparse histograms using the specified method:
 
 * Correlation (``method=CV_COMP_CORREL``)
@@ -224,6 +226,12 @@ The functions ``compareHist`` compare two dense or two sparse histograms using t
 
         d(H_1,H_2) =  \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}}
 
+* Kullback-Leibler divergence (``method=CV_COMP_KL_DIV``).
+
+    .. math::
+
+        d(H_1,H_2) = \sum _I H_1(I) \log \left(\frac{H_1(I)}{H_2(I)}\right)
+
 The function returns
 :math:`d(H_1, H_2)` .
 
index 7928ae0..76d65c2 100644 (file)
@@ -204,7 +204,8 @@ enum { HISTCMP_CORREL        = 0,
        HISTCMP_INTERSECT     = 2,
        HISTCMP_BHATTACHARYYA = 3,
        HISTCMP_HELLINGER     = HISTCMP_BHATTACHARYYA,
-       HISTCMP_CHISQR_ALT    = 4
+       HISTCMP_CHISQR_ALT    = 4,
+       HISTCMP_KL_DIV        = 5
      };
 
 //! the color conversion code
index dd0d8b8..de8fb62 100644 (file)
@@ -509,7 +509,8 @@ enum
     CV_COMP_INTERSECT     =2,
     CV_COMP_BHATTACHARYYA =3,
     CV_COMP_HELLINGER     =CV_COMP_BHATTACHARYYA,
-    CV_COMP_CHISQR_ALT    =4
+    CV_COMP_CHISQR_ALT    =4,
+    CV_COMP_KL_DIV        =5
 };
 
 /* Mask size for distance transform */
index e7e03ce..1be7315 100644 (file)
@@ -2323,6 +2323,18 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method )
                 s2 += b;
             }
         }
+        else if( method == CV_COMP_KL_DIV )
+        {
+            for( j = 0; j < len; j++ ){
+                double p = h1[j];
+                double q = h2[j];
+                if( p == 0.0 )
+                    continue;
+                if( q == 0.0 )
+                    q += 1e-10;
+                result += p * cv::log( p / q );
+            }
+        }
         else
             CV_Error( CV_StsBadArg, "Unknown comparison method" );
     }
index 19ccc65..55f4df0 100644 (file)
@@ -948,7 +948,7 @@ int CV_ThreshHistTest::validate_test_results( int /*test_case_idx*/ )
 class CV_CompareHistTest : public CV_BaseHistTest
 {
 public:
-    enum { MAX_METHOD = 5 };
+    enum { MAX_METHOD = 6 };
 
     CV_CompareHistTest();
 protected:
@@ -1021,6 +1021,12 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
             sq0 += v0*v0;
             sq1 += v1*v1;
             result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
+            if( fabs(v0) > DBL_EPSILON )
+            {
+                if( fabs(v1) < DBL_EPSILON )
+                    v1 += 1e-10;
+                result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 );
+            }
         }
     }
     else
@@ -1046,6 +1052,12 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
             s0 += v0;
             sq0 += v0*v0;
             result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
+            if( fabs(v0) > DBL_EPSILON )
+            {
+                if( fabs(v1) < DBL_EPSILON )
+                    v1 += 1e-10;
+                result0[CV_COMP_KL_DIV] += v0 * cv::log( v0 / v1 );
+            }
         }
 
         for( node = cvInitSparseMatIterator( sparse1, &iterator );
@@ -1076,7 +1088,8 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
             i == CV_COMP_CHISQR_ALT ? "Alternative Chi-Square" :
             i == CV_COMP_CORREL ? "Correlation" :
             i == CV_COMP_INTERSECT ? "Intersection" :
-            i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" : "Unknown";
+            i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" :
+            i == CV_COMP_KL_DIV ? "Kullback-Leibler" : "Unknown";
 
         if( cvIsNaN(v) || cvIsInf(v) )
         {