相關說明及公式可以參考:
https://zh.wikipedia.org/zh-tw/直方图均衡化
https://face2ai.com/DIP-5-10-灰度图像-图像增强-直方图均衡化HistogramEqualization/
均衡化部分,說白了就是套公式即可完成。
這邊還是說明一下程式步驟,方便了解公式內容。
程式步驟:
- 載入圖檔並轉成灰階
- 讀取圖檔數值後,儲存數值次數 (例如 255 這個值出現幾次)
- 依序累加所有數值 (例如 :1 = 0+1, 2= 0+1+2 … )
- 計算均衡化並寫入圖片值
灰階圖檔均衡化代碼:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
Mat img, grayImage;
void Histogran_Equalization(void);
int main(void)
{
img = imread("C:\\Users\\User\\Downloads\\Image2\\test.jpg", CV_LOAD_IMAGE_COLOR); //open and read the image
cvtColor(img, grayImage, CV_RGB2GRAY);
Histogran_Equalization();
imshow("原圖", img);
imshow("Equalization", grayImage);
waitKey(0); //wait for key press
return 0;
}
void Histogran_Equalization(void)
{
unsigned long long MN = grayImage.rows * grayImage.cols;
unsigned long HE_Table[256];
unsigned long cdf_Table[256];
unsigned long Sk[256];
for (int i = 0; i < 256; i++)
{
HE_Table[i] = 0;
Sk[i] = 0;
cdf_Table[i] = 0;
}
//save gray value
for (int x = 0; x < grayImage.rows; x++)
for (int y = 0; y < grayImage.cols; y++)
for (int i = 0; i < 256; i++)
if (grayImage.ptr<uchar>(x)[y] == i)
HE_Table[i]++;
//count value(cdf)
for (int i = 1; i <256; i++)
for (int j = 0; j <= i;j++)
if (HE_Table[i] != 0)
cdf_Table[i] += HE_Table[j];
//calculate equalization
for (int i = 0; i < 256; i++)
if (HE_Table[i] != 0)
Sk[i] = (double)((cdf_Table[i] - 1) / (double)MN) * i;
//write equalization to image
for (int x = 0; x < grayImage.rows; x++)
for (int y = 0; y < grayImage.cols; y++)
for (int i = 0; i < 256; i++)
if (grayImage.ptr<uchar>(x)[y] == i)
grayImage.ptr<uchar>(x)[y] = Sk[i];
}
下面是彩色圖檔均衡化代碼:
/*RGB*/
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
Mat img, grayImage, RGB;
void Histogran_Equalization(void);
int main(void)
{
img = imread("C:\\Users\\User\\Downloads\\Image2\\3.Left.bmp", CV_LOAD_IMAGE_COLOR); //open and read the image
cvtColor(img, grayImage, CV_BGR2YCrCb); //change the color image from BGR to YCrCb format
Histogran_Equalization();
cvtColor(grayImage, RGB, CV_YCrCb2BGR); //change the color image from YCrCb to BGR format (to display image properly)
imshow("原圖", img);
imshow("Equalization", RGB);
waitKey(0); //wait for key press
return 0;
}
void Histogran_Equalization(void)
{
unsigned long long MN = grayImage.rows * grayImage.cols;
unsigned long HE_Table[256];
unsigned long cdf_Table[256];
unsigned long Sk[256];
for (int i = 0; i < 256; i++)
{
HE_Table[i] = 0;
Sk[i] = 0;
cdf_Table[i] = 0;
}
//save gray value
for (int x = 0; x < grayImage.rows; x++)
for (int y = 0; y < grayImage.cols; y++)
for (int i = 0; i < 256; i++)
if (grayImage.at<Vec3b>(x, y)[0] == i)
HE_Table[i]++;
//count value(cdf)
for (int i = 1; i <256; i++)
for (int j = 0; j <= i; j++)
if (HE_Table[i] != 0)
cdf_Table[i] += HE_Table[j];
//calculate equalization
for (int i = 0; i < 256; i++)
if (HE_Table[i] != 0)
Sk[i] = (double)((cdf_Table[i] - 1) / (double)MN) * i;
//write equalization to image
for (int x = 0; x < grayImage.rows; x++)
for (int y = 0; y < grayImage.cols; y++)
for (int i = 0; i < 256; i++)
if (grayImage.at<Vec3b>(x, y)[0] == i)
grayImage.at<Vec3b>(x, y)[0] = Sk[i];
}