OpenCV 中值滤波与双边滤波

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV 中值滤波与双边滤波相关的知识,希望对你有一定的参考价值。

线性滤波与非线性滤波

之前一篇文章说的方框滤波、均值滤波和高斯滤波都是线性滤波器的原始数据与滤波结果是一种线性的算术运算,即用加减乘除等运算实现,所以称之为线性滤波。

非线性滤波器的原始数据与滤波结果是一种逻辑关系,即通过比较一定邻域内的灰度值大小来实现的。下面介绍的中值滤波和双边滤波就是非线性滤波。

非线性滤波

中值滤波

中值滤波原理通过一张图就可以看明白:

简言之中值滤波就是把函数框(如图中的3 X 3)内的灰度值按顺序排列,然后中值取代函数框中心的灰度值。所以一般采用奇数点的邻域来计算中值,但如果像素点数为偶数,中值就取排序像素中间两点的平均值。

中值滤波在一定的条件下可以克服常见线性滤波器如方框滤波器、均值滤波等带来的图像细节模糊,而且对滤除脉冲干扰及图像扫描噪声非常有效,也常用于保护边缘信息, 保存边缘的特性使它在不希望出现边缘模糊的场合也很有用,是非常经典的平滑噪声处理方法。

但是中值滤波的缺点也很明显,因为要进行排序操作,所以处理的时间长,是均值滤波的5倍以上。

API medianBlur()

中值滤波在OpenCV中用medianBlur函数实现,下面是函数声明:

void medianBlur( 
	InputArray src, 
	OutputArray dst, 
	int ksize 
);

参数:

  • src:就是输入图像
  • dst:输出图像
  • ksize:核的大小

注意这里的ksize必须为正奇数1,3,5,7……否则程序会出错。

双边滤波

双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。

双边滤波器的好处是可以做边缘保存(edge preserving),一般用高斯滤波去降噪,会较明显地模糊边缘,对于高频细节的保护效果并不明显。双边滤波器顾名思义比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。

下图是双边滤波的原理示意图:

在双边滤波器中,输出像素的值依赖于邻域像素值的加权值组合:

而加权系数w(i,j,k,l)取决于空域核和值域核的乘积。
(i,j),(k,l)分别指两个像素点的坐标。
其中空域核表示如下(如图):

值域核表示为:

两者相乘后,就会产生依赖于数据的双边滤波权重函数:

d函数是根据像素距离选择权重,距离越近权重越大,这一点和方框滤波,高斯滤波方式相同。而r函数则是根据像素的差异来分配权值。如果两个像素值越接近,即使相距较远,也比差异大而距离近的像素点权重大。正是r函数的作用,使得边缘,即相距近但差异大的像素点的特性得以保留。

API bilateralFilter()

OpenCV中用bilateralFilter函数实现双边滤波。

函数原型:

void bilateralFilter( 
	InputArray src, 
	OutputArray dst, 
	int d,
	double sigmaColor, 
	double sigmaSpace,
	int borderType = BORDER_DEFAULT 
);

参数:

  • src:输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。
  • dst:即目标图像,需要和源图片有一样的尺寸和类型。
  • d:表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
  • sigmaColor:颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
  • sigmaSpace:坐标标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
  • borderType:用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。

案例:

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>  

using namespace cv;

int main() {

	Mat img = imread("./test2.jpg");	// 据说丑女经过双边滤波用有美颜效果哦,有兴趣的同学可以试试

	Mat median_img, bilateral_img;

	medianBlur(img, median_img, 10);
	bilateralFilter(img, bilateral_img, 25, 25 * 2, 25 / 2);

	namedWindow("中值滤波", CV_WINDOW_AUTOSIZE);
	imshow("中值滤波", median_img);

	namedWindow("双边滤波", CV_WINDOW_AUTOSIZE);
	imshow("双边滤波", bilateral_img);

	waitKey(0);
	return 0;
}

以上是关于OpenCV 中值滤波与双边滤波的主要内容,如果未能解决你的问题,请参考以下文章

opencv 图像平滑

OpenCV 图像处理 (线性滤波,非线性滤波 - 方框滤波均值滤波高斯滤波中值滤波,双边滤波)

opencv学习-均值滤波高斯滤波中值滤波双边滤波

OPENCV入门之六非线性滤波(中值滤波双边滤波)

OpenCV滤波器 龙门石窟篇Python-Open_CV系列(均值滤波器中值滤波器高斯滤波器双边滤波器)

opencv学习笔记15种图像滤波辨析:方框均值高斯中值双边