直方圖
一、原理和目的
(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;

