《学习OpenCV》练习7-3

#include "cv.h"
#include "highgui.h"
#include "stdio.h"

//*****************************************************
//画直方图函数:根据输入图像,显示HSV二维直方图
//src        :指向输入图像的指针
//h_bins     :H分量(hue色调)在直方图里划分的等级
//s_bins     :S分量(saturation饱和度)在直方图里划分的等级
//scale      :直方图每个矩形的宽度
//width      :直方图的宽度
//height     :直方图的高度
//srcname[]  :用于储存载入源图像窗口的名字
//histname[] :用于储存显示直方图图像的窗口的名字
//返回值hist  :指向生成的直方图的指针
//*****************************************************
CvHistogram* myHSVHistogram( IplImage* src, int h_bins, int s_bins, int scale, int width, int height, const char srcname[], const char histname[] )
{
	if (src==NULL || src->nChannels!=3)
	{
		return NULL;
	}

	/*hsv图像初始化*/
	IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 );
	IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 );
	IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 );
	IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 );
	IplImage* planes[] = { h_plane, s_plane };

	/*H分量(hue色调)划分等级,S分量(saturation饱和度)划分等级*/
	int hist_size[] = { h_bins, s_bins };
 
	/*H分量、S分量的变化范围*/
	float h_ranges[] = { 0, 180 }; 
	float s_ranges[] = { 0, 255 };
	float* ranges[] = { h_ranges, s_ranges };
 
	/*输入图像转换到HSV颜色空间,并将h、s、v分别分割到各自的单通道图像上*/
	cvCvtColor( src, hsv, CV_BGR2HSV );
	cvSplit( hsv, h_plane, s_plane, v_plane, 0 );
 
	/*创建直方图,二维, 每个维度上均分*/
	CvHistogram * hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 );

	/*根据H、S两个平面数据统计planes图像的直方图*/
	cvCalcHist( planes, hist, 0, 0 );
 
	/*获取直方图统计的最大值,用于动态显示直方图*/
	float max_value;
	cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 );

	/*设置直方图显示图像的高度、宽度*/										
	IplImage* hist_img = cvCreateImage( cvSize(width,height), 8, 3 );	
	cvZero( hist_img );
 
	/*用来进行HSV到RGB颜色转换的临时单位图像*/
	IplImage* hsv_color = cvCreateImage(cvSize(1,1),8,3);					//单位图像,相当于一个8bit、3通道的像素点
	IplImage* rgb_color = cvCreateImage(cvSize(1,1),8,3);

	/*for循环显示矩形*/
	for (int h=0; h<h_bins; h++)											//循环画色调直方图
	{
		for (int s=0; s<s_bins; s++)										//在每个画色调直方图循环中,循环画饱和度直方图
		{
			int i = h*s_bins+s;												//直方图中某一矩形的序号(从左到右,由大到小,从0开始)
			float bin_val = cvQueryHistValue_2D( hist, h, s );				//获得某一直方图矩形的数值,即统计数值
			int intensity = cvRound( bin_val*height/max_value );			//四舍五入,计算显示在图像中的矩形高度
			cvSet2D( hsv_color, 0, 0, cvScalar( h*180.f/h_bins, s*255.f/s_bins, 255, 0));
			cvCvtColor( hsv_color, rgb_color, CV_HSV2BGR );					//为hsv像素点设置颜色(颜色设置使用了归一化),并转换为rgb格式
			CvScalar color = cvGet2D( rgb_color, 0, 0 );
			cvRectangle(													//画矩形
				hist_img, 
				cvPoint( i*scale, height ),									//起点横坐标为第i个矩形乘以每个矩形宽度,纵坐标为图像高度,即图像底部
				cvPoint( (i+1)*scale, height-intensity ),					//终点横坐标为矩形宽度,纵坐标为图像底减去矩形高度,令矩形显示在底部
				color,										
				CV_FILLED,													//填充矩形
				8, 
				0 );
		}
	}
	/*显示源图像与直方图*/
	cvNamedWindow( srcname, CV_WINDOW_NORMAL );
	cvShowImage( srcname, src );
	cvNamedWindow( histname, CV_WINDOW_AUTOSIZE );
	cvShowImage( histname, hist_img );

	return hist;
}

//**************************************************************************
//生成EMD的signature函数:输入图像生成signature并输出EMD距离
//hist1,hist2          :指向输入比较图像的指针
//h_bins,s_bins        :H(hue色调)、S(saturation饱和度)在直方图里划分的等级
//返回值emd             :输入两幅比较图像的EMD距离
//**************************************************************************
float myEMDsignature( CvHistogram* hist1, CvHistogram* hist2, int h_bins, int s_bins )
{
	/*构建一个(h_bins*s_bins)*3的矩阵头*/
	CvMat* sig1 = NULL;
	CvMat* sig2 = NULL;
	int rows = h_bins*s_bins;
	int cols = 3;
	sig1 = cvCreateMat( rows, cols, CV_32FC1 );
	sig2 = cvCreateMat( rows, cols, CV_32FC1 );

	/*给二维直方图的矩阵赋值,矩阵每一列第一个变量为bin的值,第二第三为为某点坐标(h,s)*/
	for (int h=0; h<h_bins; h++)
	{
		for (int s=0; s<s_bins; s++)
		{
			float bin_val = cvQueryHistValue_2D( hist1, h, s );
			cvSet2D( sig1, h*s_bins+s, 0, cvScalar(bin_val));
			cvSet2D( sig1, h*s_bins+s, 1, cvScalar(h));
			cvSet2D( sig1, h*s_bins+s, 2, cvScalar(s));
			bin_val = cvQueryHistValue_2D( hist2, h, s );
			cvSet2D( sig2, h*s_bins+s, 0, cvScalar(bin_val));
			cvSet2D( sig2, h*s_bins+s, 1, cvScalar(h));
			cvSet2D( sig2, h*s_bins+s, 2, cvScalar(s));
		}
	}
	/*计算EMD距离并返回*/
	float emd = cvCalcEMD2( sig1, sig2, CV_DIST_L2 );
	return emd;
}

//*****************************************************
//主函数
//*****************************************************
int main()
{
	/*载入图像并检测*/
	IplImage* image1 = cvLoadImage( "E:\\...\\hand_1.jpg", CV_LOAD_IMAGE_COLOR );  
    assert(image1 != NULL);  
    IplImage* image2 = cvLoadImage( "E:\\...\\hand_2.jpg", CV_LOAD_IMAGE_COLOR );  
    assert(image2 != NULL);   
    IplImage* image3 = cvLoadImage( "E:\\...\\hand_3.jpg", CV_LOAD_IMAGE_COLOR );  
    assert(image3 != NULL);

	/*显示直方图的变量初始化*/
	int h_bins = 18;								//180平均分成18份
	int s_bins = 8;									//256平均分成8份
	int scale = 8;									//每个矩形宽度为8
	int width = (h_bins*s_bins)*scale;
	int height = 300;

	/*创建直方图,并调用我的直方图画图函数画出直方图*/
	CvHistogram* hist1;  
    CvHistogram* hist2;  
    CvHistogram* hist3;  
    hist1 = myHSVHistogram( image1, h_bins, s_bins, scale, width, height, "hand_1", "hist_image_1" );
    hist2 = myHSVHistogram( image2, h_bins, s_bins, scale, width, height, "hand_2", "hist_image_2" ); 
    hist3 = myHSVHistogram( image3, h_bins, s_bins, scale, width, height, "hand_3", "hist_image_3" );  

	/*对比第一、第二两个直方图,并打印各个比较值*/
	printf( "h_bins=%d, s_bins=%d时图像1与图像2直方图的比较:\n", h_bins, s_bins );
	double cpm1 = cvCompareHist( hist1, hist2, CV_COMP_CORREL );  
    double cpm2 = cvCompareHist( hist1, hist2, CV_COMP_CHISQR );  
    double cpm3 = cvCompareHist( hist1, hist2, CV_COMP_INTERSECT );  
    double cpm4 = cvCompareHist( hist1, hist2, CV_COMP_BHATTACHARYYA );
	float emd = myEMDsignature( hist1, hist2, h_bins, s_bins );
	printf( "相关:%f \n卡方:%f \n相交:%f \n距离:%f \nEMD :%f \n\n", cpm1, cpm2, cpm3, cpm4, emd );

	/*对比第一、第三两个直方图,并打印各个比较值*/
	printf( "h_bins=%d, s_bins=%d时图像1与图像3直方图的比较:\n", h_bins, s_bins );
	cpm1 = cvCompareHist( hist1, hist3, CV_COMP_CORREL );  
    cpm2 = cvCompareHist( hist1, hist3, CV_COMP_CHISQR );  
    cpm3 = cvCompareHist( hist1, hist3, CV_COMP_INTERSECT );  
    cpm4 = cvCompareHist( hist1, hist3, CV_COMP_BHATTACHARYYA );  
	emd = myEMDsignature( hist1, hist3, h_bins, s_bins );
	printf( "相关:%f \n卡方:%f \n相交:%f \n距离:%f \nEMD :%f \n\n", cpm1, cpm2, cpm3, cpm4, emd );

	/*对比第二、第三两个直方图,并打印各个比较值*/
	printf( "h_bins=%d, s_bins=%d时图像2与图像3直方图的比较:\n", h_bins, s_bins );
	cpm1 = cvCompareHist( hist2, hist3, CV_COMP_CORREL );  
    cpm2 = cvCompareHist( hist2, hist3, CV_COMP_CHISQR );  
    cpm3 = cvCompareHist( hist2, hist3, CV_COMP_INTERSECT );  
    cpm4 = cvCompareHist( hist2, hist3, CV_COMP_BHATTACHARYYA ); 
	emd = myEMDsignature( hist2, hist3, h_bins, s_bins );
	printf( "相关:%f \n卡方:%f \n相交:%f \n距离:%f \nEMD :%f \n\n", cpm1, cpm2, cpm3, cpm4, emd );

	/*释放内存,销毁图像*/
	cvWaitKey(0);
	cvReleaseImage( &image1 );
	cvReleaseImage( &image2 );
	cvReleaseImage( &image3 );
	cvReleaseHist( &hist1 );
	cvReleaseHist( &hist2 );
	cvReleaseHist( &hist3 );
	cvDestroyAllWindows();

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值