Merge pull request #2765 from pradeep-pyro:kullback_leibler
This commit is contained in:
		@@ -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)` .
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 */
 | 
			
		||||
 
 | 
			
		||||
@@ -2325,6 +2325,21 @@ 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( fabs(p) <= DBL_EPSILON ) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                if(  fabs(q) <= DBL_EPSILON ) {
 | 
			
		||||
                    q = 1e-10;
 | 
			
		||||
                }
 | 
			
		||||
                result += p * std::log( p / q );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            CV_Error( CV_StsBadArg, "Unknown comparison method" );
 | 
			
		||||
    }
 | 
			
		||||
@@ -2360,7 +2375,7 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method )
 | 
			
		||||
        CV_Assert( H1.size(i) == H2.size(i) );
 | 
			
		||||
 | 
			
		||||
    const SparseMat *PH1 = &H1, *PH2 = &H2;
 | 
			
		||||
    if( PH1->nzcount() > PH2->nzcount() && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT)
 | 
			
		||||
    if( PH1->nzcount() > PH2->nzcount() && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT && method != CV_COMP_KL_DIV )
 | 
			
		||||
        std::swap(PH1, PH2);
 | 
			
		||||
 | 
			
		||||
    SparseMatConstIterator it = PH1->begin();
 | 
			
		||||
@@ -2440,6 +2455,18 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method )
 | 
			
		||||
        s1 = fabs(s1) > FLT_EPSILON ? 1./std::sqrt(s1) : 1.;
 | 
			
		||||
        result = std::sqrt(std::max(1. - result*s1, 0.));
 | 
			
		||||
    }
 | 
			
		||||
    else if( method == CV_COMP_KL_DIV )
 | 
			
		||||
    {
 | 
			
		||||
        for( i = 0; i < N1; i++, ++it )
 | 
			
		||||
        {
 | 
			
		||||
            double v1 = it.value<float>();
 | 
			
		||||
            const SparseMat::Node* node = it.node();
 | 
			
		||||
            double v2 = PH2->value<float>(node->idx, (size_t*)&node->hashval);
 | 
			
		||||
            if( !v2 )
 | 
			
		||||
                v2 = 1e-10;
 | 
			
		||||
            result += v1 * std::log( v1 / v2 );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        CV_Error( CV_StsBadArg, "Unknown comparison method" );
 | 
			
		||||
 | 
			
		||||
@@ -2785,7 +2812,7 @@ cvCompareHist( const CvHistogram* hist1,
 | 
			
		||||
    CvSparseMatIterator iterator;
 | 
			
		||||
    CvSparseNode *node1, *node2;
 | 
			
		||||
 | 
			
		||||
    if( mat1->heap->active_count > mat2->heap->active_count && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT)
 | 
			
		||||
    if( mat1->heap->active_count > mat2->heap->active_count && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT && method != CV_COMP_KL_DIV )
 | 
			
		||||
    {
 | 
			
		||||
        CvSparseMat* t;
 | 
			
		||||
        CV_SWAP( mat1, mat2, t );
 | 
			
		||||
@@ -2887,6 +2914,13 @@ cvCompareHist( const CvHistogram* hist1,
 | 
			
		||||
        result = 1. - result*s1;
 | 
			
		||||
        result = sqrt(MAX(result,0.));
 | 
			
		||||
    }
 | 
			
		||||
    else if( method == CV_COMP_KL_DIV )
 | 
			
		||||
    {
 | 
			
		||||
        cv::SparseMat sH1, sH2;
 | 
			
		||||
        ((const CvSparseMat*)hist1->bins)->copyToSparseMat(sH1);
 | 
			
		||||
        ((const CvSparseMat*)hist2->bins)->copyToSparseMat(sH2);
 | 
			
		||||
        result = cv::compareHist( sH1, sH2, CV_COMP_KL_DIV );
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        CV_Error( CV_StsBadArg, "Unknown comparison method" );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,13 @@ 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  )
 | 
			
		||||
                continue;
 | 
			
		||||
            if( fabs(v1) <= DBL_EPSILON )
 | 
			
		||||
                v1 = 1e-10;
 | 
			
		||||
            result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
@@ -1046,6 +1053,13 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
 | 
			
		||||
            s0 += v0;
 | 
			
		||||
            sq0 += v0*v0;
 | 
			
		||||
            result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
 | 
			
		||||
            {
 | 
			
		||||
            if (v0 <= DBL_EPSILON)
 | 
			
		||||
                continue;
 | 
			
		||||
            if (!v1)
 | 
			
		||||
                v1 = 1e-10;
 | 
			
		||||
            result0[CV_COMP_KL_DIV] += v0 * std::log( v0 / v1 );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for( node = cvInitSparseMatIterator( sparse1, &iterator );
 | 
			
		||||
@@ -1076,7 +1090,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) )
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user