CV学习-直方图均衡化
2017-03-21 16:46
120 查看
利用直方图均衡化增强图像
利用直方图均衡化增强图像概述
灰度直方图
核心思想
证明过程
代码
测试结果
概述
图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法。直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法。直方图拉伸是通过对比度拉伸对直方图进行调整,从而“扩大”前景和背景灰度的差别,以达到增强对比度的目的,这种方法可以利用线性或非线性的方法来实现;直方图均衡化则通过使用累积函数对灰度值进行“调整”以实现对比度的增强。直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。这种方法通常用来增加许多图像的局部对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
灰度直方图
概念灰度直方图(histogram)是灰度级的函数,它表示图象中具有每种灰度级的象素的个数,反映图象中每种灰度出现的频率。灰度直方图的横坐标是灰度级,纵坐标是该灰度级出现的频率,是图象的最基本的统计特征。
从概率的观点来理解,灰度出现的频率可看作其出现的概率,这样直方图就对应于概率密度函数pdf,而概率分布函数就是直方图的累积和,即概率密度函数的积分.
性质
它只反映该图像中不同灰度值出现的次数,而未反映某一灰度值像素所在的位置。也就是说,它只包含了该图像中某一灰度值的像素出现的概率,而丢失了其所在位置的信息。
核心思想
直方图均衡化处理的中心思想是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。对图像空间域点的增强过程是通过增强函数t=EH(s)来完成的,t、s分别为目标图像和原始图像上的像素点(x, y)处的灰度值。
在进行均衡化处理时,增强函数EH需要满足两个条件:
1)、增强函数EH(s)在0≤s≤L-1的范围内是一个单调递增函数,这个条件保证了在增强处理时没有打乱原始图像的灰度排列次序;
2)、对于0≤s≤L−1应当有0≤EH(s)≤L−1,它保证了变换过程中灰度值的动态范围的一致性。同样的,对于反变换过程s=EH-(t),在0≤t≤1时也必须满足上述两个条件。
可以证明累积分布函数就是满足上述条件,通过该函数可以完成s到t的均匀分布转换,即使直方图均衡化的灰度变化函数是累积分布函数(概率分部函数)。
离散情况下的增强转换方程为:
彩色图片可以分别提取RGB三个通道的值分别进行直方图均衡化操作,然后再将三个通道的值合并成彩色图像。
证明过程
代码
实现代码采用CImg.h读入和显示图像,CImg 库是一个免费、开源的图像处理C++库,名称原意是 Cool Image,正如其名,CImg是一个非常优秀、功能强大、代码简洁、使用方便的C++ 图像处理库。代码可以到CImg官网下载
CImg 官网:http://cimg.sourceforge.net/
main.cpp
#include "CImg.h" #include <string> #include <iostream> using namespace cimg_library; using namespace std; void ImgHE(const char* filename, bool isGray) { // 读入图片 CImg<unsigned char> source; source.load_bmp(filename); // 测试用例预处理 CImg<unsigned char> img; if (source.spectrum() == 3 && isGray) { img = source.get_RGBtoGray(); } else if (source.spectrum() == 1 && !isGray) { // 灰度图片作彩色图片处理 cout << "error test!" << endl; return; } else { img = source; } // 图片参数 int height = img.height(); int width = img.width(); int size = width * height; int channel = img.spectrum(); // 结果图像 CImg<unsigned char> result(width, height, 1, channel, 0); // RGB三个通道分别进行直方图均衡化 // 灰度图片只有一个通道 for (int k = 0; k < channel; k++) { int hg[256] = { 0 }; // 直方图 float hgPDF[256] = { 0 }; // PDF float hgCDF[256] = { 0 }; // CDF int hgEQL[256] = { 0 }; //归一化直方图 // 统计像素值分布直方图 cimg_forXY(img, x, y) { hg[(int)img(x, y, 0, k)]++; } for (int i = 0; i < 256; i++) { hgPDF[i] = (float)hg[i] / size; // PDF if (i == 0) { // CDF hgCDF[i] = hgPDF[i]; } else hgCDF[i] = hgCDF[i - 1] + hgPDF[i]; hgEQL[i] = (int)(255 * hgCDF[i] + 0.5); // 归一化 t = int[(L-1)*s + 0.5] } // 生成结果图像 cimg_forXY(img, x, y) { result(x, y, 0, k) = hgEQL[(int)img(x, y, 0, k)]; } } // 显示结果 (img, result).display(); } int main() { // HistogramEqualization ImgHE("1.bmp", true); ImgHe("1.bmp", false); return 0; }
测试结果
左图为原图,右图为增强后的图相关文章推荐
- OpenCV函数学习之cvLUT
- 学习汇编的一些心得,CV之后无法LINK和INT 21H的问题
- 全球机器学习ML、机器视觉CV、 图像处理PP领域的学习站点
- Oopencv学习心得(二)——绘制直方图
- opencv中的cvWaitKey()(学习之三)
- Oopencv学习心得(二)——绘制直方图
- 学习OpenCV---cvWaitKey()
- OpenCV学习笔记(2)—— CV_Assert 函数
- OpenCv学习笔记(二)—cv::Mat学习
- cv学习
- openCv学习笔记(二)—cv::Mat学习
- Emgu.CV OpenCV 学习之路(二)
- CV学习牛人链接
- OpenCV 2.x新数据结构cv::Mat的一些学习材料
- OpenCV函数学习之cvLUT
- 学习CV&CG的那些事 II
- Emgu.CV OpenCV 学习之路(一)
- 学习OpenCV——皮肤检测类:CvAdaptiveSkinDetector
- openCv学习札记(二)—cv:Mat学习
- Opencv2 学习笔记<一>:cv::Mat数据访问方式