【C++】【图像处理】直方图均衡算法解析(以.raw格式的图像为基础进行图像处理、gray levels:256)
1 void hisEqualiz(BYTE* image, int w, int h, BYTE* outImg) 2 { 3 //直方图均衡 4 int his[256];// 声明一个长度为256的数组,用于存储每个灰度级出现的频率 5 int n, i, j; 6 7 // 初始化直方图数组 8 for (n = 0;n < 256;n++) 9 his[n] = 0; 10 11 // 统计原始图像的灰度直方图 12 for (i = 0;i < h;i++) 13 for (j = 0;j < w; j++) 14 his[image[i * w + j]]++; // 统计每个灰度级出现的频率 15 16 /* 上述代码是生成灰度直方图 */ 17 18 19 /* 20 计算累积直方图——至关重要的步骤,这一步将his表示灰度级频率转换成了 <= 当前灰度级的所有像素点个数, 21 如 new_his[1] = old_his[0] + old_his[1] 假设=5, 22 而当new_his[2] = 100时,这就说明从灰度级1到灰度级2之间的数量跨度非常的大,我们需要重新对这100个像素点表示的灰度级重新分配。 23 */ 24 for (n = 1;n < 256;n++) 25 hist[n] += his[n - 1]; 26 27 BYTE gray[256];// 存储经过均衡化后的灰度值 28 float cons; 29 cons = 255.0f / his[255];// 计算均衡化后的灰度值比例尺,即归一化因子 —— 这一步是将256个像素均匀的分配到每个像素点上,如图像有1000个像素点,则cons = 255 / 1000; 30 31 // 计算均衡化后的灰度值 32 for (n = 0;n < 256;n++) 33 gray[n] = (BYTE)(cons * his[n]);// 对每个灰度级进行均衡化计算 34 /* 35 为什么是使用cons * new_his[],而不是和 old_his[]进行操作呢? 36 old_gray[] = {0, 1, 2, 3} —— 表示从0到3上的像素点的灰度级 37 假设old_his[] = {1, 201, 13, 50} —— 表示0到3这四个灰度级的个数 38 new_his[] = {1, 202, 215, 255} —— 经过累加后,变成 <= 当前灰度级的所有像素个数 39 40 我们分别和cons(假设归一化因子是0.25)进行计算: 41 cons_old_his = {0.25, 50.25, 3.25, 12.5} = cons_old_gray —— cons_old_his此时表示每个像素点上的灰度级,我们对比 old_gray可以清晰的发现,原像素级是递增的,然是此时的cons_old_his确实第二个像素点的像素级最大,这不符合原图像 42 cons_new_his = {0.25, 50.5, 53.75, 63.75} = cons_new_gray —— 至此,这便是为什么是和 new_his 进行乘积,而不是 old_his 进行乘积。 43 44 */ 45 46 // 应用均衡化后的灰度值到输出图像 47 for (i = 0;i < h;i++) 48 for (j = 0;j < w;j++) 49 outImg[i * w + j] = gray[image[i * w + j]];// 将均衡化后的灰度值应用到输出图像中 50 }
总结:直方图均衡的核心,即获取小于等于当前灰度级存在的所有的像素点,设定归一化因子,最后进行均衡化计算。