图像处理系列——直方图统计算法

Posted nanke_yh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图像处理系列——直方图统计算法相关的知识,希望对你有一定的参考价值。

        直方图统计算法可指定对比度差的局部区域进行相应的提升,来实现图像局部区域的图像增强目的。直方图统计是根据模板大小内的像素邻域的均值、方差与全局的均值、方差的比较,来决定像素的操作。操作暗亮区域的图像只需要设置局部均值和全局均值的比值,而局部方差一般设置成小于全局的方差。

        使用直方图统计实现图像中的暗区域图像增强的具体步骤:

1、获得输入图像的平均灰度

        其中ri指灰度级为i的像元数量,p(ri)则为灰度级为i对应在直方图内的概率,得到的mG就是全图的平均灰度值了。

2、获得输入图像的方差

3、判断一个区域在点(x,y)处的局部平均灰度mSxy,局部标准差为σSxy,我们取k0,k1,k2,E,当

 

 时,我们把当前点看做较暗的点,此时我们将该像素点乘以E达到增大其灰度值效果,实现暗区域亮化目的。

4、对于与此相反的亮区域暗化,在满足下列关系情况下,再乘以一个小于1的比例系数E。

        根据上述步骤进行代码实现,并得到的试验结果如下:

/*function description:统计直方图实现图像增强
*
*input parameter:ImgTyp* srcImg         源图像
*                int size               滤波器尺寸
*				 double k0,double k1,double k2    阈值参数
*				 double E               亮度改变倍数
*				 bool dark              亮、暗区域确认        
*return:         
*                ImgTyp*     图像增强后的图像
******************************************************/
ImgTyp* HistogramFun::HistStatistic(ImgTyp* srcImg,int size,double k0,double k1,double k2,double E,bool dark)

	if (srcImg == NULL)
	
		cout<<"Error:影像为空值,读取失败"<<endl;
		return NULL;
	
	if (size%2 == 0)
	
		cout<<"滤波器尺寸不为奇数,请修改。"<<endl;
		return NULL;
	
	double mean_g = 0,sigam_g = 0;
	ImgTyp* copyImg = new ImgTyp[Width*Height];
	memcpy(copyImg,srcImg,sizeof(ImgTyp)*Width*Height);
	double* ImgGhist = CalImgHist(copyImg);
	//求均值和方差
	for (int l = 0; l < ColorLen; l++)
	
		mean_g += l * ImgGhist[l];
	
	for (int l = 0; l < ColorLen; l++)
	
		sigam_g += pow((l - mean_g),2)*ImgGhist[l];
	
	delete []ImgGhist;ImgGhist=NULL;
	int len = size*size;
	int localwidth = size/2;

	//创建局部窗口
	ImgTyp* Filter = new ImgTyp[len];
	memset(Filter,0,sizeof(ImgTyp)*len);
	//直方图
	double* ImgHist = new double[ColorLen];

	for (int i = localwidth;i < Height-localwidth;i++)
	
		for (int j = localwidth;j < Width-localwidth;j++)
			
			memset(ImgHist,0,sizeof(double)*ColorLen);
			for (int n = -localwidth;n < localwidth;n++)
			
				for (int m = -localwidth;m < localwidth;m++)
				
					Filter[(n+localwidth)*size+m+localwidth] = copyImg[(i+n)*Width+m+j];//赋值
					ImgHist[Filter[(n+localwidth)*size+m+localwidth]]++;//统计各个灰度级的数量
				
				
			//求邻域的均值和方差
			double mean_s = 0,sigam_s = 0;
			for (int l = 0; l < ColorLen; l++)
			
				ImgHist[l] = ImgHist[l] / len;//归一化求各个灰度级出现频率
				mean_s += l * ImgHist[l];
			
			for (int l = 0; l < ColorLen; l++)
			
				sigam_s += pow((l - mean_s),2)*ImgHist[l];
			

			if (dark)
			
				if (E < 1)
				
					cout<<"Error:暗区域操作,比例系数应大于1,不正确!"<<endl;
					delete []Filter;Filter=NULL;
					delete []ImgHist;ImgHist=NULL;
					delete []copyImg;copyImg=NULL;
					return NULL;
				
				if ((mean_s <= mean_g*k0) && (sqrt(sigam_s) <= k2*sqrt(sigam_g)) && (sqrt(sigam_s) >= k1*sqrt(sigam_g)))
				
					int target_value = E * copyImg[i*Width+j];

					if (target_value > ColorLen-1)
					
						target_value = ColorLen-1;
					
					copyImg[i*Width+j] = target_value;
				
			 
			else
			
				if (E > 1)
				
					cout<<"Error:亮区域操作,比例系数应小于1,不正确!"<<endl;
					delete []Filter;Filter=NULL;
					delete []copyImg;copyImg=NULL;
					delete []ImgHist;ImgHist=NULL;
					return NULL;
				
				if ((mean_s > mean_g*k0) && (sqrt(sigam_s) <= k2*sqrt(sigam_g)) && (sqrt(sigam_s) >= k1*sqrt(sigam_g)))
				
					int target_value = E * copyImg[i*Width+j];

					if (target_value > ColorLen-1)
					
						target_value = ColorLen-1;
					
					copyImg[i*Width+j] = target_value;
				
			
			
		
	
	delete []Filter;Filter=NULL;
	delete []ImgHist;ImgHist=NULL;
	return copyImg;

得到的测试结果:

原图

参数:

3,0.4,0.02,0.4,10,ture

参数:

7,0.4,0.02,0.4,10,ture

        从上结果可见,基于直方图统计算法的图像处理,能够有效的增强图像局部特征细节信息。滤波器尺寸越小,得到到细节越明显,但需要的计算消耗越大。同时其中涉及的k0,k1,k2,E等参数都过于依赖经验,或者需要从大量的重复试验中获取。参数的设置不同,得到的结果也会存在区别。

以上是关于图像处理系列——直方图统计算法的主要内容,如果未能解决你的问题,请参考以下文章

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

图像处理系列——直方图之灰度直方图(Image Histogram)

图像相似度检测算法

OpenCV 完整例程50. 图像增强—直方图统计量图像增强

MATLAB可视化实战系列(二十五)-MATLAB基于直方图的图像去雾

图像处理系列——局部直方图均衡化算法