直方图统计和显示
直方图
一、原理和目的
(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;

 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号