版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SakuraMashiro/article/details/80322121
一、概念
直方图均衡,空域图像处理中最常用的技术之一,属于灰度变换的范畴,旨在通过一个灰度变换的函数,将原图像的每个灰度级映射到一个新的灰度级,提高灰度级的动态范围,使图像的直方图(即不同灰度出现次数的概率分布图)在整个灰度级的范围内趋于均匀,从而增强图像整体的对比度。
二、映射函数
灰度变换的目的就是找到一个合适的映射函数s=T(r)
对于离散的数字图像而言,就变成了累积求和
其中L是指图像的灰度范围,对于8位的灰度图而言就是256.
三、步骤
- 扫描原图像的所有像素
- 统计每个灰度出现的次数,并除以像素的总数(归一化)。
- 根据上面的公式对灰度的概率进行累加求和,并乘以255(L-1),就得到了变换后的新的灰度。
- 根据映射表将原图像的灰度替换成新的灰度。
四、VS2015+OpenCV实现
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
Mat src = imread("timg.jpg",0);
if (src.empty()) {
cout << "图像读取失败";
return -1;
}
imshow("直方图均衡前的图片", src);
int nr = src.rows;
int nc = src.cols;
//像素总数
int total = nr * nc;
//转换后的目标矩阵
Mat dst_2(nr, nc, CV_8U);
//获取原图像直方图
uchar *p_1 = NULL;
//存储直方图统计结果的数组
unsigned int hist[256] = { 0 };
//扫描原图像
for (int i = 0; i < nr; i++) {
//获取第i行像素数组首指针
p_1 = src.ptr<uchar>(i);
for (int j = 0; j < nc; j++) {
hist[p_1[j]] ++;
}
}
//计算灰度变换函数
//transf_fun存储均衡前像素值与均衡后像素值的映射关系
uchar transf_fun[256] = { 0 };
transf_fun[0] = (uchar)(255 * hist[0] / total);
//累积
for (int i = 1; i < 256; i++) {
hist[i] = hist[i - 1] + hist[i];
transf_fun[i] = (uchar)(255 * hist[i] / total);
}
uchar * p_2 = NULL;
for (int i = 0; i < nr; i++) {
//获取第i行像素数组首指针
p_2 = dst_2.ptr<uchar>(i);
p_1 = src.ptr<uchar>(i);
//根据映射关系将原图像灰度替换成直方图均衡后的灰度
for (int j = 0; j < nc; j++) {
p_2[j] = transf_fun[p_1[j]];
}
}
imshow("直方图均衡后的图像",dst_2);
waitKey(0);
return 0;
}
变换前
变换后