图像相似度--直方图方法

清疚 2022-06-13 05:37 357阅读 0赞

目标

本文档尝试解答如下问题:

  • 如何使用OpenCV函数 compareHist 产生一个表达两个直方图的相似度的数值。
  • 如何使用不同的对比标准来对直方图进行比较。

原理

  • 要比较两个直方图( H\_\{1\} and H\_\{2\} ), 首先必须要选择一个衡量直方图相似度的 对比标准 (d(H\_\{1\}, H\_\{2\})) 。
  • OpenCV 函数 compareHist 执行了具体的直方图对比的任务。该函数提供了4种对比标准来计算相似度:

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

      其中

      \\bar\{H\_k\} =  \\frac\{1\}\{N\} \\sum \_J H\_k(J)

      N 是直方图中bin的数目。

    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)+H\_2(I)\}

    3. Intersection ( CV_COMP_INTERSECT )

      d(H\_1,H\_2) =  \\sum \_I  \\min (H\_1(I), H\_2(I))

    4. Bhattacharyya 距离( 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)\}\}

源码

  • 本程序做什么?

    • 装载一张 基准图像 和 两张 测试图像 进行对比。
    • 产生一张取自 基准图像 下半部的图像。
    • 将图像转换到HSV格式。
    • 计算所有图像的H-S直方图,并归一化以便对比。
    • 基准图像 直方图与 两张测试图像直方图,基准图像半身像直方图,以及基准图像本身的直方图分别作对比。
    • 显示计算所得的直方图相似度数值。
  • 下载代码: 点击 这里
  • 代码一瞥:

    include “opencv2/highgui/highgui.hpp”

    include “opencv2/imgproc/imgproc.hpp”

    include

    include

    using namespace std;
    using namespace cv;

    / @函数 main */
    int main( int argc, char
    argv )
    {

    Mat src_base, hsv_base;
    Mat src_test1, hsv_test1;
    Mat src_test2, hsv_test2;
    Mat hsv_half_down;

    /// 装载三张背景环境不同的图像
    if( argc < 4 )

    1. {
    2. printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n");
    3. return -1;
    4. }

    src_base = imread( argv[1], 1 );
    src_test1 = imread( argv[2], 1 );
    src_test2 = imread( argv[3], 1 );

    /// 转换到 HSV
    cvtColor( src_base, hsv_base, CV_BGR2HSV );
    cvtColor( src_test1, hsv_test1, CV_BGR2HSV );
    cvtColor( src_test2, hsv_test2, CV_BGR2HSV );

    hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) );

    /// 对hue通道使用30个bin,对saturatoin通道使用32个bin
    int h_bins = 50; int s_bins = 60;
    int histSize[] = {

    1. h_bins, s_bins };

    // hue的取值范围从0到256, saturation取值范围从0到180
    float h_ranges[] = {

    1. 0, 256 };

    float s_ranges[] = {

    1. 0, 180 };

    const float* ranges[] = {

    1. h_ranges, s_ranges };

    // 使用第0和第1通道
    int channels[] = {

    1. 0, 1 };

    /// 直方图
    MatND hist_base;
    MatND hist_half_down;
    MatND hist_test1;
    MatND hist_test2;

    /// 计算HSV图像的直方图
    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() );

    ///应用不同的直方图对比方法
    for( int i = 0; i < 4; i++ )

    1. {
    2. int compare_method = i;
    3. double base_base = compareHist( hist_base, hist_base, compare_method );
    4. double base_half = compareHist( hist_base, hist_half_down, compare_method );
    5. double base_test1 = compareHist( hist_base, hist_test1, compare_method );
    6. double base_test2 = compareHist( hist_base, hist_test2, compare_method );
    7. 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 );
    8. }

    printf( “Done \n” );

    return 0;
    }

解释

  1. 声明储存基准图像和另外两张对比图像的矩阵( RGB 和 HSV )

    1. Mat src_base, hsv_base;
    2. Mat src_test1, hsv_test1;
    3. Mat src_test2, hsv_test2;
    4. Mat hsv_half_down;
  2. 装载基准图像(src_base) 和两张测试图像:

    1. if( argc < 4 )
    2. {
    3. printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n");
    4. return -1;
    5. }
    6. src_base = imread( argv[1], 1 );
    7. src_test1 = imread( argv[2], 1 );
    8. src_test2 = imread( argv[3], 1 );
  3. 将图像转化到HSV格式:

    1. cvtColor( src_base, hsv_base, CV_BGR2HSV );
    2. cvtColor( src_test1, hsv_test1, CV_BGR2HSV );
    3. cvtColor( src_test2, hsv_test2, CV_BGR2HSV );
  4. 同时创建包含基准图像下半部的半身图像(HSV格式):

    1. hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) );
  5. 初始化计算直方图需要的实参(bins, 范围,通道 H 和 S ).

    1. int h_bins = 50; int s_bins = 32;
    2. int histSize[] = {
    3. h_bins, s_bins };
    4. float h_ranges[] = {
    5. 0, 256 };
    6. float s_ranges[] = {
    7. 0, 180 };
    8. const float* ranges[] = {
    9. h_ranges, s_ranges };
    10. int channels[] = {
    11. 0, 1 };
  6. 创建储存直方图的 MatND 实例:

    1. MatND hist_base;
    2. MatND hist_half_down;
    3. MatND hist_test1;
    4. MatND hist_test2;
  7. 计算基准图像,两张测试图像,半身基准图像的直方图:

    1. calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );
    2. normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() );
    3. calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false );
    4. normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() );
    5. calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );
    6. normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );
    7. calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false );
    8. normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
  8. 按顺序使用4种对比标准将基准图像(hist_base)的直方图与其余各直方图进行对比:

    1. for( int i = 0; i < 4; i++ )
    2. {
    3. int compare_method = i;
    4. double base_base = compareHist( hist_base, hist_base, compare_method );
    5. double base_half = compareHist( hist_base, hist_half_down, compare_method );
    6. double base_test1 = compareHist( hist_base, hist_test1, compare_method );
    7. double base_test2 = compareHist( hist_base, hist_test2, compare_method );
    8. 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 );
    9. }

结果

  1. 使用下列输入图像:









    Base_0

    Test_1

    Test_2

    第一张为基准图像,其余两张为测试图像。同时我们会将基准图像与它自身及其半身图像进行对比。

  2. 我们应该会预料到当将基准图像直方图及其自身进行对比时会产生完美的匹配, 当与来源于同一样的背景环境的半身图对比时应该会有比较高的相似度, 当与来自不同亮度光照条件的其余两张测试图像对比时匹配度应该不是很好:
  3. 下面显示的是结果数值:








































对比标准 基准 - 基准 基准 - 半身 基准 - 测试1 基准 - 测试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

对于 CorrelationIntersection 标准, 值越大相似度越大。因此可以看到对于采用这两个方法的对比,*基准 - 基准* 的对比结果值是最大的, 而 基准 - 半身 的匹配则是第二好(跟我们预测的一致)。而另外两种对比标准,则是结果越小相似度越大。 我们可以观察到基准图像直方图与两张测试图像直方图的匹配是最差的,这再一次印证了我们的预测。

转载来自:http://blog.csdn.net/zhuiqiuk/article/details/54945607

学习参考:http://blog.csdn.net/cxf7394373/article/details/6955530

发表评论

表情:
评论列表 (有 0 条评论,357人围观)

还没有评论,来说两句吧...

相关阅读

    相关 图像相似中的Hash算法

    本博客中使用的代码见本文末尾        度量两张图片的相似度有许多算法,本文讲介绍工程领域中最常用的图片相似度算法之一——Hash算法。Hash算法准确的说有三种,分别为

    相关 图像直方图

    灰度直方图的定义 灰度直方图定义为数字图像中各灰度级与其出现的频数之间的统计关系,用公式表示为 P(k)=nkn,k=0,1,...,L−1 且 ∑k=0L−1P