OPENCV——直方图计算calcHist

图像的灰度直方图是一个离散函数,它表示图像每一灰度级与该灰度级出现频率的对应关系。可以应用于各种需要统计的数据中,使用简单、方便。但该运算是一个不可逆的过程。

函数原型如下:

//! computes the joint dense histogram for a set of images.
CV_EXPORTS 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 );

//! computes the joint sparse histogram for a set of images.
CV_EXPORTS void calcHist( const Mat* images, int nimages,
                          const int* channels, InputArray mask,
                          SparseMat& hist, int dims,
                          const int* histSize, const float** ranges,
                          bool uniform=true, bool accumulate=false );

CV_EXPORTS_W void calcHist( InputArrayOfArrays images,
                            const vector<int>& channels,
                            InputArray mask, OutputArray hist,
                            const vector<int>& histSize,
                            const vector<float>& ranges,
                            bool accumulate=false );

       参数:

        nimages——输入的图像的个数。

        channels——指明通道数。int channels[] = {0, 1};通道0和通道1。

        mask——掩码。如果mask不为空,那么它必须是一个8位(CV_8U)的数组,为0的像素点不统计。

        hist——保存直方图的矩阵

        dims——直方图的维数。

        histSize——每维bin的个数。

        ranges——用来进行统计的范围。    float rang1[] = {0, 256}; float rang2[] = {0, 256};

 const float *rangs[] = {rang1, rang2};那么就是对0,256和0,256范围的值进行统计,2D直方图)。

       uniform——如果为true,采用均匀直方图。

       accumulate——直方图建立时清除内存痕迹标志,默认为0,即清除。

下面是1D和2D直方图计算CODE:
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main()
{
	//生成一幅单通道图像。
	cv::Mat src = cv::imread("lena.png");
	if( !src.data )
	{ return -1; }

<pre name="code" class="cpp" style="color: rgb(0, 128, 0); font-size: 14px; line-height: 21px;">#pragma region single
/// 分割成3个单通道图像 ( R, G 和 B )vector<Mat> rgb_planes;split( src, rgb_planes );
	/// 设定bin数目
	int histSize = 255;

	/// 设定取值范围 ( R,G,B) )
	float range[] = { 0, 255 } ;
	const float* histRange = { range };
	bool uniform = true; bool accumulate = false;

	Mat r_hist, g_hist, b_hist;

	/// 计算直方图:
	calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
	calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
	calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );

	// 创建直方图画布
	int hist_w = 400; int hist_h = 400;
	int bin_w = cvRound( (double) hist_w/histSize );

	Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );

	/// 将直方图归一化到范围 [ 0, histImage.rows ]
	normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
	normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
	normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

	// 在直方图画布上画出直方图
	for( int i = 1; i < histSize; i++ )
	{
		line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
			Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
			Scalar( 0, 0, 255), 2, 8, 0  );
		line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
			Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
			Scalar( 0, 255, 0), 2, 8, 0  );
		line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
			Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
			Scalar( 255, 0, 0), 2, 8, 0  );
	}

	/// 显示直方图
	namedWindow("calcHist sDemo", CV_WINDOW_AUTOSIZE );
	imshow("calcHist sDemo", histImage );
	waitKey(0);
#pragma endregion single

#pragma region multi
	MatND hist; 
	/// 计算直方图:
	int rbins = 255, gbins = 255, bbins = 255;  
	int histSize1[] = {rbins, gbins, bbins}; 

	float rranges[] = { 0, 256};  
	float granges[] = { 0, 256};  
	float branges[] = { 0, 256};

	const float*ranges[] = { rranges, granges, branges }; 
	 int channels[] = {0, 1, 2}; 
	calcHist( &src, 1,channels , Mat(), hist, 2, histSize1, ranges, true, false );
	double maxVal=0;  
	minMaxLoc(hist, 0, &maxVal, 0, 0);  
	int scale = 2;  
	Mat histImg = Mat::zeros(gbins*scale, rbins*scale, CV_8UC3); 

	int n = hist.channels();

	for( int h = 0; h < rbins; h++ )  
	{  
		for( int s = 0; s < gbins; s++ )  
		{  
			float binVal = hist.at<float>(h, s);  
			int intensity = cvRound(binVal*255/maxVal);  
			rectangle( histImg, Point(h*scale, s*scale),Point((h+1)*scale-1, (s+1)*scale-1), Scalar::all(intensity), CV_FILLED);  
		}  
	} 
	/// 显示直方图 
	namedWindow("<span style="font-family: 'Courier New'; white-space: pre-wrap;">calcHist MDemo</span><span style="font-family: 'Courier New'; white-space: pre-wrap;">"</span><span style="line-height: 1.5; font-family: 'Courier New'; white-space: pre-wrap;">, 1 );  </span><span style="font-family: 'Courier New'; white-space: pre-wrap;">
</span>	imshow( "<span style="font-family: 'Courier New'; white-space: pre-wrap;">calcHist MDemo</span><span style="line-height: 1.5; font-family: 'Courier New'; white-space: pre-wrap;">", histImg );  </span>
	waitKey(0);
#pragma endregion multi
	return 0;
}


 
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值