OpenCV4入门教程052:线性滤波

索引地址:系列索引

图像滤波降噪介绍:图像噪声与去噪(图片滤波)

线性滤波

线性邻域滤波是一种常用的邻域算子;邻域算子(局部算子)是利用给定像素周围的像素值的决定此像素的最终输出值的一种算子。下面这个图解可以很好的说明这个过程:

邻域算子(局部算子)是利用给定像素周围的像素值的决定此像素的最终输出值的一种算子。而线性邻域滤波是一种常用的邻域算子,像素的输出值取决于输入像素的加权和,具体过程如下图。

邻域算子(局部算子)是利用给定像素周围的像素值的决定此像素的最终输出值的一种算子。而线性邻域滤波是一种常用的邻域算子,像素的输出值取决于输入像素的加权和,具体过程如下图:

filter

假设有6x6的图像像素点矩阵。卷积过程:6x6上面是个3x3的窗口,从左向右,从上向下移动,黄色的每个像个像素点值之和取平均值赋给中心红色像素作为它卷积处理之后新的像素值。每次移动一个像素格。

几种常见的线性滤波器:

(1)低通滤波器:允许低频率通过;
(2)高通滤波器:允许高频率通过;
(3)带通滤波器 :允许一定区域的频率通过;
(4)带阻滤波器 :阻止一定范围内的频率并且允许其他频率通过;
(5)全通滤波器 :允许所有频率通过,仅仅改变相位;
(6)陷波滤波器(Band stop filter):阻止一个狭窄频率范围通过的特殊带阻滤波器。

线性滤波器的原始数据与滤波结果是一种算术运算,即用加减乘除等运算实现,如均值滤波器(模板内像素灰度值的平均值)、高斯滤波器(高斯加权平均值)等。由于线性滤波器是算术运算,有固定的模板,因此滤波器的转移函数是可以确定并且是唯一的(转移函数即模板的傅里叶变换)。

方框滤波

boxFilter函数的作用是使用方框滤波(box filter)来模糊一张图片。

1
2
3
4
5
6
void boxFilter(InputArray src,
OutputArray dst,
int ddepth,
Size ksize,
Point anchor=Point(-1,-1),
boolnormalize=true,int borderType=BORDER_DEFAULT);

参数说明:

  • 第一个参数,InputArray类型的src,输入图像,即图像源,填Mat类对象即可,该函数对通道是独立处理的,且可以处理任意通道数的图片,处理图片深度应该是CV_8U,CV_16U,CV_16S,CV_32F,CV_64F之一;
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和原图像有一样的尺寸和类型;
  • 第三个参数,int类型的ddepth,输入图像的深度,-1代表用原图像深度,即src.depth();
  • 第四个参数,Size类型的ksize,内核的大小,一般用Size(w,h)的写法来表示内核的大小,例如Size(3,3)就是3×3的核大小;
  • 第五个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意有默认值Point(-1,-1),如果这个点坐标是负值的话就表示取核中心为锚点;
  • 第六个参数,bool类型的normalize,默认值为true,一个标识符,表示内核是否被其区域归一化了;
  • 第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT,一般不去管它。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc,char** argv) {
//载入原图
Mat image = imread("1.jpg");

//进行滤波操作
Mat out;
boxFilter(image, out, -1, Size(3, 3));

//显示
imshow("boxfilter-original", image);
imshow("boxfilter-result", out);

waitKey();
return(0);
}

测试效果:

boxfilter

均值滤波(Mean Filter)

均值滤波实际上就是用均值替代原图像中的各个像素值。

均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(假设我333 * 3,窗口,则以目标像素为中心的周围8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来(目标核的)像素值。对噪声图像特别是有大的孤立点的图像非常敏感,即使有极少数量点存在较大差异也会导致平均值的明显波动。

blur函数的作用是对输入的图像均值滤波后用dst输出。

1
2
3
4
5
void blur(InputArray src,
OutputArray dst,
Size ksize,
Point anchor=Point(-1,-1),
int borderType=BORDER_DEFAULT);

参数说明:

  • 第一个参数,InputArray类型的src,输入图像,即图像源,填Mat类对象即可,该函数对通道是独立处理的,且可以处理任意通道数的图片,处理图片深度应该是CV_8U,CV_16U,CV_16S,CV_32F,CV_64F之一;
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和原图像有一样的尺寸和类型;比如可以用Mat::clone,以源图片为模板来初始化得到如假包换的目标图;
  • 第三个参数,Size类型的ksize,内核的大小,一般用Size(w,h)的写法来表示内核的大小,例如Size(3,3)就是3×3的核大小;
  • 第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意有默认值Point(-1,-1),如果这个点坐标是负值的话就表示取核中心为锚点;
  • 第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT,一般不去管它。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char **argv) {
//载入原图
Mat image = imread("1.jpg");

//进行滤波操作
Mat out;
blur(image, out, Size(7, 7));

//显示
imshow("meanblur-original", image);
imshow("meanblur-result", out);

waitKey();
return (0);
}

效果如图:

meanfilter

高斯滤波(Gaussian Filter)

高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。

高斯滤波的具体操作:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。进行高斯滤波的通常原因是真实图像在空间内的像素是缓慢变化的,因此临近点的像素变化不会很明显,但是随机的两个点就可能形成很大的像素差。正是基于这一点,高斯滤波在保留信号的条件下减少噪声。遗憾的是,这种方法在接近边缘处就无效了,因此高斯滤波会破平边缘。但是,高斯平滑滤波器对于抑制服从正态分布的噪声仍然是非常有效的。

GaussianBlur函数的作用是用高斯滤波来模糊一张图片。

1
2
3
4
5
6
void GaussianBlur(InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY=0,
int borderType=BORDER_DEFAULT);

参数说明:

  • 第一个参数,InputArray类型的src,输入图像,即图像源,填Mat类对象即可,该函数对通道是独立处理的,且可以处理任意通道数的图片,处理图片深度应该是CV_8U,CV_16U,CV_16S,CV_32F,CV_64F之一;
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和原图像有一样的尺寸和类型;比如可以用Mat::clone,以源图片为模板来初始化得到如假包换的目标图;
  • 第三个参数,Size类型的ksize,内核的大小,一般用Size(w,h)的写法来表示内核的大小,ksize.width和ksize.height可以不同,但必须是正数&&奇数!!
  • 第四个参数,double类型的sigmaX,表示高斯核函数在X方向上的标准差;
  • 第五个参数,double类型的sigmaY,表示高斯核函数在Y方向上的标准差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都为零,那就由ksize.width和ksize.hight计算出来。为了结果的正确性着想,最好把第三个参数Size,第四个参数sigmaX,第五个参数sigmaY全部制定好;
  • 第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT,一般不去管它。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc,char** argv) {
//载入原图
Mat image = imread("1.jpg");

//进行滤波操作
Mat out;
GaussianBlur(image,out,Size(3,3),0,0);

//显示
imshow("gaussianblur-original", image);
imshow("gaussianblur-result", out);

waitKey();
return(0);
}

测试效果:

gaussianblur

线性滤波动态操作

通过滑动栏进行动态赋值内核大小

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//---------------------------------【头文件、命名空间包含部分】-------------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#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,g_dstImage3;//存储图片的Mat类型
int g_nBoxFilterValue=3; //方框滤波参数值
int g_nMeanBlurValue=3; //均值滤波参数值
int g_nGaussianBlurValue=3; //高斯滤波参数值


//-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
//四个轨迹条的回调函数
static void on_BoxFilter(int, void *); //均值滤波
static void on_MeanBlur(int, void *); //均值滤波
static void on_GaussianBlur(int, void *); //高斯滤波


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

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

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


//=================【<1>方框滤波】==================
//创建窗口
namedWindow("1-boxFilter", 1);
//创建轨迹条
createTrackbar("内核值:", "1-boxFilter", &g_nBoxFilterValue, 40, on_BoxFilter);
on_BoxFilter(g_nBoxFilterValue, 0);
//================================================

//=================【<2>均值滤波】==================
//创建窗口
namedWindow("2-meanBlur", 1);
//创建轨迹条
createTrackbar("内核值:", "2-meanBlur",&g_nMeanBlurValue, 40,on_MeanBlur );
on_MeanBlur(g_nMeanBlurValue,0);
//================================================

//=================【<3>高斯滤波】=====================
//创建窗口
namedWindow("3-gaussianBlur", 1);
//创建轨迹条
createTrackbar("内核值:", "3-gaussianBlur",&g_nGaussianBlurValue, 40,on_GaussianBlur );
on_GaussianBlur(g_nGaussianBlurValue,0);
//================================================


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

//按下“q”键时,程序退出
while(char(waitKey(1)) != 'q') {}

return 0;
}


//-----------------------------【on_BoxFilter( )函数】------------------------------------
// 描述:方框滤波操作的回调函数
//-----------------------------------------------------------------------------------------------
static void on_BoxFilter(int, void *)
{
//方框滤波操作
boxFilter( g_srcImage, g_dstImage1, -1,Size( g_nBoxFilterValue+1, g_nBoxFilterValue+1));
//显示窗口
imshow("1-boxFilter", g_dstImage1);
}


//-----------------------------【on_MeanBlur( )函数】------------------------------------
// 描述:均值滤波操作的回调函数
//-----------------------------------------------------------------------------------------------
static void on_MeanBlur(int, void *)
{
//均值滤波操作
blur( g_srcImage, g_dstImage2, Size( g_nMeanBlurValue+1, g_nMeanBlurValue+1), Point(-1,-1));
//显示窗口
imshow("2-meanBlur", g_dstImage2);
}


//-----------------------------【ContrastAndBright( )函数】------------------------------------
// 描述:高斯滤波操作的回调函数
//-----------------------------------------------------------------------------------------------
static void on_GaussianBlur(int, void *)
{
//高斯滤波操作
GaussianBlur( g_srcImage, g_dstImage3, Size( g_nGaussianBlurValue*2+1, g_nGaussianBlurValue*2+1 ), 0, 0);
//显示窗口
imshow("3-gaussianBlur", g_dstImage3);
}

测试效果(内核大小为20):

dyna


OpenCV4入门教程052:线性滤波
https://blog.jackeylea.com/opencv/opencv-linear-filter/
作者
JackeyLea
发布于
2020年6月14日
许可协议