OpenCV  4.2.0
Open Source Computer Vision
Histogram Comparison

Prev Tutorial: Histogram Calculation
Next Tutorial: Back Projection

Goal

In this tutorial you will learn how to:

  • Use the function cv::compareHist to get a numerical parameter that express how well two histograms match with each other.
  • Use different metrics to compare histograms

Theory

  • To compare two histograms ( \(H_{1}\) and \(H_{2}\) ), first we have to choose a metric ( \(d(H_{1}, H_{2})\)) to express how well both histograms match.
  • OpenCV implements the function cv::compareHist to perform a comparison. It also offers 4 different metrics to compute the matching:
    1. Correlation ( CV_COMP_CORREL )

      \[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}}\]

      where

      \[\bar{H_k} = \frac{1}{N} \sum _J H_k(J)\]

      and \(N\) is the total number of histogram bins.
    2. Chi-Square ( CV_COMP_CHISQR )

      \[d(H_1,H_2) = \sum _I \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)}\]

    3. Intersection ( method=CV_COMP_INTERSECT )

      \[d(H_1,H_2) = \sum _I \min (H_1(I), H_2(I))\]

    4. Bhattacharyya distance ( CV_COMP_BHATTACHARYYA )

      \[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)}}\]

Code

  • What does this program do?
    • Loads a base image and 2 test images to be compared with it.
    • Generate 1 image that is the lower half of the base image
    • Convert the images to HSV format
    • Calculate the H-S histogram for all the images and normalize them in order to compare them.
    • Compare the histogram of the base image with respect to the 2 test histograms, the histogram of the lower half base image and with the same base image histogram.
    • Display the numerical matching parameters obtained.

Explanation

  • Load the base image (src_base) and the other two test images:
  • Convert them to HSV format:
  • Also, create an image of half the base image (in HSV format):
  • Initialize the arguments to calculate the histograms (bins, ranges and channels H and S ).
  • Calculate the Histograms for the base image, the 2 test images and the half-down base image:
  • Apply sequentially the 4 comparison methods between the histogram of the base image (hist_base) and the other histograms:

Results

  1. We use as input the following images:

    Base_0
    Test_1
    Test_2

    where the first one is the base (to be compared to the others), the other 2 are the test images. We will also compare the first image with respect to itself and with respect of half the base image.

  2. We should expect a perfect match when we compare the base image histogram with itself. Also, compared with the histogram of half the base image, it should present a high match since both 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:
  3. 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
    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.
cv::Mat::rows
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
Definition: mat.hpp:2086
cv::String
std::string String
Definition: cvstd.hpp:150
cv::NORM_MINMAX
@ NORM_MINMAX
flag
Definition: base.hpp:207
cv::cvtColor
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
Converts an image from one color space to another.
cv::COLOR_BGR2HSV
@ COLOR_BGR2HSV
convert RGB/BGR to HSV (hue saturation value), color conversions
Definition: imgproc.hpp:585
cv::normalize
void normalize(const SparseMat &src, SparseMat &dst, double alpha, int normType)
highgui.hpp
cv::imread
Mat imread(const String &filename, int flags=IMREAD_COLOR)
Loads an image from a file.
cv::Mat::empty
bool empty() const
Returns true if the array has no elements.
cv::Mat::cols
int cols
Definition: mat.hpp:2086
cv::Range
Template class specifying a continuous subsequence (slice) of a sequence.
Definition: types.hpp:589
imgcodecs.hpp
cv::dnn::print
static void print(const MatShape &shape, const String &name="")
Definition: shape_utils.hpp:188
cv::calcHist
void calcHist(InputArrayOfArrays images, const std::vector< int > &channels, InputArray mask, OutputArray hist, const std::vector< int > &histSize, const std::vector< float > &ranges, bool accumulate=false)
cv::compareHist
double compareHist(const SparseMat &H1, const SparseMat &H2, int method)
cv::calcHist
void calcHist(const Mat *images, int nimages, const int *channels, InputArray mask, OutputArray hist, int dims, const int *histSize, const float **ranges, bool uniform=true, bool accumulate=false)
Calculates a histogram of a set of arrays.
cv::Mat
n-dimensional dense array class
Definition: mat.hpp:791
cv::compareHist
double compareHist(InputArray H1, InputArray H2, int method)
Compares two histograms.
cv::CommandLineParser
Designed for command line parsing.
Definition: utility.hpp:796
cv
"black box" representation of the file storage associated with a file on disk.
Definition: affine.hpp:51
imgproc.hpp
cv::normalize
static Vec< _Tp, cn > normalize(const Vec< _Tp, cn > &v)