直方图统计和显示

直方图

一、原理和目的

(1)目的:将单通道图像的灰度值与对应的频率数据可视化,便于分析图像

(2)原理:创建一个大小为256的数组,表示0~255的灰度范围,然后对图像进行遍历,每次读取到一个灰度值就在数组对应的值进行自增操作。最终数组的下标代表的是灰度,下标对应的值代表的是灰度频率,然后根据数据的数据描线,最终描成直方图。

灰度

0

1

...

255

频率

x

y

...

z

公式:

①   W=k*256  W图像的宽度

 

②   {

         Pmin = min hist[i]     Pmin,灰度频率的最小值

         Pmax=max hist[i]     Pmax,灰度频率的最大值

   }

 

③   S=W/Pmax         S,y方向的缩放比例

④   H=W+△             H,图像的高度

 

⑤   {

         ∀i,hist[i]

         P1=(i*k+1,H-1-S.Hist[i])

         P2=(i*k+1,H-1)

参数:k,△,k表示线宽,△表示高度方向上最高直方图的余量;

 

二、步骤

(1)使用公式1计算图像宽W

(2)使用公式2、3、4计算图像高H

(3)遍历数组,对每一个i,

                   可用公式5计算P1,P2

                   调用line()

          直到图像遍历完毕

(4)显示直方图

 

三、伪代码

输入:{H(i)|i=0,1,...,255}

△:表示高度方向上最高直方图的余量,防止图像显示不完整,在代码中为dt表示

K:表示线宽

arr[]表示存放灰度频率的数组,下标值与灰度频率一一对应

输出:直方图图像

 

void showHisto(long arr[],int k,int dt)

{

         求arr中的最大值,等比例显示

 

         遍历arr数组,根据数组值,调用line描线

 

         显示直方图

}

 

四、源码

void traverse(cv::Mat src,long arr[])	//统计灰度级以及其频率,下标为灰度级,数组值为频率
{
	long grayData[256] = { 0 };

	for (int i = 0; i < src.rows; i++)
	{

		uchar* src_rows_ptr = src.ptr<uchar>(i);
		for (int j = 0; j < src.cols; j++)
		{
			grayData[src_rows_ptr[j]]++;
		}
	}
	for (int i = 0; i < 255; i++) {
		arr[i] = grayData[i];
	}
}

 

ong getMax(long arr[])	//求最大灰度频率
{
	long max = 0;
	for (int i = 0; i < 256; i++)
	{
		if (max < arr[i]) {
			max = arr[i];
		}
	}
	return max;
}

  

void showHisto(long arr[],int k,int dt)  //显示直方图
{

    long Pmax = getMax(arr);    //getMax只是求arr数组的最大值,可以自己写一下

 

    Mat mat(k * 256+20, k * 256 , 0);

    for (int i = 0; i < 256; i++) {

        line(mat, Point(i*k + 1, k * 256+ dt), Point(i*k + 1, 256.0 * k+ dt  -  arr[i] * (3*256.0/ Pmax)), Scalar(0, 0, 0), 3);  //等比例显示

    }

    imshow("histo", mat);

}

  

 

 

五、结果图

显示的结果图像和将数据导出到Excel所显示的图像一致,如果要将直方图缩小或者放大可以用cv::resize;

 

posted @ 2021-05-07 09:18  will-z  阅读(1029)  评论(0编辑  收藏  举报