OpenCV  3.0.0-rc1
Open Source Computer Vision
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Histogram Comparison

Goal

In this tutorial you will learn how to:

Theory

Code

1 
7 #include "opencv2/imgcodecs.hpp"
10 #include <iostream>
11 #include <stdio.h>
12 
13 using namespace std;
14 using namespace cv;
15 
19 int main( int argc, char** argv )
20 {
21  Mat src_base, hsv_base;
22  Mat src_test1, hsv_test1;
23  Mat src_test2, hsv_test2;
24  Mat hsv_half_down;
25 
27  if( argc < 4 )
28  {
29  printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n");
30  return -1;
31  }
32 
33  src_base = imread( argv[1], 1 );
34  src_test1 = imread( argv[2], 1 );
35  src_test2 = imread( argv[3], 1 );
36 
38  cvtColor( src_base, hsv_base, COLOR_BGR2HSV );
39  cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV );
40  cvtColor( src_test2, hsv_test2, COLOR_BGR2HSV );
41 
42  hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) );
43 
45  int h_bins = 50; int s_bins = 60;
46  int histSize[] = { h_bins, s_bins };
47 
48  // hue varies from 0 to 179, saturation from 0 to 255
49  float h_ranges[] = { 0, 180 };
50  float s_ranges[] = { 0, 256 };
51 
52  const float* ranges[] = { h_ranges, s_ranges };
53 
54  // Use the o-th and 1-st channels
55  int channels[] = { 0, 1 };
56 
57 
59  MatND hist_base;
60  MatND hist_half_down;
61  MatND hist_test1;
62  MatND hist_test2;
63 
65  calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );
66  normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() );
67 
68  calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false );
69  normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() );
70 
71  calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );
72  normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );
73 
74  calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false );
75  normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
76 
78  for( int i = 0; i < 4; i++ )
79  {
80  int compare_method = i;
81  double base_base = compareHist( hist_base, hist_base, compare_method );
82  double base_half = compareHist( hist_base, hist_half_down, compare_method );
83  double base_test1 = compareHist( hist_base, hist_test1, compare_method );
84  double base_test2 = compareHist( hist_base, hist_test2, compare_method );
85 
86  printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 );
87  }
88 
89  printf( "Done \n" );
90 
91  return 0;
92 }
convert RGB/BGR to HSV (hue saturation value), color conversions
Definition: imgproc.hpp:554
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
Converts an image from one color space to another.
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions ...
Definition: mat.hpp:1865
Mat imread(const String &filename, int flags=IMREAD_COLOR)
Loads an image from a file.
double compareHist(InputArray H1, InputArray H2, int method)
Compares two histograms.
int cols
Definition: mat.hpp:1865
static Vec< _Tp, cn > normalize(const Vec< _Tp, cn > &v)
for i
Definition: modelConvert.m:63
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.
Template class specifying a continuous subsequence (slice) of a sequence.
Definition: types.hpp:531
flag
Definition: base.hpp:176
int main(int argc, const char *argv[])
Definition: facerec_demo.cpp:67
n-dimensional dense array class
Definition: mat.hpp:726

Explanation

  1. Declare variables such as the matrices to store the base image and the two other images to compare ( RGB and HSV )
    Mat src_base, hsv_base;
    Mat src_test1, hsv_test1;
    Mat src_test2, hsv_test2;
    Mat hsv_half_down;
  2. Load the base image (src_base) and the other two test images:
    if( argc < 4 )
    { printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n");
    return -1;
    }
    src_base = imread( argv[1], 1 );
    src_test1 = imread( argv[2], 1 );
    src_test2 = imread( argv[3], 1 );
  3. Convert them to HSV format:
    cvtColor( src_base, hsv_base, COLOR_BGR2HSV );
    cvtColor( src_test1, hsv_test1, COLOR_BGR2HSV );
    cvtColor( src_test2, hsv_test2, COLOR_BGR2HSV );
  4. Also, create an image of half the base image (in HSV format):
    hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) );
  5. Initialize the arguments to calculate the histograms (bins, ranges and channels H and S ).
    int h_bins = 50; int s_bins = 60;
    int histSize[] = { h_bins, s_bins };
    float h_ranges[] = { 0, 180 };
    float s_ranges[] = { 0, 256 };
    const float* ranges[] = { h_ranges, s_ranges };
    int channels[] = { 0, 1 };
  6. Create the MatND objects to store the histograms:
    MatND hist_base;
    MatND hist_half_down;
    MatND hist_test1;
    MatND hist_test2;
  7. Calculate the Histograms for the base image, the 2 test images and the half-down base image:
    calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );
    normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -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() );
    calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );
    normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -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() );
  8. Apply sequentially the 4 comparison methods between the histogram of the base image (hist_base) and the other histograms:
    for( int i = 0; i < 4; i++ )
    { int compare_method = i;
    double base_base = compareHist( hist_base, hist_base, compare_method );
    double base_half = compareHist( hist_base, hist_half_down, compare_method );
    double base_test1 = compareHist( hist_base, hist_test1, compare_method );
    double base_test2 = compareHist( hist_base, hist_test2, compare_method );
    printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 );
    }

Results

  1. We use as input the following images:
    Histogram_Comparison_Source_0.jpg
    Base_0
    Histogram_Comparison_Source_1.jpg
    Test_1
    Histogram_Comparison_Source_2.jpg
    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:
    *Method* Base - Base Base - Half Base - Test 1 Base - Test 2
    *Correlation* 1.000000 0.930766 0.182073 0.120447
    *Chi-square* 0.000000 4.940466 21.184536 49.273437
    *Intersection* 24.391548 14.959809 3.889029 5.775088
    *Bhattacharyya* 0.000000 0.222609 0.646576 0.801869
    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.