OpenCV-跟我一起学数字图像处理之直方图均衡化

从这篇博文开始,小生正式从一个毫不相干专业转投数字图像处理。废话不多说了,talk is cheap. show me the code.

  • 直方图均衡化目的

由于一些图像灰度的分布过于集中,这样会导致图像的层次不够分明,直方图均衡化就是为了让图像的灰度分布更均匀,图像的层次感更强。

  • 数学原理

  基于连续灰度分布的结论推导

直方图均衡化属于数字图像处理中灰度变换(intensity transformation)的内容,灰度变换的目的就是找到一个合适的映射函数s=T(r).将原图像的灰度值映射到新的图像中,已达到优化图像的目的。

假设原图像的灰度统计直方图标准化后为pr(r).原图像灰度范围为(0~L-1)。那么直方图均衡化找到的就是这样一个映射函数:

设映射后的图像的灰度分布为ps(s),在由概率论相关理论(随机变量函数的概率密度与随机变量概率密度的关系)可知:

对映射函数两边进行求导

所以我们可以得到变换后的图像直方图分布为

我们可以看到,变换后的图像灰度直方图分布恒为1/(L-1),这就达到了上面的目的,使得图像的灰度分布更均匀,层次感更强。

 

注:在灰度变换中,变换函数T(r)需要满足下面的两点要求,

  1. 当0≤r≤L-1时,T(r)是一个严格递增函数。
  2. 当0≤r≤L-1时,0≤T(r)≤L-1。

第一点要求的原因是,对于变化前像素和变换后像素灰度的明暗顺序不能改变,之所以要严格递增,是为了确保变化前和变换后像素可以一一对应。

第二点要求的原因是,变换后的图像不能超过原先的灰度级数。

不难发现,其实直方图均衡化的过程并不一定满足条件1。所以该变换时不可逆的。

  公式的离散化

设原图像灰度等级为0、1、2……L-1.离散化后的映射公式就是

在利用上面公式进行计算的时候,需要把计算的结果s(r),近似为最近的整数。

  • 基于OpenCV的直方图均衡化

OpenCV中有专门的直方图均衡化函数,equalizeHist,定义的头文件在imaproc/imaproc.hpp中。

基于OpenCV的直方图均衡化代码段:

 1 //load the original image and show
 2 Mat src,dst_1;
 3 src = imread("test.jpg",0);
 4 namedWindow("OriginalGrayImage");
 5 imshow("OriginalGrayImage",src);
 6 
 7 //use the OpenCV measure do histogram equalization
 8 equalizeHist(src,dst_1);
 9 namedWindow("histogram equalization_opencv");
10 imshow("histogram equalization_opencv",dst_1);

仿真结果:

原图:

使用equalizeHist均衡化后的结果:

  • 根据推导过程,自己编写的直方图均衡化

代码段如下:

 1 //rewrite the histogram algorithm
 2 //get some needed information
 3 int nr = src.rows;
 4 int nc = src.cols;
 5 int n = nr*nc;
 6 Mat dst_2(nr,nc,CV_8U);
 7 
 8 //get the histogram of original image
 9 uchar *p_1 = NULL;
10 unsigned int hist[256] = {0};
11 for(int i=0;i<nr;i++)
12 {
13     p_1 = src.ptr<uchar>(i);
14     for(int j=0;j<nc;j++)
15     {
16         hist[p_1[j]] = hist[p_1[j]]+1;
17     }
18 }
19 
20 //calculate the transform function
21 uchar transf_fun[256] = {0};
22 transf_fun[0] = (uchar)(255*hist[0]/n);
23 for(int i=1;i<256;i++)
24 {
25     hist[i] = hist[i-1]+hist[i];
26     transf_fun[i] = (uchar)(255*hist[i]/n);
27 }
28    
29 //pad dst_2 the equalized values
30 uchar *p_2 = NULL;
31 for(int i=0;i<nr;i++)
32 {
33     p_2 = dst_2.ptr<uchar>(i);
34     p_1 = src.ptr<uchar>(i);
35     for(int j=0;j<nc;j++)
36     {
37          p_2[j] = transf_fun[p_1[j]];
38     }
39 }
40 
41 //show the results of our own histogram algorithm
42 namedWindow("histogram equalization_own");
43 imshow("histogram equalization_own",dst_2)       

运行结果:

转载于:https://www.cnblogs.com/german-iris/p/4811462.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值