个人博客:http://www.chenjianqu.com/
原文链接:http://www.chenjianqu.com/show-11.html
概念
在统计学中,直方图(英语:Histogram)是一种对数据分布情况的图形表示,是一种二维统计图表,它的两个坐标分别是统计样本和该样本对应的某个属性的度量。直方图是品质管理七大工具之一。把直方图上每个属性的计数除以所有属性的计数之和,就得到了归一化直方图。之所以叫“归一”,是因为归一化直方图的所有属性的计数之和为1,也就是说,每个属性对应计数都是0到1之间的一个数(百分比)。
简而言之,直方图是图像中像素强度分布的图形表达方式。它统计了每一个强度值所具有的像素个数。
直方图均衡化
直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法。是图像处理领域中利用图像直方图对对比度进行调整的方法。
均衡化指的是把一个分布(给定的直方图)映射到另一个分布(一个更宽更统一的强度值分布),所以强度值分布会在整个范围内展开。映射函数应该是一个累积分布函数(cumulative distribution function(cdf))。
直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。
这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。这种方法对于背景和前景都太亮或者太暗的图像非常有用。
这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。
这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。
算法步骤
(1)、统计原始图像各灰度级的像素数目ni,0≤i<L, L是图像中所有的灰度数(通常为256);
(2)、图像中灰度为i的像素的出现概率是:px(i)=p(x=i)=ni/n,n是图像中所有的像素数,px(i)实际上是像素值为i的图像的直方图,归一化到[0, 1];
(3)、px的累积分布函数,是图像的累计归一化直方图:
(4)、直方图均衡化计算公式, cdfmin为累积分布函数最小值,M和N分别代表了图像的长宽像素个数,而L则是灰度级数(如图像为8位深度,则灰度级别共有2^8=256级数,这也是最常见的灰度级数),v为原始图像中为v的像素值:
算法实现 - 绘制直方图
Mat generateHistogram(vector<int> hist,int maxValue)
{
int width = 512;
int height = 512;
Mat dst(width, height,CV_8UC1, Scalar(0));
int n = hist.size();
for (int i = 0; i < n; i++)
{
int interval = width / n;
int x = i * interval;
int maxY =int( hist[i] * height / maxValue);
for (int j = 0; j < maxY; j++)
dst.at<uchar>(height -j-1, x)=255;
}
return dst;
}
Mat showHistogram(Mat &src, int n)
{
vector<int> hist;
int max;
for (int k = 0; k < n; k++)
hist.push_back(0);
double interval = n / 256.0;
for(int i=0;i<src.rows;i++)
for (int j = 0; j < src.cols; j++)
{
int pix = int(src.at<uchar>(i, j)*interval);
hist[pix]++;
}
max = hist[0];
for (int k = 1; k < n; k++)
{
if (hist[k] > max)
max = hist[k];
}
return generateHistogram(hist, max);
}
当n=256时,运行结果如下:
算法实现 – 直方图均衡化
Mat HistogramEqualization(Mat &src, int n)
{
vector<int> hist;
vector<double> proHist;//累计概率向量
vector<int> dstHist;
int max;
double interval = n / 256.0;
long sumPix = src.rows*src.cols;
Mat dst(src.rows,src.cols, CV_8UC1, Scalar(0));
for (int k = 0; k < n; k++) {
hist.push_back(0);
dstHist.push_back(0);
proHist.push_back(0.0);
}
for (int i = 0; i < src.rows; i++)
for (int j = 0; j < src.cols; j++)
hist[int(src.at<uchar>(i, j)*interval)]++;
//求出累计概率矩阵和灰度级像素数量最大值
max = hist[0];
proHist[0] = hist[0]*1.0 / sumPix;
for (int k = 1; k < n; k++) {
proHist[k] = proHist[k-1]+hist[k] * 1.0 / sumPix;
if (hist[k] > max)
max = hist[k];
}
//根据累计概率对灰度级进行映射
for (int i = 0; i < n; i++) {
dstHist[i] = int(proHist[i] * (n - 1) + 0.5);//0.5表示要四舍五入
}
//对图像进行映射
for (int i = 0; i < src.rows; i++)
for (int j = 0; j < src.cols; j++) {
int srcLevel = int(src.at<uchar>(i, j)*interval);
int dstLevel = dstHist[srcLevel];
dst.at<uchar>(i, j) = int(dstLevel / interval);
}
return dst;
}
原图:
直方图均衡化之后:
参考文献
[1] 百科百科.直方图均衡化.
[2] CSDN博客:fengbingchun. 灰度图像直方图均衡化公式及实现.
https://blog.csdn.net/fengbingchun/article/details/79188021 . 2018-01-28
[3] 韩九强,杨磊.数字图像处理.西安交通大学出版社.2018-08