直方图均衡化
直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。
直方图均衡化要达到的效果:
基本思想:把原始图的直方图变换为均匀分 布的形式,这样就增加了像素灰度值的动态 范围,从而达到增强图像整体对比度的效果
使用的方法是灰度级变换:s = T(r)
原理:
s=T(r) 0≤r≤1
T(r)满足下列两个条件:
(1)T(r)在区间0≤r≤1中为单值且单调递增
(2)当0≤r≤1时,0≤T(r) ≤1
条件(1)保证原图各灰度级在变换后仍保持从黑 到白(或从白到黑)的排列次序
条件(2)保证变换前后灰度值动态范围的一致性
Pr(r)是r的概率密度函数,Ps(s)是s的概 率密度函数,Pr(r)和T(r)已知,且T-1(s) 满足上述条件(1),所以有
已知一种重要的变换函数:
关于上限的定积分的导数就是该上限的积分值 (莱布尼茨准则)
对于离散值:
其中rk 是第k个灰度级,k = 0,1,2,…,L-1.
nk是图像中灰度级为rk的像素个数.
n是图像中像素的总数.
已知变换函数的离散形式为:
sk称作直方图均衡化 将输入图像中灰度级为rk(横坐标)的像素映射 到输出图像中灰度级为sk (横坐标)的对应像素得到.
实现代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/****************************************************************************** * 作用: 灰度均衡函数 * 参数: * pixel 原始像素数组 * tempPixel 保存变换后图像的像素数组 * width 原始图像宽度 ******************************************************************************/ void GrayEqualize(BYTE* pixel, BYTE* tempPixel, UINT width, UINT height) { // 灰度映射表 BYTE map[256]; long lCounts[256]; memset(lCounts, 0, sizeof(long) * 256); // 计算各灰度值个数 for (UINT i = 0; i < width * height; i++) { int x = pixel[i * 4]; lCounts[x]++; } // 保存运算中的临时值 long lTemp; for (int i = 0; i < 256; i++) { lTemp = 0; for (int j = 0; j <= i; j++) lTemp += lCounts[j]; map[i] = (BYTE)(lTemp * 255.0f / width / height); } // 变换后的值直接在映射表中查找 for (UINT i = 0; i < width * height; i++) { int x = pixel[i * 4]; tempPixel[i*4] = tempPixel[i*4+1] = tempPixel[i*4+2] = pixel[i * 4]; tempPixel[i*4+3] = 255; } }
彩色图直方图均衡化:
更清晰:
opencv代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
//// #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; using namespace std; int main( int argc, const char** argv ) { Mat img = imread("MyPic.JPG", CV_LOAD_IMAGE_COLOR); //open and read the image if (img.empty()) //if unsuccessful, exit the program { cout << "Image cannot be loaded..!!" << endl; return -1; } vector<Mat> channels; Mat img_hist_equalized; cvtColor(img, img_hist_equalized, CV_BGR2YCrCb); //change the color image from BGR to YCrCb format split(img_hist_equalized,channels); //split the image into channels equalizeHist(channels[0], channels[0]); //equalize histogram on the 1st channel (Y) merge(channels,img_hist_equalized); //merge 3 channels including the modified 1st channel into one image cvtColor(img_hist_equalized, img_hist_equalized, CV_YCrCb2BGR); //change the color image from YCrCb to BGR format (to display image properly) //create windows namedWindow("Original Image", CV_WINDOW_AUTOSIZE); namedWindow("Histogram Equalized", CV_WINDOW_AUTOSIZE); //show the image imshow("Original Image", img); imshow("Histogram Equalized", img_hist_equalized); waitKey(0); //wait for key press destroyAllWindows(); //destroy all open windows return 0; }
代码中使用的函数:
New OpenCV functions
- cvtColor(img, img_hist_equalized, CV_BGR2YCrCb)
- void split(const Mat& m, vector<Mat>& mv )
- const Mat& m - Input multi-channel array
- vector<Mat>& mv - vector that stores the each channel of the input array
- equalizeHist(channels[0], channels[0]);
- void merge(const vector<Mat>& mv, OutputArray dst )
- const vector<Mat>& mv - vector that holds several channels. All channels should have same size and same depths
- OutputArray dst - stores the destination multi-channel array
- cvtColor(img_hist_equalized, img_hist_equalized, CV_YCrCb2BGR)
参考博客:http://opencv-srf.blogspot.jp/2013/08/histogram-equalization.html