本文为毛星云《OpenCV3编程入门》学习记录。
1. 平滑处理
平滑处理(smoothing)也称模糊处理(bluring),是一种简单且使用频率很高的图像处理方法。平滑处理的用途有很多,最常见的是用来减少图像上的噪点或者失真。在涉及到降低图像分辨率时,平滑处理是非常好用的方法。
2. 图像滤波与滤波器
图像滤波,指在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。
消除图像中的噪声成分叫作图像的平滑化或滤波操作。信号或图像的能量大部分集中在幅度谱的低频和中频段,而在较高频段,有用的信息经常被噪声淹没。因此一个能降低高频成分幅度的滤波器就能够减弱噪声的影响。
图像滤波的目的有两个:一个是抽出对象的特征作为图像识别的特能模式:另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。
而对滤波处理的要求也有两条:一是不能损坏图像的轮廓及边缘等重要信息;二是使图像清晰视觉效果好。
平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊:另一类是消除噪音。
空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的平均亮度值。邻域的大小与平滑的效果直接相关,邻域越大平滑的效果越好,但邻域过大,平滑也会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需合理选择邻域的大小生关于滤波器,一种形象的比喻是:可以把滤波器想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看我们得到的图像。
滤波器的种类有很多,在新版本的OpenCV中,提供了如下5种常用的图像平滑处理操作方法,它们分别被封装在单独的函数中,使用起来非常方便.
- 方框滤波—BoxBlur函数
- 均值滤波(邻域平均滤波)—Blur函数
- 高斯滤波—GaussianBlur函数
- 中值滤波——medianBlur函数
- 双边滤波——bilateralFilater函数
3. 线性滤波器简介
线性滤波器:线性滤波器经常用于剔除输入信号中不想要的频率或者从许多频率中选择一个想要的频率。
几种常见的线性滤波器如下。
- 低通滤波器:允许低频率通过;
- 高通滤波器:允许高倾率通过:
- 带通滤波器:允许一定范围频率通过;
- 带阻滤波器:阻止一定范围频率通过并且允许其他频率通过:
- 全通滤波器:允许所有频率通过,仅仅改变相位关系;
- 陷波滤波器(Band-StopFilter):阻止一个狄窄频率范围通过,是一种特殊带阻滤波器。
4. 滤波和模糊
关于滤波和模糊,大家往往在初次接触的时候会弄混淆:“一会儿说滤波,一会儿又说模糊,似乎不太清楚。”
不过,没关系,在这里,我们就来分析一下,为大家扫清障碍。
上文已经提到过,滤波是将信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施。
为了方便说明,就拿我们经常用的高斯滤波来作例了吧。滤波可分低通滤波和高通滤波两种:高斯滤波是指用高斯函数作为滤波函数的滤波操作,至于是不是模糊,要看是高斯低通还是高斯高通,低通就是模糊,高通就是锐化。
其实说白了是很简单的:
- 高斯滤波是指用高斯函数作为滤波函数的滤波操作:
- 高斯模糊就是高斯低通滤波。
5. 邻域算子与线性邻域滤波
邻域算子(局部算子)是利用给定像素周围的像索值的决定此像素的最终输出值的一种算子。而线性邻域滤波就是一种常用的邻域算子,像素的输出值取决于输入像素的权和,具体过程如下图所示。
邻域算子除了用于局部色调调整以外,还可以用于图像滤波,以实现图像的平滑和锐化,图像边缘增强或者图像噪声的去除。本节我们介绍的主角是线性邻域滤波算子,即用不同的权重去结合一个小邻域内的像素,来得到应有的处理效果。
图注:
邻域滤波(卷积)一一左边图像与中间图像的卷积产生右边图像。目标图像中蓝色标记的像素是利用原图像中红色标记的像素计算得到的。
线性滤波处理的输出像素值 g ( i , j ) g(i,j) g(i,j)是输入像素值 f ( i + k , j + I ) f(i+k,j+I) f(i+k,j+I)的加权和,如下
g ( i , j ) = ∑ k , I f ( i + k , j + I ) h ( k , I ) g(i,j)=\sum_{k,I}f(i+k,j+I)h(k,I) g(i,j)=∑k,If(i+k,j+I)h(k,I)
其中的 h ( k , I ) h(k,I) h(k,I),我们称其为“核”,是滤波器的加权系数,即滤波器的“滤波系数”。
上而的式子可以简单写作:
g = f ⨂ h g=f\bigotimes h g=f⨂h
其中f表示输入像素值,h表示加权系数“核”,g表示输出像素值。
在新版本的OpenCV中,提供了如下三种常用的线性滤波操作,它们分别被封装在单独的函数中,使用起来非常方便。
- 方框滤波—boxblur函数
- 均值滤波一一一blur函数
- 高斯滤波—GaussranBlur函数
下面我们来对它们进行一一介绍。
6. 方框滤波(boxFiIter)
方框滤波(boxFilter)被封装在一个名为boxblur的函数中,即boxblur函数的作用是使用方框滤波器(boxfilter)来模糊一张图片,从src输入,从dst输出。
函数原型如下。
C++:
void boxFilter(InputArray src,OutputArray dst,int ddepth,Size ksize,Point anchor=Point(-1,-1),bool normalize=true,int borderType=BORDER_DEFAULT)
参数详解如下。
- 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片。但需要注意,待处理的图片深度应该为CV8U、CV16U、CV_16S、CV_32F以及CV64F之一。
- 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
- 第三个参数,int*型的ddepth,输出图像的深度,-1代表使用原图深度,即src.depth()。
- 第四个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般用Size(w,h)来表示内核的大小,其中w为像素宽度,h为像素高度。Size(3,3)就表示33的核大小,Size(5,5)就表示55的核大小。
- 第五个参数,Point类型的anchor,表示锚点(即被平滑的那个点)。注意它有默认值Point(-1,-1),如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
- 第六个参数,bool类型的normalize,默认值为true,一个标识符,表示内核是否被其区域归一化(normalized)了。
- 第七个参数,类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它,
BoxFilter()函数方框滤波所用的核表示如下。
K = a [ 1 1 1 . . . 1 1 1 1 1 . . . 1 1 . . . . . . . . . . . . . . . . . . 1 1 1 . . . 1 1 ] K=a\begin{bmatrix} 1&1 &1 &... &1 &1 \\ 1&1 &1 &... &1 &1 \\ ...&... &... &... &... &... \\ 1&1 &1 &... &1 &1 \end{bmatrix} K=a⎣⎢⎢⎡11...111...111