数字图像处理学习笔记(六)平均滤波,高斯滤波(C++语言)

参考文献:数字图像处理(第三版)(第四版)   美RafaelC.Gonzalez(拉斐尔C.冈萨雷斯)

参考博客:https://www.cnblogs.com/wangguchangqing/p/6407717.html

全代码地址:https://mp.csdn.net/postedit/100053767

 平均滤波与高斯滤波,他们都是低通滤波的一种(使图像模糊化,原理就是是相邻像素变化没那么剧烈,使你看到的相互邻接的像素就比较接近了)。我个人认为高斯滤波中心权重比较大,所以模糊效果相对来说不如均值滤波。网上的很多原理教程讲的真的很好。在下水平不够,只会用一句简单的话来说,从数学角度,其实就是拿卷积内核,对每个像素做卷积运算。那么就涉及到几个步骤。

步骤一:内核的产生

这个非常简单,平均滤波就是用1.0除总大小就行。(注意1.0,浮点数)

for(int i=0;i<kernel_side_length;++i)
		for (int j = 0; j < kernel_side_length; ++j)
		{
			kernel[i][j] =1.0/(kernel_side_length*kernel_side_length);
			//printf("% f", kernel[i][j]);
		}

高斯滤波,这个也不难,如果你不去推高斯分布公式的话。简单说一下就是,归一化的高斯分布,这是个权重问题。还是看上文的播客吧。不建议直接代工式产生内核,还是大概查一下资料。

void Bmp::produce_gauss_martix(double **gauss_martix,const int kernel_side_length,const double variance)const
{
	double index;
	double sum=0.0;
	index=1.0/(2*PI*variance);
	for(int i=0;i<kernel_side_length;++i)
		for(int j=0;j<kernel_side_length;++j)
		{
			gauss_martix[i][j]=index*exp((-1.0)*((i-kernel_side_length/2)*(i-kernel_side_length/2)+(j-kernel_side_length/2)*(j-kernel_side_length/2))/2*variance);
			sum += gauss_martix[i][j];
		}//代高斯分布公式
	for (int i = 0; i < kernel_side_length; ++i)
		for (int j = 0; j < kernel_side_length; ++j)
		{
			gauss_martix[i][j] /=sum;
		}//归一化
}

步骤二:零扩展

有点像迷宫老鼠的思想,比如你(0,0)这个位置的像素,没有邻居,拿卷积内核怎么卷积呢?这时候就往外拓展n圈层0,这个n圈层,是根据你的内核大小来的。比如如果你5x5的内核,那你就拓展两层0。(这里就是说你要开辟一段新的内存空间了)这里要提醒一下对外圈赋值0的问题,最简单粗暴的方法是先把申请的空间元素全部弄成0,然后再填像素。我没这么干,然后调试了好久。(注意要找映射关系,你可以拿笔画画,也可边调试边推)

空间申请:

	pixel_zero=new byte**[heigth+kernel_side_length-1];
	for(int i=0;i< heigth+kernel_side_length-1;++i)
		pixel_zero[i]=new byte*[width+kernel_side_length-1];
	for(int i=0;i< heigth+kernel_side_length-1;++i)
		for(int j=0;j< width+kernel_side_length-1;++j)
			pixel_zero[i][j]=new byte[byte_count];//为补0像素申请空间

补0:

void Bmp::supply_zero(byte ***pixel_zero,const int kernel_side_length)const
{
	for(int i=0;i<heigth+ kernel_side_length-1;++i)
	{
		for(int j=0;j<kernel_side_length/2;++j)
			for(int k=0;k<byte_count;++k)
			{
				pixel_zero[i][j][k]=0;
			}
	}//左边列
	for(int i=0;i<heigth+kernel_side_length - 1;++i)
	{
		for(int j=width+ kernel_side_length / 2;j<width+kernel_side_length-1;++j)
			for(int k=0;k<byte_count;++k)
			{
				//printf("%d\n",j);
				pixel_zero[i][j][k]=0;
			}
	}//右边列
	for(int i=0;i<width + kernel_side_length - 1;++i)
	{
		for(int j=0;j<kernel_side_length/2;++j)
			for(int k=0;k<byte_count;++k)
			{
				pixel_zero[j][i][k]=0;
			}
	}//上边行.注意j代表行
	for(int i=0;i<width + kernel_side_length - 1;++i)
	{
		for(int j=heigth+ kernel_side_length / 2;j<heigth+kernel_side_length-1;++j)
			for(int k=0;k<byte_count;++k)
			{
				pixel_zero[j][i][k]=0;
			}
	}//下边行.注意j代表行
	for(int i=0;i<heigth;++i)
		for (int j = 0; j < width; ++j)
			for(int k=0;k<byte_count;++k)
			{
				pixel_zero[i+kernel_side_length/2][j+ kernel_side_length / 2][k]=pixel[i][j][k];
			}//为0扩展像素矩阵赋值
}

步骤三:卷积运算

卷积运算,就是把一堆乘法加起来。(你要特别注意,RGB是三通道的,你要分开来算)。

void Bmp::convolution (byte***pixel_zero,double **kernel,const int kernel_side_length)const
{
	double red_sum;
	double green_sum;
	double blue_sum;
	for(int i=0;i<heigth;++i)
		for (int j = 0; j < width;++j)
			{
				red_sum=green_sum=blue_sum=0;
				for(int m=0;m<kernel_side_length;++m)
				{
					for(int n=0;n<kernel_side_length;++n)
					{
						red_sum+=kernel[m][n]*pixel_zero[i+m][j+n][0];
						green_sum+=kernel[m][n]*pixel_zero[i+m][j+n][1];
						blue_sum+=kernel[m][n]*pixel_zero[i+m][j+n][2];
					}
				}
				pixel_temp[i][j][0]=red_sum;
				pixel_temp[i][j][1]=green_sum;
				pixel_temp[i][j][2]=blue_sum;
			}
}

展示:

均值滤波

原图像

9x9均值滤波后

9x9方差为1.0高斯滤波后

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值