学习OpenCV2 —— 直方图匹配

版权声明:转载请注明出处 https://blog.csdn.net/GDFSG/article/details/50794517

参考

  1. http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.html
  2. 《OpenCV3编程入门》

原理

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

a. 相关 Correlation ( CV_COMP_CORREL )
其中,
N是直方图中bin的数目。 
相关系数是衡量随机变量X与Y相关程度的一种方法,相关系数的取值范围是[-1,1]。相关系数的绝对值越大,则表明X与Y相关度越高。当X与Y线性相关时,相关系数取值为1(正线性相关)或-1(负线性相关)。
b. 卡方 Chi-Square ( CV_COMP_CHISQR ) 
c. 直方图相交 Intersection ( CV_COMP_INTERSECT ) 
d. Bhattacharyya 距离( CV_COMP_BHATTACHARYYA ) 
显然对于巴氏距离,d>0, 如果H1和H2完全相同,则d = 0, d越大,相似度越小

示例代码

本程序做什么?

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

源代码

//---------------------------------【头文件、命名空间包含部分】----------------------------
//		描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;


//--------------------------------------【main( )函数】-----------------------------------------
//          描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main( )
{
	//【0】改变console字体颜色
	system("color 2F"); 

	//【1】声明储存基准图像和另外两张对比图像的矩阵( RGB 和 HSV )
	Mat srcImage_base, hsvImage_base;
	Mat srcImage_test1, hsvImage_test1;
	Mat srcImage_test2, hsvImage_test2;
	Mat hsvImage_halfDown;

	//【2】载入基准图像(srcImage_base) 和两张测试图像srcImage_test1、srcImage_test2,并显示
	srcImage_base = imread( "pic1.jpg",1 );
	srcImage_test1 = imread( "pic2.jpg", 1 );
	srcImage_test2 = imread( "pic3.jpg", 1 );
	//显示载入的3张图像
	imshow("基准图像",srcImage_base);
	imshow("测试图像1",srcImage_test1);
	imshow("测试图像2",srcImage_test2);

	// 【3】将图像由BGR色彩空间转换到 HSV色彩空间
	cvtColor( srcImage_base, hsvImage_base,  COLOR_BGR2HSV );
	cvtColor( srcImage_test1, hsvImage_test1, COLOR_BGR2HSV );
	cvtColor( srcImage_test2, hsvImage_test2, COLOR_BGR2HSV );

	//【4】创建包含基准图像下半部的半身图像(HSV格式)
	hsvImage_halfDown = hsvImage_base( Range( hsvImage_base.rows/2, hsvImage_base.rows - 1 ), Range( 0, hsvImage_base.cols - 1 ) );
	
	//【5】初始化计算直方图需要的实参
	// 对hue通道使用30个bin,对saturatoin通道使用32个bin
	int h_bins = 50; int s_bins = 60;
	int histSize[] = { h_bins, s_bins };
	// hue的取值范围从0到256, saturation取值范围从0到180
	float h_ranges[] = { 0, 256 };
	float s_ranges[] = { 0, 180 };
	const float* ranges[] = { h_ranges, s_ranges };
	// 使用第0和第1通道
	int channels[] = { 0, 1 };

	// 【6】创建储存直方图的 MatND 类的实例:
	MatND baseHist;
	MatND halfDownHist;
	MatND testHist1;
	MatND testHist2;

	// 【7】计算基准图像,两张测试图像,半身基准图像的HSV直方图:
	calcHist( &hsvImage_base, 1, channels, Mat(), baseHist, 2, histSize, ranges, true, false );
	normalize( baseHist, baseHist, 0, 1, NORM_MINMAX, -1, Mat() );

	calcHist( &hsvImage_halfDown, 1, channels, Mat(), halfDownHist, 2, histSize, ranges, true, false );
	normalize( halfDownHist, halfDownHist, 0, 1, NORM_MINMAX, -1, Mat() );

	calcHist( &hsvImage_test1, 1, channels, Mat(), testHist1, 2, histSize, ranges, true, false );
	normalize( testHist1, testHist1, 0, 1, NORM_MINMAX, -1, Mat() );

	calcHist( &hsvImage_test2, 1, channels, Mat(), testHist2, 2, histSize, ranges, true, false );
	normalize( testHist2, testHist2, 0, 1, NORM_MINMAX, -1, Mat() );


	//【8】按顺序使用4种对比标准将基准图像的直方图与其余各直方图进行对比:
	for( int i = 0; i < 4; i++ )
	{ 
		//进行图像直方图的对比
		int compare_method = i;
		double base_base = compareHist( baseHist, baseHist, compare_method );
		double base_half = compareHist( baseHist, halfDownHist, compare_method );
		double base_test1 = compareHist( baseHist, testHist1, compare_method );
		double base_test2 = compareHist( baseHist, testHist2, compare_method );
		//输出结果
		printf( " 方法 [%d] 的匹配结果如下:\n",i);
		printf( " 【基准图 - 基准图】:%f, 【基准图 - 半身图】:%f,【基准图 - 测试图1】: %f, 【基准图 - 测试图2】:%f\n", base_base, base_half , base_test1, base_test2 );
		printf( "-----------------------------------------------------------------\n");
	}

	printf( "检测结束。" );
	waitKey(0);
	return 0;
}


结果

  1. 使用下列输入图像: 
    这里写图片描述 这里写图片描述 这里写图片描述
  2. 我们应该会预料到当将基准图像直方图及其自身进行对比时会产生完美的匹配, 当与来源于同一样的背景环境的半身图对比时应该会有比较高的相似度, 当与来自不同亮度光照条件的其余两张测试图像对比时匹配度应该不是很好:
  3. 下面是结果: 
    这里写图片描述
            对于 Correlation 和 Intersection 标准, 值越大相似度越大。因此可以看到对于采用这两个方法的对比,基准 - 基准 的对比结果值是最大的, 而 基准 - 半身 的匹配则是第二好(跟我们预测的一致)。而另外两种对比标准,则是结果越小相似度越大。 我们可以观察到基准图像直方图与两张测试图像直方图的匹配是最差的,这再一次印证了我们的预测。

猜你喜欢

转载自blog.csdn.net/GDFSG/article/details/50794517