模糊又称平滑,是一种去噪手段,接下来我们会介绍均值模糊和高斯模糊。
均值模糊
我们会先创建一个卷积核,这个卷积核可以是3*3或者任意的x*x,如下图:
在创建完一个3*3卷积核后我们会将黄色格子和红色格子的像素值给加起来然后除以9(也就是卷积核里有多少个像素点就除以多少),这样我们就得出了平均值,然后将平均值赋给红色格子,这样我们就对一个像素完成了模糊处理。
所谓模糊就是平滑,只要让所有的像素值都趋于一个平均值就能达到平滑的效果了。接着我们就对下一个像素点进行同样的处理直到整张图片都完成处理。
openCV给出了均值模糊的API:
void blur( InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT );
src:输入图像
dst:输出图像
ksize:卷积核大小
Point anchor:锚点,最后得出的平均值所赋给的像素点坐标也就是上文所提到的红色格子,建议不要轻易改变这里的数值,默认数值为(-1,-1)
borderType: 用于推断图像外部边缘像素,有默认值BORDER_DEFAULT,这个参数是什么意思呢?就是我们在使用卷积核时是从第2行第2列开始的,那么问题来了第一行和第一列怎么办?难道我们就不管了?当然不可能,我们对边缘处理有以下几种办法:
- ① 对称处理,就是把已有的点拷贝到另一面的对应位置,模拟出完整的矩阵。
- ② 赋0,想象图像是无限长的图像的一部分,除了我们给定值的部分,其他部分的像素值都是0
- ③ 赋边界值,想象图像是无限制长,但是默认赋值的不是0而是对应边界点的值
示例
#include<opencv2/opencv.hpp> #include<stdc++.h> using namespace cv; using namespace std; int main() { Mat a, b; a = imread("D:\\壁纸\\带带大师兄.jpg"); if (!a.data) { cout << " 没有找到图片"; waitKey(0); return -1; } imshow("清晰的孙笑川", a); blur(a, b, Size(9, 9)); imshow("模糊的孙笑川", b); waitKey(0); return 0; }
运行结果如下:
高斯模糊
均值模糊就是通过求平均值来进行模糊操作,这样的结果会使我们最后得到的图像不够平滑,而且更加容易受到噪声的干扰。
而高斯模糊则是通过线性滤波方式进行去噪,通过权重的方式来进行平均值的计算,什么意思呢?让我们看下图:
图中的数字代表每个像素点的像素值,这是让我们引入一个公式:
这是二维高斯函数以此来表明在正态分布上每个像素点的权重,
通俗点讲就是越靠近锚点的权重越大,越远离锚点的权重越小。通过加权平均数我们可以得到更平滑的模糊图像。
openCV给出了高斯模糊的api:
void GaussianBlur( InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT );
src:输入图像
dst:输出图像
ksize:卷积核大小,这里我们要注意一下在使用高斯模糊时卷积核大小只能是奇数*奇数
sigmax:在X方向的标准差,通常情况下sigmax与sigmay的值是一样的,而且openCV允许在这两个值中填写0,这样openCV会自动算出每个点的权重。
sigmay:在Y方向的标准差
borderTypr:用于推断图像外部边缘像素,有默认值BORDER_DEFAULT。
示例
#include<opencv2/opencv.hpp> #include<stdc++.h> using namespace cv; using namespace std; int main() { Mat a, b; int height,width; a = imread("D:\\壁纸\\带带大师兄.jpg"); if (!a.data) { cout << " 没有找到图片"; waitKey(0); return -1; } imshow("清晰的孙笑川", a); GaussianBlur(a, b, Size(9, 9), 0, 0); imshow("模糊的孙笑川", b); waitKey(0); return 0; }
运行结果如下:
为了让各位对均值模糊和高斯模糊有个更直观的认识所以我展示一下均值模糊和高斯模糊的对比:
影流之主