OpenCV4入门系列教程47:非线性滤波

入门系列索引:系列教程索引地址

上一篇:OpenCV4入门系列教程46:线性滤波

非线性滤波

中值滤波(Median bluring)

中值滤波法是一种基于排序统计理论的一种能有效抑制噪声的非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值,也就是将中心像素的值用所有像素值的中间值(不是平均值)替换。中值滤波通过选择中间值避免图像孤立噪声点的影响,对脉冲噪声、斑点噪声、椒盐噪声有良好的滤除作用,特别是在滤除噪声的同时,能够保护信号的边缘,使之不被模糊。这些优良特性是线性滤波方法所不具有的。此外,中值滤波的算法比较简单,也易于用硬件实现。所以,中值滤波方法一经提出后,便在数字信号处理领得到重要的应用。

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

参数说明:

  • 第一参数,InputArray类型的src,函数的输入参数,填1,3或者4通道的Mat类型的图像。当ksize为3或5的时候,图像深度需为CV_8U、CV_16U、CV_32F其中之一,而对于较大孔径尺寸的图片,只能是CV_8U;
  • 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数需要和源图片有一样的尺寸和类型,我们可以用Mat::clone,以源图片为模板来初始化得到如假包换的目标图;
  • 第三个参数,int类型的ksize,孔径的现行尺寸(aperture linear size),注意这个参数必须是大于1 的奇数(3、5、7、…)

双边滤波(Bilateral Filtering)

双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。双边滤波能够提供一种不会将边缘平滑掉的方法,但作为代价,需要更多的处理时间。与高斯滤波类似,双边滤波会依据每个像素及其领域构造一个加权平均值,加权计算包括两个部分,其中第一部分加权方式与高斯平滑中相同,第二部分也属于高斯加权,但不是基于中心像素点与其他像素点的空间距离之上的加权,而是基于其他像素与中心像素的亮度差值的加权。可以将双边滤波视为高斯平滑,对相似的像素赋予较高的权重,不相似的像素赋予较小的权重,也可用于图像分割之中。

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

函数原型

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

参数说明:

  • 参数1:输入图像;
  • 参数2:输出图像;
  • 参数3:过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
  • 参数4::颜色空间过滤器的sigma值,这个参数的值月大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。 (这个参数可以理解为值域核w_r的\sigma_r)
  • 参数5:坐标空间中滤波器的sigma值,如果该值较大,则意味着越远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace. (这个参数可以理解为空间域核w_d的\sigma_d)
  • 参数6:默认值BORDER_DEFAULT

动态参数测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//--------------------------------------【程序说明】-------------------------------------------
// 程序说明:《OpenCV3编程入门》OpenCV3版书本配套示例程序37
// 程序描述:非线性滤波综合示例
// 2014年11月 Created by @浅墨_毛星云
// 2014年12月 Revised by @浅墨_毛星云
//------------------------------------------------------------------------------------------------

//-----------------------------------【头文件包含部分】---------------------------------------
// 描述:包含程序所依赖的头文件
//----------------------------------------------------------------------------------------------
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

//-----------------------------------【命名空间声明部分】---------------------------------------
// 描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------
using namespace std;
using namespace cv;


//-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage,g_dstImage1,g_dstImage2;
int g_nMedianBlurValue=10; //中值滤波参数值
int g_nBilateralFilterValue=10; //双边滤波参数值

//-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
//轨迹条回调函数
static void on_MedianBlur(int, void *); //中值滤波器
static void on_BilateralFilter(int, void *); //双边滤波器

//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main( )
{
// 载入原图
g_srcImage = imread( "1.jpg", 1 );
if( !g_srcImage.data ) { printf("读取srcImage错误~! \n"); return false; }

//克隆原图到四个Mat类型中
g_dstImage1 = g_srcImage.clone( );
g_dstImage2 = g_srcImage.clone( );

//显示原图
imshow("0-original",g_srcImage);

//=================【<4>中值滤波】===========================
//创建窗口
namedWindow("1-medianblur", 1);
//创建轨迹条
createTrackbar("参数值:", "1-medianblur",&g_nMedianBlurValue, 50,on_MedianBlur );
on_MedianBlur(g_nMedianBlurValue,0);
//=======================================================


//=================【<5>双边滤波】===========================
//创建窗口
namedWindow("2-bilateralFilter", 1);
//创建轨迹条
createTrackbar("参数值:", "2-bilateralFilter",&g_nBilateralFilterValue, 50,on_BilateralFilter);
on_BilateralFilter(g_nBilateralFilterValue,0);
//=======================================================

//输出一些帮助信息
cout<<endl<<"\t运行成功,请调整滚动条观察图像效果~\n\n"
<<"\t按下“q”键时,程序退出。\n";
while(char(waitKey(1)) != 'q') {}

return 0;
}

//-----------------------------【on_MedianBlur( )函数】------------------------------------
// 描述:中值滤波操作的回调函数
//-----------------------------------------------------------------------------------------------
static void on_MedianBlur(int, void *)
{
medianBlur ( g_srcImage, g_dstImage1, g_nMedianBlurValue*2+1 );
imshow("1-medianblur", g_dstImage1);
}

//-----------------------------【on_BilateralFilter( )函数】------------------------------------
// 描述:双边滤波操作的回调函数
//-----------------------------------------------------------------------------------------------
static void on_BilateralFilter(int, void *)
{
bilateralFilter ( g_srcImage, g_dstImage2, g_nBilateralFilterValue, g_nBilateralFilterValue*2, g_nBilateralFilterValue/2 );
imshow("2-bilateralFilter", g_dstImage2);
}

dyna

下一篇:OpenCV4入门系列教程48:USM锐化