0%

直方图均衡化

​ 直方图均衡化是通过对原图像在像素个数多的灰度级进行展宽,对像素个数少的灰度级进行缩减,使原图像的灰度直方图修正为均匀分布的直方图。

步骤

由原图像得灰度直方图

​ 计每一个像素值的点的个数。

例如:原图像

1 3 9 9 8
2 1 3 7 3
3 6 0 6 4
6 8 2 0 5
2 9 2 6 0

灰度直方图

灰度级 像素点个数H
0 3
1 2
2 4
3 4
4 1
5 1
6 4
7 1
8 2
9 3

由灰度直方图得灰度级像素百分比

​ 灰度直方图中的像素点个数 / 总像素点个数

灰度级 灰度级像素百分比HR
0 0.12
1 0.08
2 0.16
3 0.16
4 0.04
5 0.04
6 0.16
7 0.04
8 0.08
9 0.12

计算各灰度级的累积分布

灰度级 累积分布HS
0 0.12
1 0.20
2 0.36
3 0.52
4 0.56
5 0.60
6 0.76
7 0.80
8 0.88
9 1.00

求出新图像的灰度值

image-20200116210709241

​ 即乘以灰度级个数后再四舍五入。

C++实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

//直方图均衡化
void histogram_equalization(Mat &img, Mat &result) {
int H[256] = {0};
for (int i = 0; i <= 255; i++) {
H[i] = 0; // 灰度直方图
}
// 由原图像得灰度直方图
for (int nrow = 0; nrow < img.rows; nrow++) {
for (int ncol = 0; ncol < img.cols; ncol++) {
int h = img.ptr<uchar>(nrow)[ncol];
H[h] ++;
}
}
// 由灰度直方图得灰度级像素百分比
int NR = img.rows * img.cols; // 总像素点个数
double HR[256] = {0};
for (int i = 0; i <= 255; i++) {
HR[i] = 0.0; // 灰度直方图
}
for (int i = 0; i <= 255; i++) {
HR[i] = double(H[i])/double(NR); // 灰度级像素百分比
}
// 计算各灰度级的累积分布,并求出新图像的灰度值
double HS[256] = {0};
for (int i = 0; i <= 255; i++) {
HS[i] = 0.0; // 各灰度级的累积分布
}
for (int i = 1; i <= 255; i++) {
for (int j = 0; j <= i; j++) {
HS[i] += HR[j];
}
H[i] = round(HS[i] * 255);
}
// 获得新图像
for (int nrow = 0; nrow < img.rows; nrow++) {
for (int ncol = 0; ncol < img.cols; ncol++) {
int h = img.ptr<uchar>(nrow)[ncol];
result.ptr<uchar>(nrow)[ncol] = H[h];
}
}
}

int main() {
Mat img = imread("Unequalized.jpg", IMREAD_GRAYSCALE);
Mat result = img.clone();
histogram_equalization(img, result);
imshow("img",img);
imshow("Histogram Equalization",result);
imwrite("result.jpg", result);
waitKey();

return 0;
}

原图像:

经直方图均衡化后的图像: