直方圖均衡化 原理及其C++程式碼實現
阿新 • • 發佈:2019-01-07
演算法原理
直方圖均衡化,是對影象進行非線性拉伸,使得一定範圍內畫素值的數量的大致相同。這樣原來直方圖中的封頂部分對比度得到了增強,而兩側波谷的對比度降低,輸出的直方圖是一個較為平坦的分段直方圖。具體來講可以表現為下面這個圖:
通過這種方法可以按照需要對影象的亮度進行調整,並且,這種方法是可逆的,也就是說知道了均衡化函式,就可以恢復原始的直方圖。接下來對原理進行說明:設變數
代表影象中畫素灰度級。對灰度級進行歸一化處理,即
,其中
表示黑,
表示白。對於一幅給定的圖片來說,每個畫素在
的灰度級是隨機的,用概率密度
來表示影象灰度級的分佈。為了有利於數字影象處理,引入離散形式。在離散形式下,用
代表離散灰度級,用
代表
,並且下式子成立:
,其中
。式子中
代表影象中出現
這種灰度的畫素個數,
是影象的總畫素個數,影象進行直方圖均衡化的函式表示式為:
,式子中,k為灰度級數。相應的反變換為
程式碼實現
//直方圖均衡化
Mat Histogramequalization(Mat src) {
int R[256] = {0};
int G[256] = {0};
int B[256] = {0};
int rows = src.rows;
int cols = src.cols;
int sum = rows * cols;
//統計直方圖的RGB分佈
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
B[src.at<Vec3b>(i, j)[0]]++;
G[src.at<Vec3b>(i, j)[1]]++;
R[src.at<Vec3b>(i, j)[2]]++;
}
}
//構建直方圖的累計分佈方程,用於直方圖均衡化
double val[3] = {0};
for (int i = 0; i < 256; i++) {
val[0] += B[i];
val[1] += G[i];
val[2] += R[i];
B[i] = val[0] * 255 / sum;
G[i] = val[1] * 255 / sum;
R[i] = val[2] * 255 / sum;
}
//歸一化直方圖
Mat dst(rows, cols, CV_8UC3);
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
dst.at<Vec3b>(i, j)[0] = B[src.at<Vec3b>(i, j)[0]];
dst.at<Vec3b>(i, j)[1] = B[src.at<Vec3b>(i, j)[1]];
dst.at<Vec3b>(i, j)[2] = B[src.at<Vec3b>(i, j)[2]];
}
}
return dst;
}
效果
原圖
直方圖均衡化後的圖