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