OpenCV-模糊

均值模糊(blur)

基本原理

使用模板内所有像素的平均值代替模板中心像素灰度值,一句话,就是邻域算子都是 1 / (M * N) 的一种特殊形式的邻域滤波,均值模糊为线性滤波。

缺点

它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪点。特别是椒盐噪点

函数原型

1
2
3
4
5
6
7
8
9
10
11
12
/* 
* src 输入图像,通道数不限,depth必须是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F
* dst 输出图像,size 与 type 与原始图像相同
* ksize 波模板 kernel 的尺寸,一般使用 Size(w, h)来指定,如 Size(3,3),且必须为奇数
* Point 结构元素的锚点位置,默认值value(-1,-1)表示锚点位于结构元素中心
* borderType 推断边缘类型
*/
void blur( InputArray src,
OutputArray dst,
Size ksize,
Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );

实例

1
2
3
Mat mat_base = imread("fish.png"); 
Mat mat_dst;
blur(mat_base, mat_dst, Size(7, 7));

中值模糊(medianBlur)

基本原理

把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。中值滤波对脉冲噪声(椒盐噪声)有良好的滤除作用,特别是在滤除噪声的同时,能够保护信号的边缘,使之不被模糊。这些优良特性是线性滤波方法所不具有的。此外,中值滤波的算法比较简单,也易于用硬件实现。

优点

算法简单,易于实现,能够很好的去处椒盐化

函数原型

1
2
3
4
5
6
7
8
/*
* src 输入图像,应为1、3或4通道图像,当ksize为3或5时,图像深度应为
CV_8U、CV_16U或CV_32F,对于较大的孔径尺寸,它只能是CV_8U
* dst 输出图像,size与type与原始图像相同
* ksize 孔径线性尺寸:必须是大于1的奇数,例如3、5、7…
void medianBlur( InputArray src,
OutputArray dst,
int ksize );

实例

1
2
3
4
5
Mat mat_base = imread("fish.png");
Mat mat_salt = mat_base.clone();
Mat mat_dst;
salt(mat_salt, 3000); //椒盐化
medianBlur(mat_base, mat_dst, 3); //中值模糊

高斯模糊(GaussianBlur)

高斯滤波模板中最重要的参数就是高斯分布的标准差σ。它代表着数据的离散程度,如果σ较小,那么生成的模板中心系数越大,而周围的系数越小,这样对图像的平滑效果就不是很明显;相反,σ较大时,则生成的模板的各个系数相差就不是很大,比较类似于均值模板,对图像的平滑效果就比较明显。

函数原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
* src 输入图像,图像可以有任意数量的通道,这些通道独立处理,但深度应为CV_8U、CV_16U、CV_16S、CV_32F或CV_64F
* dst 输出图像,size 与 type 与原始图像相同
* ksize 高斯核大小,ksize.width 和 ksize.height 可以不同,但它们都必须是正数和奇数。或者,它们可以是零,然后由西格玛计算
* sigmaX X 方向的高斯核标准差
* sigmaY Y 方向的高斯核标准差,如果 sigmaY 为零,则设置为等于 sigmaX,如果两个sigma均为零,则根据 ksize.width 和 ksize.height 计算它们
* borderType 推断边缘类型
*/
void GaussianBlur( InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY = 0,
int borderType = BORDER_DEFAULT );
1
2
3
sigmaX = \left(\frac {nx - 1}{2} \right) * 0.3 + 0.8,nx = ksize.width - 1

sigmaY = \left(\frac {ny - 1}{2} \right) * 0.3 + 0.8,ny = ksize.height - 1

实例

1
2
3
Mat mat_base = imread("fish.png");
Mat mat_dst;
GaussianBlur(mat_base, mat_dst, Size(5, 5), 3, 3); //高斯模糊

双边模糊(bilateralFilter)

目前我们了解的滤波器都是为了平滑图像,问题是有些时候这些滤波器不仅仅削弱了噪声,连带着把边缘也给磨掉了。为避免这样的情形 (至少在一定程度上 ), 我们可以使用双边滤波。

特点

类似于高斯滤波器,双边滤波器也给每一个邻域像素分配一个加权系数。 这些加权系数包含两个部分,第一部分加权方式与高斯滤波一样,第二部分的权重则取决于该邻域像素与当前像素的灰度差值。

所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素,这样就能对边缘附近的像素值予以保存,但是由于保存过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤除。

函数原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
* src 输入图像,8位或浮点、1通道或3通道图像
* dst 输出图像,size 与 type 与原始图像相同
* 过滤期间使用的每个像素邻域的直径。如果是非正数,它从 sigmaSpace 计算出来
* sigmaColor 颜色空间中滤波器的 sigma 值,参数值越大,表示像素邻域中的其他颜色将混合在一起,从而形成更大的半等色区域
* sigmaSpace 坐标空间中滤波器的 sigma值,参数值越大,意味着像素越远,只要它们的颜色足够接近,它们就会相互影响,当d>0时,它指定邻域大小,而不考虑 sigmaSpace。否则,d 是与 sigmaSpace成正比例的
* borderType 推断边缘类型
*/
void bilateralFilter( InputArray src,
OutputArray dst,
int d,
double sigmaColor,
double sigmaSpace,
int borderType = BORDER_DEFAULT );

实例

1
2
3
Mat mat_base = imread("fish.png");
Mat mat_dst;
bilateralFilter(mat_base, mat_dst, 5,3000,3000);