1、 直方图
对于一幅图像的每个灰度级的像素个数进行统计,得到每个灰度级占整张图像的比例:
n_k为灰度等级k的像素数量,N为整幅图像的像素数总和。
将各个灰度级的像素数量绘制为条形图就是直方图了
2、 直方图均衡化
一幅对比度较小的图像其直方图分布一定集中在一个比较小的灰度级范围内,想要更好多的展现图像的细节信息,可以对直方图进行均值化,使得各个灰度级的占比(大致)相同,这样就加大了图像的对比度。
直方图均衡化实现:
由直方图可以得到灰度等级的离散概率分布函数:
而根据灰度量化级数M得到各个等级的量化值为:
然后对每一个F(k)重新进行等级划分,划分规则如下:
如果F(k) 与 G(j)最相近,就将所有原始灰度级为r_k的像素转变为灰度级r_j
按此规则对各个灰度等级的像素重新划分灰度级,达到均衡化的目标。
直方图均衡化并不能把同一灰度等级的像素分开,只是根据各个灰度等级的像素数量占比,将像素数较小且级别相近的灰度级归并,并对其重新划分灰度等级的操作。
因此均衡化后,量化级别的数目减少,不同级别之间可能会存在间隔,使得原本对比度不明显的区域之间的边界更加明显,所以提升了图像的对比度。
例如,对于一个8灰度级的灰度图片的直方图均衡化过程为:(图片来源于参考文献[1])
可以看到,均衡化后灰度等级数量变少,部分等级之间的间隔变大,对比度就得到了提升
3、使用
Opencv直方图均衡化函数:
void equalizeHist(InputArray src,InputArray dst);
//参数:输入图片,输出图片
注意:opencv3中的直方图均衡化函数只能对灰度图进行均衡化,不能对彩色图片进行处理。
如果想要对彩色图片进行均衡化,可以将图片从RGB空间转到HSV空间,然后分离通道单独对V通道(即亮度通道)进行均衡化,然后与其他两个通道合并,这样能够在不改变图像的色相等的基础上实现彩色图片亮度的均衡化。
使用实例:
#include <iostream>
//opencv库
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
//namespace
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("../Images/7.jpg");
if (src.empty()) { cout << "read the image failed!!!!!!" << endl; return -1; }
//灰度均值化
Mat src_gray;
Mat dst_gray;
cvtColor(src, src_gray, COLOR_BGR2GRAY);
equalizeHist(src_gray, dst_gray);
//彩色图像 亮度均值化
Mat src_hsv;
Mat dst_hsv;
cvtColor(src, src_hsv, COLOR_BGR2HSV);
vector<Mat> hsv_channels;
split(src_hsv,hsv_channels);//分离HSV通道并存储,存储顺序为H,S,V
equalizeHist(hsv_channels[2], hsv_channels[2]);//对亮度通道进行均衡化后存储回原位置
merge(hsv_channels, dst_hsv);//通道合并
cvtColor(dst_hsv, dst_hsv, COLOR_HSV2BGR);//将图像重新转换到RGB空间用于显示
namedWindow("src_gray", WINDOW_NORMAL);
namedWindow("dst_gray", WINDOW_NORMAL);
namedWindow("src", WINDOW_NORMAL);
namedWindow("dst_hsv", WINDOW_NORMAL);
imshow("src_gray", src_gray);
imshow("dst_gray", dst_gray);
imshow("src", src);
imshow("dst_hsv", dst_hsv);
waitKey(0);
return 0;
}
最终处理结果如下:
灰度:
彩色:
这张图效果不太明显,可以选用明暗差异小的图片进行测试,效果会更好
4、参考文献
[1]《数字图像处理与图像通信》朱秀昌 刘峰 胡栋
[2] 《OpenCV3编程入门》
[3] https://blog.csdn.net/kuweicai/article/details/73824485