一起自学SLAM算法:3.2 图像滤波

  连载文章,长期更新,欢迎关注:


写在前面

第1章-ROS入门必备知识

第2章-C++编程范式

第3章-OpenCV图像处理

        3.1 认识图像数据

        3.2 图像滤波

        3.3 图像变换

        3.4 图像特征点提取

...

更多精彩内容,持续更新中......


大家如有任何技术问题,欢迎加入QQ技术群(117698356),进群一起交流讨论

通过上面的学习,已经知道图像是由一个个像素点组成的,处理图像就是处理这些像素点。但是需要注意的是,图像中的像素之间的关联性是重要的信息,不能完全把像素点割裂开来,这一点也正是众多图像算法的出发点。这里就通过图像滤波,来具体理解像素之间的这种关联性。图像滤波的目的是在尽量保留图像特征的条件下,过滤掉图像中的噪声,其直接影响到后续图像识别、分析等算法的效果。

3.2.1 线性滤波

关于图像的线性滤波过程,如图3-2所示,滤波器h(x,y)为一个加权系数的窗,利用窗对图像中的像素f(x,y)进行加权求和,结果g(x,y)就是滤波输出值,窗口滑过图像的所有像素,就能实现对所有像素的滤波。窗口在图像上的滑动过程,也称作卷积,用符号*表示。当然,窗口的取值和尺寸可以根据需要选择,这样就可以实现不同的滤波算法。最常用的是均值滤波和高斯滤波。

一起自学SLAM算法:3.2 图像滤波_第1张图片

图3-2  线性滤波原理

 均值滤波器的窗h(x,y)由均匀分布的系数构成,具体表达式如式3-1所示,其中width和height分别是窗的宽和高。

 

高斯滤波器的窗h(x,y)由二维高斯分布的系数构成,具体表达式如式(3-2)所示,其中u_{x}u_{y}是二维高斯分布的均值,这里假定二维分布是独立的,协方差退化成方差,\sigma _{x}^{2}\sigma _{y}^{2}是二维高斯分布的方差。

 

虽然均值滤波和高斯滤波的数学运算是比较复杂的,但是OpenCV对其做了很好的封装实现,直接调用函数就行了。均值滤波由blur函数实现,函数原型如下:

void blur(InputArray src,
            OutputArray dst,
            Size ksize,
            Point anchor=Point(-1,-1),
            int borderType=BORDER_DEFAULT)

高斯滤波由GaussianBlur函数实现,函数原型如下:

void GaussianBlur(InputArray src,
                      OutputArray dst,
                      Size ksize,
                      double sigmaX,
                      double sigmaY=0,
                      int borderType=BORDER_DEFAULT)

均值滤波操作起来非常简单,但给图像去噪的同时也破坏了其细节信息,使图像变得模糊不清,所以去噪效果并不好。高斯滤波虽然计算起来复杂一点,但是对图像中的高斯噪声有非常好的滤除效果,并且高斯噪声是普遍存在的,所以高斯滤波被广泛地应用在图像处理中,高斯滤波通常也称高斯平滑或高斯模糊。

3.2.2 非线性滤波

有些图像的噪声,比如椒盐噪声,使用非线性滤波会有更好的效果。在线性滤波中,利用窗对图像中的像素进行加权求和。非线性滤波中,窗的运算不是进行简单的加权求和,而是进行一些特殊的运算,比如求中值等。这里介绍两种常用的非线性滤波算法,中值滤波和双边滤波。

1)中值滤波,是取窗内的像素中值作为滤波输出值。中值滤波依靠的是排序法,用中值来近似真实值,能有效去除孤立的噪声点。

2)双边滤波,会复杂一点。先说说前面讲过的高斯滤波,窗口中的加权系数为二维高斯分布,高斯函数的取值只与空间位置有关。与高斯滤波不同的是,双边滤波中窗口的加权系数同时跟空间位置和像素值相似度有关,这样能保留细节信息的同时去除掉噪声。双边滤波的窗h(x,y,m,n)的系数分布由空间系数q(x,y,m,n)和像素值相似度系数r(x,y,m,n)相乘得到,具体表达式如式3-3所示。

 而滤波输出值g(x,y)并不是直接加权求和得来的,而是按式(3-4)所示求得。

 虽然中值滤波和双边滤波的数学运算是比较复杂的,但是OpenCV对其做了很好的封装实现,直接调用函数就行了。均值滤波由medianBlur函数实现,函数原型如下:

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

双边滤波由bilateralFilter函数实现,函数原型如下:

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

中值滤波能很好的去除椒盐噪声,双边滤波能保留细节的同时去除噪声。结合实际场景,合理的选择滤波算法能达到意想不到的效果。

3.2.3 形态学滤波

形态学滤波是基于形状的图像处理方法,OpenCV中最基本的形态学操作是膨胀(dilate)和腐蚀(erode)。膨胀是求局部最大值的操作,腐蚀则与之相反,腐蚀是求局部最小值的操作,如图3-3所示。

 图3-3  形态学滤波原理

膨胀就是求局部最大值的操作,图像A与操作核B进行卷积,在操作核B的覆盖下取区域中的最大值作为输出结果,输出结果的位置由操作核B的锚点决定,具体表达式如式3-5所示。选择不同形状和尺寸的操作核,可以得到不同的滤波效果。

 腐蚀就是求局部最小值的操作,图像A与操作核B进行卷积,在操作核B的覆盖下取区域中的最小值作为输出结果,输出结果的位置由操作核B的锚点决定,具体表达式如式(3-6)所示。选择不同形状和尺寸的操作核,可以得到不同的滤波效果。

利用基本的膨胀和腐蚀操作组合,可以实现更多形态学滤波算法,比如开运算(open)、闭运算(close)、形态学梯度(morphgrad)、顶帽运算(tophat)和黑帽运算(blackhat)。

开运算就是先腐蚀后膨胀,具体表达式如式(3-7)所示。

 闭运算就是先膨胀后腐蚀,具体表达式如式(3-8)所示。

 形态学梯度就是膨胀图片与腐蚀图片的差值,具体表达式如式(3-9)所示。

 顶帽运算就是原图片与图片开运算的差值,具体表达式如式(3-10)所示。

 黑帽运算就是图片闭运算与原图片的差值,具体表达式如式(3-11)所示。

 形态学滤波的各种算法已经被封装到OpenCV的morphologyEx函数,直接调用就可以了。函数原型如下:

void morphologyEx(InputArray src,
                      OutputArray dst,
                      int op,
                      InputArray kernel,
                      Pointanchor=Point(-1,-1),
                      int iterations=1,
                      int borderType=BORDER_CONSTANT,
                      constScalar& borderValue=morphologyDefaultBorderValue())

其中,int op参数可以取不同的值,来选择执行不同的形态学滤波算法,具体可选取值如下所示。

  • MORPH_DILATE:膨胀;
  • MORPH_ERODE:腐蚀;
  • MORPH_OPEN:开运算;
  • MORPH_CLOSE:闭运算;
  • MORPH_GRADIENT:形态学梯度;
  • MORPH_TOPHAT:顶帽运算;
  • MORPH_BLACKHAT:黑帽运算。

参考文献

【1】 张虎,机器人SLAM导航核心技术与实战[M]. 机械工业出版社,2022.

你可能感兴趣的:(一起自学SLAM算法,计算机视觉,c++,算法,自动驾驶,图像处理)