《学习OpenCV》练习7-6

#include "cv.h"
#include "highgui.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;
}

//*****************************************************
//主函数
//*****************************************************
int main()
{
	/*载入图像并检测*/
	IplImage* image = cvLoadImage( "E:\\...\\hand_1.jpg", CV_LOAD_IMAGE_COLOR );  
    assert(image != 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* hist;  
    hist = myHSVHistogram( image, h_bins, s_bins, scale, width, height, "hand_1", "hist_image_1" );

	/*将图像1分割成3幅单通道的BGR图像*/
    IplImage* b_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );
	IplImage* g_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );
	IplImage* r_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );
	cvSplit( image, b_plane, g_plane, r_plane, 0 );	
	IplImage* planes[] = { g_plane, r_plane };
	IplImage* backProject = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );

	/*根据源图像每个像素的坐标(i,j)与在直方图中的值bin(hij,sij),重新组成一幅图像backProject*/
	cvCalcBackProject( planes, backProject, hist );

	/*通过腐蚀运算,输出显示图像*/
    cvErode( backProject, backProject );
	cvNamedWindow( "backProject", CV_WINDOW_NORMAL );
	cvShowImage( "backProject", backProject );

	cvWaitKey(0);
	cvReleaseImage( &image );
	cvReleaseImage( &b_plane );
	cvReleaseImage( &g_plane );
	cvReleaseImage( &r_plane );
	cvReleaseImage( &backProject );
	cvReleaseHist( &hist );
	cvDestroyAllWindows();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值