高斯模糊处理

借鉴:http://blog.sina.com.cn/s/blog_861912cd0101957x.html            http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html 


二维高斯曲面的公式

高斯半径(σ)对曲线形状的影响,σ越小,曲线越高越尖,σ越大,曲线越低越平缓。因此高斯半径越小,则模糊越小,高斯半径越大,则模糊程度越大。
模版矩阵的大小一般设为 ( 6*sigma+1 ) *( 6*sigma+1 )
模版搜索半径一般为	3σ 为合适
		3*3模版
			1 2 1
			2 4 2              /16
			1 2 1
			是对r=0.849时的一个近似
			guass radius=0.849000
			0.062467   0.125000   0.062467
			0.125000   0.250131   0.125000
			0.062467   0.125000   0.062467
			int r= (f1(i - 1,j - 1) + f1(i - 1,j + 1) + f1(i + 1,j - 1) + f1(i + 1,j + 1) + (f1(i - 1,j) + f1(i,j - 1) + f1(i + 1,j) + f1(i,j + 1)) * 2 + f1(i,j) * 4 ) / 16;
			int g = (f2(i - 1, j - 1) + f2(i - 1, j + 1) + f2(i + 1, j - 1) + f2(i + 1, j + 1) + (f2(i - 1, j) + f2(i, j - 1) + f2(i + 1, j) + f2(i, j + 1)) * 2 + f2(i, j) * 4) / 16;
			int b = (f3(i - 1, j - 1) + f3(i - 1, j + 1) + f3(i + 1, j - 1) + f3(i + 1, j + 1) + (f3(i - 1, j) + f3(i, j - 1) + f3(i + 1, j) + f3(i, j + 1)) * 2 + f3(i, j) * 4) / 16;
附 :源代码
//一般情况下模版为( 6*sigma+1 ) *( 6*sigma+1 )的矩阵。 注:sigma为高斯公式中的sigma
#define sigma  1 //高斯半径
const int  N = (int)(sigma * 3);
#define M_PI 3.1415926535898
double a[2 * N + 1][2 * N + 1];
d CMFCAppDlg::CalcMatrix() //计算权重矩阵
{
	/*
	高斯半径越小,则模糊越小,高斯半径越大,则模糊程度越大。我们将看到ps对高斯半径的范围定义是【0.1~250】
	半径为r时,取σ为 r/3 是一个比较合适的取值
	*/
	int i, j;
	double A = 1 / (2 * M_PI*sigma*sigma);
	double sum = 0.0;
	for (i = -1 * N; i <= N; i++)
	{
		for (j = -1 * N; j <= N; j++)
		{
			a[i + N][j + N] = A*exp((-1)*(i*i + j*j) / (2 * sigma * sigma));
		}
	}
	if (sum == 1.0)
		return;
	for (i = 0; i < 2 * N + 1; i++)
		for (j = 0; j < 2 * N + 1; j++)
			sum += a[i][j];//计算权值和
	/*归一化:
	首先求得权重总和,为了须让它们的权重之和等于1,
	还要把上面值还要分别除以这个和,得到最终的权重矩阵。
	若滤镜的权重总值不等于1,使用总值大于1的滤镜会让图像偏亮,小于1的滤镜会让图像偏暗。
	*/
	for (i = 0; i < 2 * N + 1; i++)
		for (j = 0; j < 2 * N + 1; j++)
			a[i][j] /= sum;

}
int CMFCAppDlg::f1(int x, int y)
{
	return GetRValue(img.GetPixel(x, y));
}
int CMFCAppDlg::f2(int x, int y)
{
	return GetGValue(img.GetPixel(x, y));
	
}
int CMFCAppDlg::f3(int x, int y)
{
	return GetBValue(img.GetPixel(x, y));
}
void CMFCAppDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	bStart = TRUE;
	CDC *pDC = GetDC();
	img.Load(_T("D:\\1.png"));
	//给图片做高斯处理
	int i, j;
	for(i = N;i<img.GetWidth()-N;i++)
		for (j = N; j < img.GetHeight()-N; j++)
		{
			/*
			3*3模版
			1 2 1
			2 4 2              /16
			1 2 1
			是对r=0.849时的一个近似
			guass radius=0.849000
			0.062467   0.125000   0.062467
			0.125000   0.250131   0.125000
			0.062467   0.125000   0.062467
			int r= (f1(i - 1,j - 1) + f1(i - 1,j + 1) + f1(i + 1,j - 1) + f1(i + 1,j + 1) + (f1(i - 1,j) + f1(i,j - 1) + f1(i + 1,j) + f1(i,j + 1)) * 2 + f1(i,j) * 4 ) / 16;
			int g = (f2(i - 1, j - 1) + f2(i - 1, j + 1) + f2(i + 1, j - 1) + f2(i + 1, j + 1) + (f2(i - 1, j) + f2(i, j - 1) + f2(i + 1, j) + f2(i, j + 1)) * 2 + f2(i, j) * 4) / 16;
			int b = (f3(i - 1, j - 1) + f3(i - 1, j + 1) + f3(i + 1, j - 1) + f3(i + 1, j + 1) + (f3(i - 1, j) + f3(i, j - 1) + f3(i + 1, j) + f3(i, j + 1)) * 2 + f3(i, j) * 4) / 16;
			*/
			CalcMatrix();
			/*
			下面两层for含义:
				例: a11  a12  a13
					 a21  a22  a23
					 a31  a32  a33
				此时N等于1
				由于权值矩阵中,a11, a13, a31, a33 的值是相等的,所以只需要把四个角落的计算一遍即可
			*/
			int r, g, b;
			r = g = b = 0;
			for (int m = 0; m < N + 1; m++)
			{
				for (int n = 0; n < N + 1; n++)
				{
					if (N - m != 0 && N - n != 0)
					{
			/*
				由于高斯分布是对称的,所以只要计算左上角,然后四个角落分别相乘自己对应的矩阵权值。
				如果列或者行与中点在同一直线上,则计算两次。
				中点计算一次。
			*/
						r += f1(i - (N - m), j - (N - n))*a[m][n];
						g += f2(i - (N - m), j - (N - n))*a[m][n];
						b += f3(i - (N - m), j - (N - n))*a[m][n];

						r += f1(i - (N - m), j + (N - n))*a[m][n];
						g += f2(i - (N - m), j + (N - n))*a[m][n];
						b += f3(i - (N - m), j + (N - n))*a[m][n];

						r += f1(i + (N - m), j - (N - n))*a[m][n];
						g += f2(i + (N - m), j - (N - n))*a[m][n];
						b += f3(i + (N - m), j - (N - n))*a[m][n];

						r += f1(i + (N - m), j + (N - n))*a[m][n];
						g += f2(i + (N - m), j + (N - n))*a[m][n];
						b += f3(i + (N - m), j + (N - n))*a[m][n];
					}
					else if (N - m == 0 && N - n == 0)//中心点
					{
						r += f1(i , j )*a[m][n];
						g += f2(i , j )*a[m][n];
						b += f3(i , j )*a[m][n];
					}
					else //与中心点在同一直线上的非中心点
					{//由于在同一直线上必然有 N-m 或 N-n 为0,所以只需要- -与 + +情况
						r += f1(i - (N - m), j - (N - n))*a[m][n];
						g += f2(i - (N - m), j - (N - n))*a[m][n];
						b += f3(i - (N - m), j - (N - n))*a[m][n];

						r += f1(i + (N - m), j + (N - n))*a[m][n];
						g += f2(i + (N - m), j + (N - n))*a[m][n];
						b += f3(i + (N - m), j + (N - n))*a[m][n];
					}
				}

			}
			img.SetPixel(i, j, RGB(r,g,b));//将经过模糊处理后的像素值赋值到相应的位置
			//更新进度信息
			m_progress.SetPos((i*j) / (double)(img.GetWidth()*img.GetHeight()) * 100);
		}
	//绘制处理完成后的新图像
	img.Draw(pDC->m_hDC, 0,0);
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值