图形算法与实战:1.滤波专题 (3)高斯滤波

3 高斯滤波

本文作者:图像与视觉InSight 行者 杨尚朋 转载请注明

目录

3 高斯滤波

3.1 处理效果展示

图像处理前后对比1

图像处理前后对比2

3.2 高斯滤波方法原理

3.2.1 高斯噪声

3.2.2 高斯函数简介

3.2.3 高斯滤波原理

3.3 代码展示


3.1 处理效果展示

图像处理前后对比1

图1 原图

图2 高斯噪声处理后的图像

图3 高斯滤波处理后的图像

图像处理前后对比2

图4 原图像2

图5 高斯噪声处理过的图像

图6 高斯滤波算法处理过的图像

3.2 高斯滤波方法原理

3.2.1 高斯噪声

所谓高斯噪声,是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声,形态如下:

只看图,还是觉得抽象,深入分析一下,得到下面这幅图。

如果,统计各噪声分量幅值,分析他们出现的频率,将会得到如下结果:

观察这种噪声幅值的频率分布,可看出该分布类似高斯函数,这就将该噪声与高斯函数联系了起来,统一称为高斯噪声。

3.2.2 高斯函数简介

高斯滤波方法来源于高斯函数,主要用于滤除高斯噪声及相关无关信息。

一维高斯函数的解析式,形如下式:

f(x)=ae^{-\frac{(x-b)^{^{2}}}{2c^{^{2}}}}

使用了不同的参数,生成了不同的图像:

二维高斯函数解析式,形如下式:

G(x,y)=\frac{1}{2\pi \sigma ^{2}} e^{-\tfrac{x^{^{2}}+y^{^{2}}}{2\sigma ^{^{2}}}}

二维高斯函数的图像,形如下图:

        高斯函数各参数意义:a 能调节函数的最大值,表示幅度大小;b 与函数对称轴位置直接相关,x = b 为函数的对称轴;c 则与函数的半峰全宽有关。

        高斯函数特点:高斯函数是一个典型的正态分布函数,有以下性质:在图像对称轴处,有最大值,随着自变量x向正轴或者负轴延伸,函数值变小,至无穷远处,逼近于0。

        这条性质非常好用。

3.2.3 高斯滤波原理

        高斯滤波的本质,是对邻域的线性卷积。

        很好懂吧,接下来咱们具体看。

        图像,在逻辑上,存储方式为二维矩阵,是离散变量(各灰度值)集合。对离散变量的卷积,仅仅是,核窗口内各元素乘以对应权值,再加到一起,和值作为核窗口中心元素的新值。

        你看,卷积也没什么难的。

        无论是均值滤波、高斯滤波、巴特沃斯滤波,还是Canny、Sobber算法求边缘,本质都是卷积运算,因为算子不同,所以才有了不同的效果。

        以 3×3 的卷积核为例。

        均值滤波的核窗口内,各元素权重都为1/(3×3)=1/9。滤波过程为,各元素都乘以1/9之后再相加,所得和值填入核窗口中心像素内,作为新值。新值的生成,需要邻域灰度值的参与,邻域灰度值对新值的大小施加了影响,影响的大小由权值确定,都是1/9。一个图像由width×height个点构成,滑动核窗口,对下一个点进行均值滤波操作,重复,直至达到迭代结束的条件。

        简单,对吧。

        高斯滤波呢?是一样的过程。只是,权值不再固定为1/9,而是交由二维高斯函数计算。权值计算完毕,核窗口内各灰度值乘以核窗口内对应权值,再加到一块,和值就作为核窗口中心点的灰度值。核窗口中心点的灰度值的确定,也引入了邻域灰度值的影响。

        滚动鼠标中键,稍微往前翻一下,一起来看流星雨二维高斯函数的解析式。公式右上角出现了 x^{^{2}}+y^{^{2}},该和项表征当前点距中心的远近程度,该项越大,距离越远,对应的二维高斯函数函数值越小,对应的权重值越小。

        下面展示完整的高斯滤波过程。

        设σ=1.5那么核窗口内各点的权重值为:

        上述表格中数字相加为0.4787147,需要将相加和设定为1,同比例缩放后,各点的权重为:

假设图像某区域各像素灰度值如下:

首先,各像素灰度值与对应权值相乘:

然后,将各和值加到中心点,完成了单点的高斯滤波:

最后,滑动核窗口,遍历处理各像素,直至达到迭代结束条件。

3.3 代码展示

 

 

 

//给图像添加高斯噪声
#include <cmath>
#include <limits>
#include <cstdlib>
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>

using namespace cv;
using namespace std;

double generateGaussianNoise(double m, double sigma);
Mat addGaussianNoise(Mat &srcImag);

int main()
{
	Mat srcImage = imread("C:\\Users\\SYYSP\\Desktop\\BLOG\\滤波专题\\高斯滤波\\cp.jpg");
	if (!srcImage.data)
	{
		cout << "未正确读入图片!" << endl;
		system("pause");
		return -1;
	}
	Mat dstImage = addGaussianNoise(srcImage);
	string sResultPath = "C:\\Users\\SYYSP\\Desktop\\BLOG\\滤波专题\\高斯滤波\\cpAddGaussianNoise.jpg";
	imwrite(sResultPath, dstImage);

	GaussianBlur(dstImage, dstImage, Size(7, 7), 0, 0);
	imwrite("C:\\Users\\SYYSP\\Desktop\\BLOG\\滤波专题\\高斯滤波\\cpRemoveGauss.jpg", dstImage);

	waitKey();
	return 0;
}

//生成高斯噪声
double generateGaussianNoise(double mu, double sigma)
{
	//定义小值
	const double epsilon = numeric_limits<double>::min();
	static double z0, z1;
	static bool flag = false;
	flag = !flag;
	//flag为假构造高斯随机变量X
	if (!flag)
		return z1 * sigma + mu;
	double u1, u2;
	//构造随机变量
	do
	{
		u1 = rand() * (1.0 / RAND_MAX);
		u2 = rand() * (1.0 / RAND_MAX);
	} while (u1 <= epsilon);
	//flag为真构造高斯随机变量
	z0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI*u2);
	z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI*u2);
	return z0 * sigma + mu;
}

//为图像添加高斯噪声
Mat addGaussianNoise(Mat &srcImag)
{
	Mat dstImage = srcImag.clone();
	int channels = dstImage.channels();
	int rowsNumber = dstImage.rows;
	int colsNumber = dstImage.cols*channels;
	//判断图像的连续性
	if (dstImage.isContinuous())
	{
		colsNumber *= rowsNumber;
		rowsNumber = 1;
	}
	for (int i = 0; i < rowsNumber; i++)
	{
		for (int j = 0; j < colsNumber; j++)
		{
			//添加高斯噪声
			int val = dstImage.ptr<uchar>(i)[j] +
				generateGaussianNoise(2, 0.8) * 32;
			if (val < 0)
				val = 0;
			if (val > 255)
				val = 255;
			dstImage.ptr<uchar>(i)[j] = (uchar)val;
		}
	}
	return dstImage;
}

用作实例的两幅图像均来自网络,侵删。

猜你喜欢

转载自blog.csdn.net/qq_32391345/article/details/106724610