Merge pull request #1248 from vkocheganov:chi_square_alt
This commit is contained in:
commit
1840fd5f00
@ -173,6 +173,8 @@ Compares two histograms.
|
|||||||
|
|
||||||
* **CV_COMP_CHISQR** Chi-Square
|
* **CV_COMP_CHISQR** Chi-Square
|
||||||
|
|
||||||
|
* **CV_COMP_CHISQR_ALT** Alternative Chi-Square
|
||||||
|
|
||||||
* **CV_COMP_INTERSECT** Intersection
|
* **CV_COMP_INTERSECT** Intersection
|
||||||
|
|
||||||
* **CV_COMP_BHATTACHARYYA** Bhattacharyya distance
|
* **CV_COMP_BHATTACHARYYA** Bhattacharyya distance
|
||||||
@ -202,6 +204,14 @@ The functions ``compareHist`` compare two dense or two sparse histograms using t
|
|||||||
|
|
||||||
d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}
|
d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}
|
||||||
|
|
||||||
|
* Alternative Chi-Square (``method=CV_COMP_CHISQR_ALT``)
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
d(H_1,H_2) = 2 * \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)+H_2(I)}
|
||||||
|
|
||||||
|
This alternative formula is regularly used for texture comparison. See e.g. [Puzicha1997]_.
|
||||||
|
|
||||||
* Intersection (``method=CV_COMP_INTERSECT``)
|
* Intersection (``method=CV_COMP_INTERSECT``)
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -493,3 +503,4 @@ The function clears histogram bins that are below the specified threshold.
|
|||||||
|
|
||||||
|
|
||||||
.. [RubnerSept98] Y. Rubner. C. Tomasi, L.J. Guibas. *The Earth Mover’s Distance as a Metric for Image Retrieval*. Technical Report STAN-CS-TN-98-86, Department of Computer Science, Stanford University, September 1998.
|
.. [RubnerSept98] Y. Rubner. C. Tomasi, L.J. Guibas. *The Earth Mover’s Distance as a Metric for Image Retrieval*. Technical Report STAN-CS-TN-98-86, Department of Computer Science, Stanford University, September 1998.
|
||||||
|
.. [Puzicha1997] Puzicha, J., Hofmann, T., and Buhmann, J. *Non-parametric similarity measures for unsupervised texture segmentation and image retrieval.* In Proc. IEEE Conf. Computer Vision and Pattern Recognition, San Juan, Puerto Rico, pp. 267-272, 1997.
|
||||||
|
@ -508,7 +508,8 @@ enum
|
|||||||
CV_COMP_CHISQR =1,
|
CV_COMP_CHISQR =1,
|
||||||
CV_COMP_INTERSECT =2,
|
CV_COMP_INTERSECT =2,
|
||||||
CV_COMP_BHATTACHARYYA =3,
|
CV_COMP_BHATTACHARYYA =3,
|
||||||
CV_COMP_HELLINGER =CV_COMP_BHATTACHARYYA
|
CV_COMP_HELLINGER =CV_COMP_BHATTACHARYYA,
|
||||||
|
CV_COMP_CHISQR_ALT =4
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Mask size for distance transform */
|
/* Mask size for distance transform */
|
||||||
|
@ -1990,12 +1990,12 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method )
|
|||||||
const float* h2 = (const float*)it.planes[1].data;
|
const float* h2 = (const float*)it.planes[1].data;
|
||||||
len = it.planes[0].rows*it.planes[0].cols*H1.channels();
|
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++ )
|
for( j = 0; j < len; j++ )
|
||||||
{
|
{
|
||||||
double a = h1[j] - h2[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 )
|
if( fabs(b) > DBL_EPSILON )
|
||||||
result += a*a/b;
|
result += a*a/b;
|
||||||
}
|
}
|
||||||
@ -2034,7 +2034,9 @@ double cv::compareHist( InputArray _H1, InputArray _H2, int method )
|
|||||||
CV_Error( CV_StsBadArg, "Unknown comparison 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();
|
size_t total = H1.total();
|
||||||
double scale = 1./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) );
|
CV_Assert( H1.size(i) == H2.size(i) );
|
||||||
|
|
||||||
const SparseMat *PH1 = &H1, *PH2 = &H2;
|
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);
|
std::swap(PH1, PH2);
|
||||||
|
|
||||||
SparseMatConstIterator it = PH1->begin();
|
SparseMatConstIterator it = PH1->begin();
|
||||||
int N1 = (int)PH1->nzcount(), N2 = (int)PH2->nzcount();
|
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 )
|
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();
|
const SparseMat::Node* node = it.node();
|
||||||
float v2 = PH2->value<float>(node->idx, (size_t*)&node->hashval);
|
float v2 = PH2->value<float>(node->idx, (size_t*)&node->hashval);
|
||||||
double a = v1 - v2;
|
double a = v1 - v2;
|
||||||
double b = v1;
|
double b = (method == CV_COMP_CHISQR) ? v1 : v1 + v2;
|
||||||
if( fabs(b) > DBL_EPSILON )
|
if( fabs(b) > DBL_EPSILON )
|
||||||
result += a*a/b;
|
result += a*a/b;
|
||||||
}
|
}
|
||||||
@ -2146,6 +2148,9 @@ double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method )
|
|||||||
else
|
else
|
||||||
CV_Error( CV_StsBadArg, "Unknown comparison method" );
|
CV_Error( CV_StsBadArg, "Unknown comparison method" );
|
||||||
|
|
||||||
|
if( method == CV_COMP_CHISQR_ALT )
|
||||||
|
result *= 2;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2485,13 +2490,13 @@ cvCompareHist( const CvHistogram* hist1,
|
|||||||
CvSparseMatIterator iterator;
|
CvSparseMatIterator iterator;
|
||||||
CvSparseNode *node1, *node2;
|
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;
|
CvSparseMat* t;
|
||||||
CV_SWAP( mat1, mat2, 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 );
|
for( node1 = cvInitSparseMatIterator( mat1, &iterator );
|
||||||
node1 != 0; node1 = cvGetNextSparseNode( &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 );
|
uchar* node2_data = cvPtrND( mat2, CV_NODE_IDX(mat1,node1), 0, 0, &node1->hashval );
|
||||||
double v2 = node2_data ? *(float*)node2_data : 0.f;
|
double v2 = node2_data ? *(float*)node2_data : 0.f;
|
||||||
double a = v1 - v2;
|
double a = v1 - v2;
|
||||||
double b = v1;
|
double b = (method == CV_COMP_CHISQR) ? v1 : v1 + v2;
|
||||||
if( fabs(b) > DBL_EPSILON )
|
if( fabs(b) > DBL_EPSILON )
|
||||||
result += a*a/b;
|
result += a*a/b;
|
||||||
}
|
}
|
||||||
@ -2590,6 +2595,9 @@ cvCompareHist( const CvHistogram* hist1,
|
|||||||
else
|
else
|
||||||
CV_Error( CV_StsBadArg, "Unknown comparison method" );
|
CV_Error( CV_StsBadArg, "Unknown comparison method" );
|
||||||
|
|
||||||
|
if( method == CV_COMP_CHISQR_ALT )
|
||||||
|
result *= 2;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,7 +948,7 @@ int CV_ThreshHistTest::validate_test_results( int /*test_case_idx*/ )
|
|||||||
class CV_CompareHistTest : public CV_BaseHistTest
|
class CV_CompareHistTest : public CV_BaseHistTest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum { MAX_METHOD = 4 };
|
enum { MAX_METHOD = 5 };
|
||||||
|
|
||||||
CV_CompareHistTest();
|
CV_CompareHistTest();
|
||||||
protected:
|
protected:
|
||||||
@ -1014,6 +1014,8 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
|
|||||||
result0[CV_COMP_INTERSECT] += MIN(v0,v1);
|
result0[CV_COMP_INTERSECT] += MIN(v0,v1);
|
||||||
if( fabs(v0) > DBL_EPSILON )
|
if( fabs(v0) > DBL_EPSILON )
|
||||||
result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;
|
result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;
|
||||||
|
if( fabs(v0 + v1) > DBL_EPSILON )
|
||||||
|
result0[CV_COMP_CHISQR_ALT] += (v0 - v1)*(v0 - v1)/(v0 + v1);
|
||||||
s0 += v0;
|
s0 += v0;
|
||||||
s1 += v1;
|
s1 += v1;
|
||||||
sq0 += v0*v0;
|
sq0 += v0*v0;
|
||||||
@ -1039,6 +1041,8 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
|
|||||||
result0[CV_COMP_INTERSECT] += MIN(v0,v1);
|
result0[CV_COMP_INTERSECT] += MIN(v0,v1);
|
||||||
if( fabs(v0) > DBL_EPSILON )
|
if( fabs(v0) > DBL_EPSILON )
|
||||||
result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;
|
result0[CV_COMP_CHISQR] += (v0 - v1)*(v0 - v1)/v0;
|
||||||
|
if( fabs(v0 + v1) > DBL_EPSILON )
|
||||||
|
result0[CV_COMP_CHISQR_ALT] += (v0 - v1)*(v0 - v1)/(v0 + v1);
|
||||||
s0 += v0;
|
s0 += v0;
|
||||||
sq0 += v0*v0;
|
sq0 += v0*v0;
|
||||||
result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
|
result0[CV_COMP_BHATTACHARYYA] += sqrt(v0*v1);
|
||||||
@ -1053,6 +1057,8 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result0[CV_COMP_CHISQR_ALT] *= 2;
|
||||||
|
|
||||||
t = (sq0 - s0*s0/total_size)*(sq1 - s1*s1/total_size);
|
t = (sq0 - s0*s0/total_size)*(sq1 - s1*s1/total_size);
|
||||||
result0[CV_COMP_CORREL] = fabs(t) > DBL_EPSILON ?
|
result0[CV_COMP_CORREL] = fabs(t) > DBL_EPSILON ?
|
||||||
(result0[CV_COMP_CORREL] - s0*s1/total_size)/sqrt(t) : 1;
|
(result0[CV_COMP_CORREL] - s0*s1/total_size)/sqrt(t) : 1;
|
||||||
@ -1067,6 +1073,7 @@ int CV_CompareHistTest::validate_test_results( int /*test_case_idx*/ )
|
|||||||
double v = result[i], v0 = result0[i];
|
double v = result[i], v0 = result0[i];
|
||||||
const char* method_name =
|
const char* method_name =
|
||||||
i == CV_COMP_CHISQR ? "Chi-Square" :
|
i == CV_COMP_CHISQR ? "Chi-Square" :
|
||||||
|
i == CV_COMP_CHISQR_ALT ? "Alternative Chi-Square" :
|
||||||
i == CV_COMP_CORREL ? "Correlation" :
|
i == CV_COMP_CORREL ? "Correlation" :
|
||||||
i == CV_COMP_INTERSECT ? "Intersection" :
|
i == CV_COMP_INTERSECT ? "Intersection" :
|
||||||
i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" : "Unknown";
|
i == CV_COMP_BHATTACHARYYA ? "Bhattacharyya" : "Unknown";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user