直方图均衡

直方图这个东西,是个好东西。所谓的直方图,就是统计这个图像当中intensity的分布情况。直方图在图像处理当中的用处还是挺大的。

这里我们说一下直方图的均衡问题。

首先,为什么要进行直方图均衡?

我们知道,在RGB色彩系统中,我们可以通过一个公式,将RGB色彩图像转换为灰度图像,这个公式就是Gray = R*0.299 + G*0.587 + B*0.114。通过这个公式,我们就能对图像中intensity有一些了解:如果一个像素点的RGB三色都比较大,那么这个像素的色彩应当是偏向于白色的,他的intensity也会增大,RGB三色都比较小的时候,像素色彩偏向于黑色,intensity也会较暗。虽然RGB三色的不同组合代表了不同的颜色,但是,我们这里只考虑RBG三色根据上面公式所获取的单一的数值大小,而这个数值大小也就是灰度值。我们对于intensity的调整不会影响图像的形状和构造。当然,由于这个公式属于三元一次方程,解不确定,因此,这个过程不可逆,也就是说,想要进行彩色图案的色彩均衡,需要另外一种办法。

既然是直方图的均衡,我们可以认为是图像intensity的均衡。我们使用的均衡方法的步骤是:

1、统计各个intensity级数的像素个数,求出intensity级数像素数目所占所有像素的比例。

2、根据不同的intensity级数我们分配不同的数值。

我们之所以这么做的原因是:

使用上面的步骤的原因为:一个图像中的intensity级数分布是没有规律的,我们之所以要进行直方图均衡,是因为他能够增强图像的对比图,提升图像的表现。第一步通过求出各个intensity的级数所占的比例,就能够得出哪个intensity级数占的比例更大,哪个更小。将比例作为权重,且intensity级数越大,显示效果更好。这就是用数学方法将占比例小的intensity级数滤去。

假如我们有如下数据:1,2,2,2,2,2,2,3,3,3,,4,4,4,,5。我们可以看到,这些数中,1,5的数量最少,2最多,其次是3,4。根据比例,1,5所占比例最小,2最多。所以,2在这个数列中的权重最大,1,5最小;放到图像中亦然。

代码如下

        int count=0;
	double *p=new double[256];
	double *per=new double[256];
	for(int i=0;i!=256;++i)
		p[i]=0;
	int *arr=new int[256];
	for(int i=0;i!=256;++i)
		arr[i]=0;

        for(int i=0;i!=in.rows;++i)
	for(int j=0;j!=in.cols;++j)
	arr[in.at<uchar>(i,j)]++;

	for(int i=0;i!=256;++i)
	per[i]=double(arr[i])/double(in.cols*in.rows);

	for(int i=0;i!=256;++i)
	for(int j=i;j>=0;--j)
	p[i]+=per[j];

	for(int i=0;i!=in.rows;++i)
	for(int j=0;j!=in.cols;++j)
	in.at<uchar>(i,j)=uchar(255*p[in.at<uchar>(i,j)]);

  这个方法的效果,和OpenCV提供的函数的效果差别不大。这个方法可以明显的提升图像的对比度,如图所示

这是原图转灰度之后的图像,我们只能依稀看到这是个什么东西,对比度实在堪忧。让我们看一下直方图均衡化之后的效果:

对比度确实高了不少,这个效果我们还是可以接受的。

posted @ 2015-08-07 18:42  你猜你猜啊  阅读(433)  评论(0编辑  收藏  举报