3.2 图像滤波
图像像素之间的关联性是重要的信息,不能完全把像素点割裂开来,这一点也正是众多图像算法的出发点。这里就通过图像滤波,来帮助大家具体理解像素之间的这种关联性。图像滤波的目的是在尽量保留图像特征的条件下,过滤掉图像中的噪声,其滤波效果直接影响到后续图像识别、分析等算法的效果。
3.2.1 线性滤波
图像的线性滤波过程,如图3-2所示,滤波器h(x, y)为一个加权系数的窗口,利用窗口对图像中的像素f(x, y)进行加权求和,结果g(x, y)就是滤波输出值,窗口滑过图像的所有像素就能实现对所有像素的滤波。窗口在图像上的滑动过程也称作卷积,用符号*表示。当然窗口的取值和尺寸可以根据需要选择,这样就可以实现不同的滤波算法。最常用的是均值滤波和高斯滤波(也称高斯平滑或高斯模糊)。
图3-2 线性滤波原理
均值滤波器的窗口h(x, y)由均匀分布的系数构成,如式(3-1)所示,其中width与height分别是窗口的宽和高。
高斯滤波器的窗口h(x, y)由二维高斯分布的系数构成,如式(3-2)所示。其中ux和uy是二维高斯分布的均值,这里假定二维分布是独立的,协方差退化成方差,是二维高斯分布的方差。
虽然均值滤波和高斯滤波的数学运算是比较复杂的,但是OpenCV对其进行了很好的封装实现,直接调用函数就行了。均值滤波由blur函数实现,高斯滤波由GaussianBlur函数实现。虽然均值滤波操作起来非常简单,但给图像去噪的同时也破坏了图像的细节信息,使图像变得模糊不清,所以去噪效果并不好。高斯滤波虽然计算起来复杂一点,但是对图像中的高斯噪声有非常好的滤除效果,并且高斯噪声是普遍存在的,所以高斯滤波使用更广泛。
3.2.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函数实现,双边滤波由bilateralFilter函数实现。中值滤波能很好地去除椒盐噪声,双边滤波能保留细节的同时去除噪声。结合实际场景,合理选择滤波算法能达到意想不到的效果。
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函数了,直接调用即可。我们可以通过morphologyEx函数的opt形参取值来选择执行不同的形态学滤波算法。