mirror of
https://github.com/zebrajr/opencv.git
synced 2025-12-06 00:19:46 +01:00
Merge pull request #27516 from ClaudioMartino:norm_KL_div
New normalization in histogram comparison tutorial to use Kullback-Leibler divergence
This commit is contained in:
commit
478040c408
|
|
@ -25,7 +25,7 @@ Theory
|
|||
|
||||
- To compare two histograms ( \f$H_{1}\f$ and \f$H_{2}\f$ ), first we have to choose a *metric*
|
||||
(\f$d(H_{1}, H_{2})\f$) to express how well both histograms match.
|
||||
- OpenCV implements the function @ref cv::compareHist to perform a comparison. It also offers 4
|
||||
- OpenCV implements the function @ref cv::compareHist to perform a comparison. It also offers 6
|
||||
different metrics to compute the matching:
|
||||
-# **Correlation ( cv::HISTCMP_CORREL )**
|
||||
\f[d(H_1,H_2) = \frac{\sum_I (H_1(I) - \bar{H_1}) (H_2(I) - \bar{H_2})}{\sqrt{\sum_I(H_1(I) - \bar{H_1})^2 \sum_I(H_2(I) - \bar{H_2})^2}}\f]
|
||||
|
|
@ -36,12 +36,18 @@ Theory
|
|||
-# **Chi-Square ( cv::HISTCMP_CHISQR )**
|
||||
\f[d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}\f]
|
||||
|
||||
-# **Intersection ( method=cv::HISTCMP_INTERSECT )**
|
||||
-# **Intersection ( cv::HISTCMP_INTERSECT )**
|
||||
\f[d(H_1,H_2) = \sum _I \min (H_1(I), H_2(I))\f]
|
||||
|
||||
-# **Bhattacharyya distance ( cv::HISTCMP_BHATTACHARYYA )**
|
||||
\f[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)}}\f]
|
||||
|
||||
-# **Alternative Chi-Square ( cv::HISTCMP_CHISQR_ALT )**
|
||||
\f[d(H_1,H_2) = 2 * \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)+H_2(I)}\f]
|
||||
|
||||
-# **Kullback-Leibler divergence ( cv::HISTCMP_KL_DIV )**
|
||||
\f[d(H_1,H_2) = \sum _I H_1(I) \log \left(\frac{H_1(I)}{H_2(I)}\right)\f] */
|
||||
|
||||
Code
|
||||
----
|
||||
|
||||
|
|
@ -123,7 +129,7 @@ Explanation
|
|||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Convert to HSV half
|
||||
@end_toggle
|
||||
|
||||
- Initialize the arguments to calculate the histograms (bins, ranges and channels H and S ).
|
||||
- Initialize the arguments to calculate the histograms (bins, ranges and channels H and S).
|
||||
|
||||
@add_toggle_cpp
|
||||
@snippet samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp Using 50 bins for hue and 60 for saturation
|
||||
|
|
@ -151,7 +157,7 @@ Explanation
|
|||
@snippet samples/python/tutorial_code/Histograms_Matching/histogram_comparison/compareHist_Demo.py Calculate the histograms for the HSV images
|
||||
@end_toggle
|
||||
|
||||
- Apply sequentially the 4 comparison methods between the histogram of the base image (hist_base)
|
||||
- Apply sequentially the 6 comparison methods between the histogram of the base image (hist_base)
|
||||
and the other histograms:
|
||||
|
||||
@add_toggle_cpp
|
||||
|
|
@ -182,15 +188,17 @@ Results
|
|||
are from the same source. For the other two test images, we can observe that they have very
|
||||
different lighting conditions, so the matching should not be very good:
|
||||
|
||||
-# Here the numeric results we got with OpenCV 3.4.1:
|
||||
*Method* | Base - Base | Base - Half | Base - Test 1 | Base - Test 2
|
||||
----------------- | ------------ | ------------ | -------------- | ---------------
|
||||
*Correlation* | 1.000000 | 0.880438 | 0.20457 | 0.0664547
|
||||
*Chi-square* | 0.000000 | 4.6834 | 2697.98 | 4763.8
|
||||
*Intersection* | 18.8947 | 13.022 | 5.44085 | 2.58173
|
||||
*Bhattacharyya* | 0.000000 | 0.237887 | 0.679826 | 0.874173
|
||||
-# Here the numeric results we got with OpenCV 4.12.0:
|
||||
*Method* | Base - Base | Base - Half | Base - Test 1 | Base - Test 2
|
||||
------------------- | ------------ | ------------ | -------------- | ---------------
|
||||
*Correlation* | 1.000000 | 0.880438 | 0.20457 | 0.065752
|
||||
*Chi-square* | 0.000000 | 0.328307 | 181.674 | 80.1494
|
||||
*Intersection* | 1.000000 | 0.75005 | 0.315061 | 0.0908022
|
||||
*Bhattacharyya* | 0.000000 | 0.237866 | 0.679825 | 0.873709
|
||||
*Chi-Square alt.* | 0.000000 | 0.395046 | 2.31572 | 3.41024
|
||||
*KL divergence* | 0.000000 | 0.321064 | 2.6616 | 9.55412
|
||||
|
||||
For the *Correlation* and *Intersection* methods, the higher the metric, the more accurate the
|
||||
match. As we can see, the match *base-base* is the highest of all as expected. Also we can observe
|
||||
that the match *base-half* is the second best match (as we predicted). For the other two metrics,
|
||||
the less the result, the better the match. We can observe that the matches between the test 1 and
|
||||
test 2 with respect to the base are worse, which again, was expected.
|
||||
that the match *base-half* is the second best match (as we predicted). For the other four metrics,
|
||||
the less the result, the better the match.
|
||||
|
|
|
|||
|
|
@ -66,20 +66,20 @@ int main( int argc, char** argv )
|
|||
Mat hist_base, hist_half_down, hist_test1, hist_test2;
|
||||
|
||||
calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );
|
||||
normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() );
|
||||
normalize( hist_base, hist_base, 1, 0, NORM_L1, -1, Mat() );
|
||||
|
||||
calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false );
|
||||
normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() );
|
||||
normalize( hist_half_down, hist_half_down, 1, 0, NORM_L1, -1, Mat() );
|
||||
|
||||
calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );
|
||||
normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );
|
||||
normalize( hist_test1, hist_test1, 1, 0, NORM_L1, -1, Mat() );
|
||||
|
||||
calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false );
|
||||
normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
|
||||
normalize( hist_test2, hist_test2, 1, 0, NORM_L1, -1, Mat() );
|
||||
//! [Calculate the histograms for the HSV images]
|
||||
|
||||
//! [Apply the histogram comparison methods]
|
||||
for( int compare_method = 0; compare_method < 4; compare_method++ )
|
||||
for( int compare_method = 0; compare_method < 6; compare_method++ )
|
||||
{
|
||||
double base_base = compareHist( hist_base, hist_base, compare_method );
|
||||
double base_half = compareHist( hist_base, hist_half_down, compare_method );
|
||||
|
|
|
|||
|
|
@ -52,23 +52,23 @@ class CompareHist {
|
|||
|
||||
List<Mat> hsvBaseList = Arrays.asList(hsvBase);
|
||||
Imgproc.calcHist(hsvBaseList, new MatOfInt(channels), new Mat(), histBase, new MatOfInt(histSize), new MatOfFloat(ranges), false);
|
||||
Core.normalize(histBase, histBase, 0, 1, Core.NORM_MINMAX);
|
||||
Core.normalize(histBase, histBase, 1, 0, Core.NORM_L1);
|
||||
|
||||
List<Mat> hsvHalfDownList = Arrays.asList(hsvHalfDown);
|
||||
Imgproc.calcHist(hsvHalfDownList, new MatOfInt(channels), new Mat(), histHalfDown, new MatOfInt(histSize), new MatOfFloat(ranges), false);
|
||||
Core.normalize(histHalfDown, histHalfDown, 0, 1, Core.NORM_MINMAX);
|
||||
Core.normalize(histHalfDown, histHalfDown, 1, 0, Core.NORM_L1);
|
||||
|
||||
List<Mat> hsvTest1List = Arrays.asList(hsvTest1);
|
||||
Imgproc.calcHist(hsvTest1List, new MatOfInt(channels), new Mat(), histTest1, new MatOfInt(histSize), new MatOfFloat(ranges), false);
|
||||
Core.normalize(histTest1, histTest1, 0, 1, Core.NORM_MINMAX);
|
||||
Core.normalize(histTest1, histTest1, 1, 0, Core.NORM_L1);
|
||||
|
||||
List<Mat> hsvTest2List = Arrays.asList(hsvTest2);
|
||||
Imgproc.calcHist(hsvTest2List, new MatOfInt(channels), new Mat(), histTest2, new MatOfInt(histSize), new MatOfFloat(ranges), false);
|
||||
Core.normalize(histTest2, histTest2, 0, 1, Core.NORM_MINMAX);
|
||||
Core.normalize(histTest2, histTest2, 1, 0, Core.NORM_L1);
|
||||
//! [Calculate the histograms for the HSV images]
|
||||
|
||||
//! [Apply the histogram comparison methods]
|
||||
for( int compareMethod = 0; compareMethod < 4; compareMethod++ ) {
|
||||
for( int compareMethod = 0; compareMethod < 6; compareMethod++ ) {
|
||||
double baseBase = Imgproc.compareHist( histBase, histBase, compareMethod );
|
||||
double baseHalf = Imgproc.compareHist( histBase, histHalfDown, compareMethod );
|
||||
double baseTest1 = Imgproc.compareHist( histBase, histTest1, compareMethod );
|
||||
|
|
|
|||
|
|
@ -45,20 +45,20 @@ channels = [0, 1]
|
|||
|
||||
## [Calculate the histograms for the HSV images]
|
||||
hist_base = cv.calcHist([hsv_base], channels, None, histSize, ranges, accumulate=False)
|
||||
cv.normalize(hist_base, hist_base, alpha=0, beta=1, norm_type=cv.NORM_MINMAX)
|
||||
cv.normalize(hist_base, hist_base, alpha=1, beta=0, norm_type=cv.NORM_L1)
|
||||
|
||||
hist_half_down = cv.calcHist([hsv_half_down], channels, None, histSize, ranges, accumulate=False)
|
||||
cv.normalize(hist_half_down, hist_half_down, alpha=0, beta=1, norm_type=cv.NORM_MINMAX)
|
||||
cv.normalize(hist_half_down, hist_half_down, alpha=1, beta=0, norm_type=cv.NORM_L1)
|
||||
|
||||
hist_test1 = cv.calcHist([hsv_test1], channels, None, histSize, ranges, accumulate=False)
|
||||
cv.normalize(hist_test1, hist_test1, alpha=0, beta=1, norm_type=cv.NORM_MINMAX)
|
||||
cv.normalize(hist_test1, hist_test1, alpha=1, beta=0, norm_type=cv.NORM_L1)
|
||||
|
||||
hist_test2 = cv.calcHist([hsv_test2], channels, None, histSize, ranges, accumulate=False)
|
||||
cv.normalize(hist_test2, hist_test2, alpha=0, beta=1, norm_type=cv.NORM_MINMAX)
|
||||
cv.normalize(hist_test2, hist_test2, alpha=1, beta=0, norm_type=cv.NORM_L1)
|
||||
## [Calculate the histograms for the HSV images]
|
||||
|
||||
## [Apply the histogram comparison methods]
|
||||
for compare_method in range(4):
|
||||
for compare_method in range(6):
|
||||
base_base = cv.compareHist(hist_base, hist_base, compare_method)
|
||||
base_half = cv.compareHist(hist_base, hist_half_down, compare_method)
|
||||
base_test1 = cv.compareHist(hist_base, hist_test1, compare_method)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user