直方图均衡化对有些图片不能达到好的效果, 为啥?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了直方图均衡化对有些图片不能达到好的效果, 为啥?相关的知识,希望对你有一定的参考价值。

写了个实现了直方图均衡化算法的图片处理程序,
采用公式:Sk = (nk/N) * 255
(公式中Sk表示均衡化后的灰度值, nk是原图中从0到某个灰度色阶k的像素总数量,N是图像像素总数)。 但是对许多不同的照片测试的时候发现, 对一些照片增强对比度效果不错, 而对另外一些(尤其是特别暗或是特别亮的)则效果不好,甚至整张图片出现明显马赛克状小块或是有些区域跟原图明显不符。 哪位高手解释一下这是为什么?
我泱泱大国, 数十亿人口, 就没有在图像处理方面有所精通的? 不能够吧?! 我就想知道为什么这个histogram equalization不是对所有图片都能取得好的增强效果。

我来说一下

首先直方图均衡化的公式为sk对nj/n在j由0到k求和,正如楼主你所说,它所起到的作用是把原本分布不均的灰度直方图在整个灰度级别内均匀分布。

呵呵,一定要抓住这一点,即均衡化是由公式实现的,你想一想,对于一幅很暗的图片,既是它的灰度直方图全都集中在低灰度区,即比如灰度值由0-255,灰度值是2,3,5等的低灰度的频数就会很大,即它们的频率好高,因为这幅画很暗。好,现在咱们把这幅画均衡化,看那个公式的定义,根据公式得来的数据,即均衡化后的直方图中,低灰度区,比如5这一灰度级所对应的频数是不是很大,因为现在的是把原图中低灰度区,即正如上面所假设的2,3,5这些频率很大的灰度级相加而得,当然加后所得更大,即在均衡化后,仅5这一点得频数就已经很高,即频数很大,即灰度级很大,可想而知,越往后加,灰度级都很大,对应的,灰度级大了,当然直方图就集中在高灰度区,相应的图像就发白或很亮。特别亮的也是一个道理。

对于这种情况,应该用直方图规定化(匹配)来处理。

对于马赛克,很简单,你想想,先画一个8*8格,拿不同深度的铅笔,比如H,2H,B,2B之类的,你想在只拿一种深度的把四个格都涂满,是不是黑乎乎一片,然后拿两种笔涂,是不是有了区别。你用的铅笔深度种类越多,整个格所构成的图画细节越明显。同理,当你把很暗的图均衡化后,灰度级别都集中在高灰度区,就相当于笔的种类很少来画这幅画,当然也有马赛克。

给你截的图是均衡化后的,你仔细想想.

呵呵

参考技术A 直方图均衡化基本上是对一幅图中的灰度值进行一下重排列平均分布一下 如果你的原始图像里面没有亮的部分全部是黑暗的灰度值接近0或者很低灰度值的 当然是不会有好效果的 就是你说的特别暗的图像 本身它的灰度值都集中在100以下 你就算是均匀分布这些低灰度值的象素 得到的图片还是低灰度值的图片 绝对的一片黑暗 特别是 看你写的公式 你在用matlab做这个程序吧 matlab处理都是按照矩阵 方块处理 会出现马赛克小块 一般的 处理这种问题可以自己稍微制造一些亮块 或者是 暗块来方便均匀化后的效果 得到各个亮度的点的总和以后 选择最多的那个值 比如说一个暗色的图 hist=80 有6000个点 那么就把灰度值=80×0.9 (记住去floor) 以上的 全部+20-40 变亮整个图像 或者自己写一个function 来检测拿125为检测界限
如果有需求 可以发你需要处理的 效果不好的图片 给我 我用matlab 试试看
lanceinmf@yahoo.com
参考技术B 现在给你讲不懂的,你学多了就懂了。 参考技术C 呵呵.不同工具有不同的用途.剪子和刀都是有刃的工具,作用就一样吗?同理,不同的对象,要用不同的工具来处理.这不是再明显不过的道理吗?

图像处理系列——直方图之直方图均衡化(Histogram Equalization)

目录

1、理论知识

2、数学原理

3、案例分析

4、代码实现

5、结果显示

6、参考


1、理论知识

        直方图均衡化是一种借助直方图变换实现灰度映射从而达到图像增强目的的方法。

        基本思想:把原始图的直方图变换成为均匀分布的形式,即对图像中像素个数多的灰度级进行展宽,而对像素个数少的灰度级进行缩减。增加了像素灰度值的动态范围,从而达到增强图像整体对比度的效果。

        直方图反映了图像的清晰程度,当直方图均匀分布时,图像最清晰。由此,利用直方图均衡化可以达到了使图像清晰的目的。

2、数学原理

        图像直方图均衡化采用累积分布函数:

        需要理解:1、为什么要选用累积分布函数?2、使用累积分布函数处理后像素值为什么会均匀分布?

  1. 均衡化过程中,必须保证两个条件:①像素无论怎么映射,一定要保证原来的大小关系不变,较亮的区域依旧较亮,较暗依旧较暗,只是对比度增大,绝对不能明暗颠倒;②如果是八位图像,那么像素映射函数的值域应在0~255之间,不能越界。因此,累积分布函数是个好的选择,因为累积分布函数是单调增函数(控制大小关系),并且值域是0到1(控制越界问题),所以直方图均衡化中使用的是累积分布函数。
  2. 累积分布函数具有一些好的性质,那么如何运用累积分布函数使得直方图均衡化?比较概率分布函数和累积分布函数,前者的二维图象是参差不齐的,后者是单调递增的。

        由于各个灰度级是离散的,上式又可以写作:

        其中,n是图像中像素的总和(n=W*H),是当前灰度级的像素个数,L是图像中灰度级总数。

3、案例分析

        接图像处理系列——直方图之灰度直方图(Image Histogram)_nanke_yh的博客-CSDN博客中计算案例有:

灰度级 r

0

1

2

3

4

5

6

7

像素数量nr

792

1026

851

662

323

240

120

82

概率分布P(r)

0.19

0.25

0.21

0.16

0.08

0.06

0.03

0.02

累积分布sk

0.19

0.44

0.65

0.81

0.89

0.95

0.98

1

均衡化取值S(k)

1

3

5

6

6

7

7

7

确定映射关系r->S(k)

0->1

1->3

2->5

3,4->6

5,6,7->7

均衡化后图像直方图

0.19

0.25

0.21

0.24

0.11

        

         继计算图像直方图后,图像均衡化的步骤:

(1)计算直方图概率累积分布sk

        这里s0=P0;

              s1=P0+P1;

              sk=P0+P1+……+Pk    where(k>1)。

(2)根据公式求取像素映射关系S(k)

        S(k)=int[max(pix)-min(pix)]*s(k)+0.5

        其中,pix指原图像中的灰度值,求取原图像中的最大灰度值减去最小灰度值。S(k)是第k灰度级所对应的均衡化图像中的灰度级。

        S(k)=int[(L-1)-0]*s(k)+0.5

        而有的均衡化理论中使用(L-1)-0,也就是该图像灰度级中的最大值减去灰度最小值。L是图像总灰度级数。

(3)灰度映射

        上一步找到了原图像和均衡化图像灰度的对应关系,对原图进行操作,将每个像素映射成新的像素即可。

(4)图像均衡化后图像直方图

        此时图像均衡化已经完成,可以再次统计新图像的灰度概率,观察一下结果。

4、代码实现

/*function description:图像直方图均衡化
*
*input parameter:
*				ImgTyp* Image    原始图像
*return:
*				ImgTyp* ImgEqual 直方图均衡化后的图像
******************************************************/
ImgTyp* HistogramFun::HistEqual2(ImgTyp* Image)

	if (Image == NULL)
	
		return NULL;
	
    double* ImgHist = CalImgHist(Image);//计算图像直方图概率分布
	ImgTyp*ImgEqual = new ImgTyp[Width*Height];
	memset(ImgEqual,0,sizeof(ImgTyp)*Width*Height);
	//累积分布sk
	double sk[ColorLen] = 0;
	//sk[0] = ImgHist[0];
	//for (int k = 1; k < ColorLen; k++)
	//
	//	sk[k] = sk[k-1] + ImgHist[k];//累计密度函数值
	//
	double  sum = 0;
	for (int k = 0; k < ColorLen; k++)
	
		sum += ImgHist[k];
		sk[k] = sum;//累计密度函数值
	
	for (int i = 0; i < Height; i++)
	
		for (int j = 0; j < Width; j++)
		
			int target_value = 0;
			target_value = int((ColorLen-1) * sk[Image[i*Width+j]]+0.5);//[(L-1)*s+0.5]
			if (target_value > ColorLen-1)
			
				target_value = ColorLen-1;
			
			ImgEqual[i*Width+j] = target_value;
		
	
	delete []ImgHist;
	ImgHist = NULL;
	return ImgEqual;

5、结果显示

        基于上面得出的结果进行显示:

均衡化后的图像1

target_value = int((ColorLen-1) * sk[Image[i*Width+j]]+0.5);//[(L-1-0)*s+0.5]

灰度级中的最大值减去灰度最小值

ImgTyp* imgEqual = hist.HistEqual2(img);

WriteTif( imgEqual,outfile[0],hist.Width,hist.Height);

showImg(outfile[0],"直方图均衡化图像1");

均衡化后图像的直方图

double* EqualhistArr = hist.CalImgHist(imgEqual);

showHist(EqualhistArr,"均衡化后图像直方图1");

均衡化后的图像2

target_value = int((MMPixel[0]-MMPixel[1]) * sk[Image[i*Width+j]]+0.5);//[(max(pix)-min(pix))*s+0.5]

图像中的最大灰度值减去最小灰度值

ImgTyp* imgEqual1 = hist.HistEqual3(img);

WriteTif(imgEqual1,outfile[2],hist.Width,hist.Height);

showImg(outfile[2],"直方图均衡化图像2");

均衡化后图像的直方图

double* EqualhistArr1 = hist.CalImgHist(imgEqual1);

showHist(EqualhistArr1,"均衡化后图像直方图2");

        发现第二种均衡化方式得到的图像相较第一种会偏暗,直方图的色阶也会少一些。

6、参考

数字图像处理:直方图均衡化 - 简书 (jianshu.com)

直方图均衡化计算过程_macunshi的专栏-CSDN博客_直方图均衡化计算步骤

图像处理之直方图均衡化及C++实现_程序员深度学习-CSDN博客

以上是关于直方图均衡化对有些图片不能达到好的效果, 为啥?的主要内容,如果未能解决你的问题,请参考以下文章

写一段代码画出一个图像的灰度直方图(不能用MATLAB自带的imhist函数),并作直方图均衡化处理。

视觉项目day28.21号实验记录(手机固定高度15cm拍摄+直方图均衡化+模板匹配,模板12个,测试28个,效果十分差)

直方图均衡化局部直方图均衡化直方图统计算法在图像处理效果上的对比

图像增强:直方图均衡和小波变换matlab

5-1 美化效果章节介绍

数字图像处理3