通常,图像处理软件会提供"模糊"(blur)滤镜,使图片产生模糊的效果。
"模糊"的算法有很多种,其中有一种叫做"高斯模糊"(Gaussian Blur)。它将正态分布(又名"高斯分布")用于图像处理。
本文介绍"高斯模糊"的算法,你会看到这是一个非常简单易懂的算法。本质上,它是一种数据平滑技术(data smoothing),适用于多个场合,图像处理恰好提供了一个直观的应用实例。
一、高斯模糊的原理
所谓"模糊",可以理解成每一个像素都取周边像素的平均值。
上图中,2是中间点,周边点都是1。
"中间点"取"周围点"的平均值,就会变成1。在数值上,这是一种"平滑化"。在图形上,就相当于产生"模糊"效果,"中间点"失去细节。
显然,计算平均值时,取值范围越大,"模糊效果"越强烈。
上面分别是原图、模糊半径3像素、模糊半径10像素的效果。模糊半径越大,图像就越模糊。从数值角度看,就是数值越平滑。
接下来的问题就是,既然每个点都要取周边像素的平均值,那么应该如何分配权重呢?
如果使用简单平均,显然不是很合理,因为图像都是连续的,越靠近的点关系越密切,越远离的点关系越疏远。因此,加权平均更合理,距离越近的点权重越大,距离越远的点权重越小。
二、正态分布的权重
正态分布显然是一种可取的权重分配模式。
在图形上,正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。
计算平均值的时候,我们只需要将"中心点"作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。
三、高斯函数
上面的正态分布是一维的,图像都是二维的,所以我们需要二维的正态分布。
正态分布的密度函数叫做"高斯函数"(Gaussian function)。它的一维形式是:
其中,μ是x的均值,σ是x的方差。因为计算平均值的时候,中心点就是原点,所以μ等于0。
根据一维高斯函数,可以推导得到二维高斯函数:
有了这个函数 ,就可以计算每个点的权重了。
四、权重矩阵
假定中心点的坐标是(0,0),那么距离它最近的8个点的坐标如下:
更远的点以此类推。
为了计算权重矩阵,需要设定σ的值。假定σ=1.5,则模糊半径为1的权重矩阵如下:
这9个点的权重总和等于0.4787147,如果只计算这9个点的加权平均,还必须让它们的权重之和等于1,因此上面9个值还要分别除以0.4787147,得到最终的权重矩阵。
五、计算高斯模糊
有了权重矩阵,就可以计算高斯模糊的值了。
假设现有9个像素点,灰度值(0-255)如下:
每个点乘以自己的权重值:
得到
将这9个值加起来,就是中心点的高斯模糊的值。
对所有点重复这个过程,就得到了高斯模糊后的图像。如果原图是彩色图片,可以对RGB三个通道分别做高斯模糊。
六、边界点的处理
如果一个点处于边界,周边没有足够的点,怎么办?
一个变通方法,就是把已有的点拷贝到另一面的对应位置,模拟出完整的矩阵。
七、参考文献
* How to program a Gaussian Blur without using 3rd party libraries
图像处理中,常用的滤波算法有均值滤波、中值滤波以及高斯滤波等。
三种滤波器的对比
滤波器种类 基本原理 特点
均值滤波 使用模板内所有像素的平均值代替模板中心像素灰度值 易收到噪声的干扰,不能完全消除噪声,只能相对减弱噪声
中值滤波 计算模板内所有像素中的中值,并用所计算出来的中值体改模板中心像素的灰度值 对噪声不是那么敏感,能够较好的消除椒盐噪声,但是容易导致图像的不连续性
高斯滤波 对图像邻域内像素进行平滑时,邻域内不同位置的像素被赋予不同的权值 对图像进行平滑的同时,同时能够更多的保留图像的总体灰度分布特征
下面本文主要对高斯滤波展开详细的介绍。
基本原理
数值图像处理中,高斯滤波主要可以使用两种方法实现。一种是离散化窗口滑窗卷积,另一种方法是通过傅里叶变化。最常见的就是滑窗实现,只有当离散化的窗口非常大,用滑窗计算量非常搭的情况下,可能会考虑基于傅里叶变化的实现方法。所以本文将主要介绍滑窗实现的卷积。
离散化窗口划船卷积时主要利用的是高斯核,高斯核的大小为奇数,因为高斯卷积会在其覆盖区域的中心输出结果。常用的高斯模板有如下几种形式:
高斯模板是通过高斯函数计算出来的,公式如下:
以3 × 3的高斯滤波器模板为例,以模板的中心位置为坐标原点进行取样。模板在各个位置的坐标,如下所示(x轴水平向右,y轴竖直向上)。
这样,将各个位置的坐标带入到高斯函数G中,得到的每个值按照位置排列,就得到了模板。
这样输出的模板有两种形式:
① 小数类型:直接计算得到的值,没有经过任何处理。
② 整数类型:将得到的值进行归一化处理,即将坐上叫的值归一化为1,其他每个系数都除以左上角的系数,然后取整。在使用整数模板时,则需要在模板的前面加一个系数,该系数为模板系数之和的倒数。
例如:生成高斯核为3 × 3,σ = 0.8的模板
小数模板:
0.057118 0.12476 0.057118
0.12476 0.2725 0.12476
0.057118 0.12476 0.057118
整数模板:
1 2.1842 1
2.1842 4.7707 2.1842
1 2.1842 1
再经过四舍五入和添加系数得到最终结果:
从以上描述中我们可以看出,高斯滤波模板中最重要的参数就是高斯分布的标准差σ。它代表着数据的离散程度,如果σ较小,那么生成的模板中心系数越大,而周围的系数越小,这样对图像的平滑效果就不是很明显;相反,σ较大时,则生成的模板的各个系数相差就不是很大,比较类似于均值模板,对图像的平滑效果就比较明显。通过下面的一维高斯分布图也可验证上述观点。
GaussianBlur函数
函数原型:
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT);
参数详解如下:
src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
ksize,高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数(并不能理解)。或者,它们可以是零的,它们都是由sigma计算而来。
sigmaX,表示高斯核函数在X方向的的标准偏差。
sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
应用示例
#include "stdafx.h"
#include
int main()
{
// 创建两个窗口,分别显示输入和输出的图像
cv::namedWindow("Example2-5_in", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Example2-5_out", cv::WINDOW_AUTOSIZE);
// 读取图像,并用输入的窗口显示输入图像
cv::Mat img = cv::imread("C:\\Users\\Bello\\Desktop\\test.jpg", -1);
cv::imshow("Example2-5_in", img);
// 声明输出矩阵
cv::Mat out;
// 进行平滑操作,可以使用GaussianBlur()、blur()、medianBlur()或bilateralFilter()
// 此处共进行了两次模糊操作
cv::GaussianBlur(img, out, cv::Size(5, 5), 3, 3);
cv::GaussianBlur(out, out, cv::Size(5, 5), 3, 3);
// 在输出窗口显示输出图像
cv::imshow("Example2-5_out", out);
// 等待键盘事件
cv::waitKey(0);
// 关闭窗口并释放相关联的内存空间
cv::destroyAllWindows();
return 0;
}
运行结果:
平滑处理前 平滑处理后
https://blog.csdn.net/godadream/article/details/81568844看这个博客