Introduce CV_COMP_CHISQR_ALT, an alternative method to calculate ChiSquare Histogram comparison
There's some disagreement about the correct formula. has its supporters, however, for texture analysis, the newly introduced formula became standard. The commit enables both uses without breaking backward compatibility. First contributor of this commit was sperrholz.
This commit is contained in:
@@ -1990,12 +1990,12 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method )
|
||||
const float* h2 = (const float*)it.planes[1].data;
|
||||
len = it.planes[0].rows*it.planes[0].cols*H1.channels();
|
||||
|
||||
if( method == CV_COMP_CHISQR )
|
||||
if( (method == CV_COMP_CHISQR) || (method == CV_COMP_CHISQR_ALT))
|
||||
{
|
||||
for( j = 0; j < len; j++ )
|
||||
{
|
||||
double a = h1[j] - h2[j];
|
||||
double b = h1[j];
|
||||
double b = (method == CV_COMP_CHISQR) ? h1[j] : h1[j] + h2[j];
|
||||
if( fabs(b) > DBL_EPSILON )
|
||||
result += a*a/b;
|
||||
}
|
||||
@@ -2034,7 +2034,9 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method )
|
||||
CV_Error( CV_StsBadArg, "Unknown comparison method" );
|
||||
}
|
||||
|
||||
if( method == CV_COMP_CORREL )
|
||||
if( method == CV_COMP_CHISQR_ALT )
|
||||
result *= 2;
|
||||
else if( method == CV_COMP_CORREL )
|
||||
{
|
||||
size_t total = H1.total();
|
||||
double scale = 1./total;
|
||||
@@ -2063,13 +2065,13 @@ 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 )
|
||||
if( PH1->nzcount() > PH2->nzcount() && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT)
|
||||
std::swap(PH1, PH2);
|
||||
|
||||
SparseMatConstIterator it = PH1->begin();
|
||||
int N1 = (int)PH1->nzcount(), N2 = (int)PH2->nzcount();
|
||||
|
||||
if( method == CV_COMP_CHISQR )
|
||||
if( (method == CV_COMP_CHISQR) || (method == CV_COMP_CHISQR_ALT) )
|
||||
{
|
||||
for( i = 0; i < N1; i++, ++it )
|
||||
{
|
||||
@@ -2077,7 +2079,7 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method )
|
||||
const SparseMat::Node* node = it.node();
|
||||
float v2 = PH2->value<float>(node->idx, (size_t*)&node->hashval);
|
||||
double a = v1 - v2;
|
||||
double b = v1;
|
||||
double b = (method == CV_COMP_CHISQR) ? v1 : v1 + v2;
|
||||
if( fabs(b) > DBL_EPSILON )
|
||||
result += a*a/b;
|
||||
}
|
||||
@@ -2146,6 +2148,9 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method )
|
||||
else
|
||||
CV_Error( CV_StsBadArg, "Unknown comparison method" );
|
||||
|
||||
if( method == CV_COMP_CHISQR_ALT )
|
||||
result *= 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2485,13 +2490,13 @@ cvCompareHist( const CvHistogram* hist1,
|
||||
CvSparseMatIterator iterator;
|
||||
CvSparseNode *node1, *node2;
|
||||
|
||||
if( mat1->heap->active_count > mat2->heap->active_count && method != CV_COMP_CHISQR )
|
||||
if( mat1->heap->active_count > mat2->heap->active_count && method != CV_COMP_CHISQR && method != CV_COMP_CHISQR_ALT)
|
||||
{
|
||||
CvSparseMat* t;
|
||||
CV_SWAP( mat1, mat2, t );
|
||||
}
|
||||
|
||||
if( method == CV_COMP_CHISQR )
|
||||
if( (method == CV_COMP_CHISQR) || (method == CV_COMP_CHISQR_ALT) )
|
||||
{
|
||||
for( node1 = cvInitSparseMatIterator( mat1, &iterator );
|
||||
node1 != 0; node1 = cvGetNextSparseNode( &iterator ))
|
||||
@@ -2500,7 +2505,7 @@ cvCompareHist( const CvHistogram* hist1,
|
||||
uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1), 0, 0, &node1->hashval );
|
||||
double v2 = node2_data ? *(float*)node2_data : 0.f;
|
||||
double a = v1 - v2;
|
||||
double b = v1;
|
||||
double b = (method == CV_COMP_CHISQR) ? v1 : v1 + v2;
|
||||
if( fabs(b) > DBL_EPSILON )
|
||||
result += a*a/b;
|
||||
}
|
||||
@@ -2590,6 +2595,9 @@ cvCompareHist( const CvHistogram* hist1,
|
||||
else
|
||||
CV_Error( CV_StsBadArg, "Unknown comparison method" );
|
||||
|
||||
if( method == CV_COMP_CHISQR_ALT )
|
||||
result *= 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user