opencv中常用的滤波方法:中值滤波、均值滤波、方框滤波、高斯滤波和双边滤波

图像滤波

图像的滤波目的有两个: 

  • 抽出图像的特征作为图像识别的特征模式; (特征提取)
  • 为适应图像处理的要求,消除图像数字化时所混入的噪声; (去噪)

图像的平滑处理: 平滑滤波是指低频增强的空间滤波技术。主要目的是模糊和消除噪音;

常用的5种图像平滑处理操作方法: 
1)方框滤波——boxFilter函数 
2)均值滤波——blur函数 
3)高斯滤波——GaussianBlur函数 
4)中值滤波——medianBlur函数 
5)双边滤波——bilateralFilter函数

前三种都属于线性滤波,后两种属于非线性滤波; 
滤波和模糊

  • 滤波是将信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施。
  • 模糊是滤波的一种。高斯滤波是指用高斯函数作为滤波函数的滤波操作。高斯模糊就是高斯低通滤波

方框滤波—boxFilter函数

函数原型

CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth,
                             Size ksize, Point anchor = Point(-1,-1),
                             bool normalize = true,
                             int borderType = BORDER_DEFAULT );

 官方解释:

@brief Blurs an image using the box filter.

The function smooths an image using the kernel:

\f[\texttt{K} = \alpha \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \end{bmatrix}\f]

where

\alpha = \begin{cases} \frac{1}{\texttt{ksize.width*ksize.height}} & \texttt{when } \texttt{normalize=true} \\1 & \texttt{otherwise}\end{cases}

Unnormalized box filter is useful for computing various integral characteristics over each pixel
neighborhood, such as covariance matrices of image derivatives (used in dense optical flow
algorithms, and so on). If you need to compute pixel sums over variable-size windows, use #integral.

@param src input image.
@param dst output image of the same size and type as src.
@param ddepth the output image depth (-1 to use src.depth()).
@param ksize blurring kernel size.
@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel center.
@param normalize flag, specifying whether the kernel is normalized by its area or not.
@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes. #BORDER_WRAP is not supported.
 

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

 均值滤波—blur函数

函数原型:

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

 @brief Blurs an image using the normalized box filter. 使用归一化放的方框滤波器模糊图片
The function smooths an image using the kernel:
\texttt{K} = \frac{1}{\texttt{ksize.width*ksize.height}} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \hdotsfor{6} \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \end{bmatrix}
The call `blur(src, dst, ksize, anchor, borderType)` is equivalent to `boxFilter(src, dst, src.type(), ksize,anchor, true, borderType)`.特殊的方框滤波
@param src input image; it can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize blurring kernel size.
@param anchor anchor point; default value Point(-1,-1) means that the anchor is at the kernel center.
@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes. #BORDER_WRAP is not supported.

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

高斯滤波—GaussianBlur函数 

函数原型:

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

@brief Blurs an image using a Gaussian filter.
The function convolves the source image with the specified Gaussian kernel. In-place filtering is supported.
@param src input image; the image can have any number of channels, which are processed independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be positive and odd. Or, they can be zero's and then they are computed from sigma.
@param sigmaX Gaussian kernel standard deviation in X direction.
@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height, respectively (see #getGaussianKernel for details); to fully control the result regardless of possible future modifications of all this semantics, it is recommended to specify all of ksize, sigmaX, and sigmaY.
@param borderType pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported.

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

基本原理

数值图像处理中,高斯滤波主要可以使用两种方法实现。

  • 一种是离散化窗口滑窗卷积
  • 另一种方法是通过傅里叶变化

最常见的就是滑窗实现,只有当离散化的窗口非常大,用滑窗计算量非常搭的情况下,可能会考虑基于傅里叶变化的实现方法。所以本文将主要介绍滑窗实现的卷积。

离散化窗口划船卷积时主要利用的是高斯核高斯核的大小为奇数,因为高斯卷积会在其覆盖区域的中心输出结果。常用的高斯模板有如下几种形式

高斯模板是通过高斯函数计算出来的,公式如下:

以3 × 3的高斯滤波器模板为例,以模板的中心位置为坐标原点进行取样。模板在各个位置的坐标,如下所示(x轴水平向右,y轴竖直向上)。

这样,将各个位置的坐标带入到高斯函数G中,得到的每个值按照位置排列,就得到了模板。

这样输出的模板有两种形式:

① 小数类型:直接计算得到的值,没有经过任何处理。

② 整数类型:将得到的值进行归一化处理,即将坐上叫的值归一化为1,其他每个系数都除以左上角的系数,然后取整。在使用整数模板时,则需要在模板的前面加一个系数,该系数为模板系数之和的倒数。

高斯滤波模板中最重要的参数就是高斯分布的标准差σ。它代表着数据的离散程度,如果σ较小,那么生成的模板中心系数越大,而周围的系数越小,这样对图像的平滑效果就不是很明显;相反,σ较大时,则生成的模板的各个系数相差就不是很大,比较类似于均值模板,对图像的平滑效果就比较明显。通过下面的一维高斯分布图也可验证上述观点。

 中值滤波-medianBlur()函数

函数原型:

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

@brief Blurs an image using the median filter.
The function smoothes an image using the median filter with the \f$\texttt{ksize} \times
\texttt{ksize}\f$ aperture. Each channel of a multi-channel image is processed independently.
In-place operation is supported.
@note The median filter uses #BORDER_REPLICATE internally to cope with border pixels, see #BorderTypes
@param src input 1-, 3-, or 4-channel image; when ksize is 3 or 5, the image depth should be CV_8U, CV_16U, or CV_32F, for larger aperture sizes, it can only be CV_8U.
@param dst destination array of the same size and type as src.
@param ksize aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ...ksize必须大于1,且为奇数

参数详解: 
第一个参数: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,9。

中值滤波(Median filter)是一种典型的非线性滤波技术,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值该方法在去除脉冲噪声、椒盐噪声的同时又能保留图像边缘细节。 
中值滤波在一定的条件下可以克服常见线性滤波器如最小均方滤波、方框滤波器、均值滤波等带来的图像细节模糊,而且对滤除脉冲干扰及图像扫描噪声非常有效,也常用于保护边缘信息, 保存边缘的特性使它在不希望出现边缘模糊的场合也很有用,是非常经典的平滑噪声处理方法。 可以在canny边缘检测之前使用。
缺点:中值滤波花费的时间是均值滤波的5倍以上。 

 双边滤波-bilateralFilter()函数

函数原型:

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

Applies the bilateral filter to an image.

The function applies bilateral filtering to the input image, as described in http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html

bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is very slow compared to most filters.

双边滤波器可以很好地减少不必要的噪声,同时保持边缘相当锐利。然而,与大多数过滤器相比它是非常慢的。

_Sigma values_: For simplicity, you can set the 2 sigma values to be the same. If they are small (\<10), the filter will not have much effect, whereas if they are large (\> 150), they will have a very strong effect, making the image look "cartoonish".

_Filter size_: Large filters (d \> 5) are very slow, so it is recommended to use d=5 for real-time applications, and perhaps d=9 for offline applications that need heavy noise filtering.

This filter does not work inplace.
@param src Source 8-bit or floating-point, 1-channel or 3-channel image.
@param dst Destination image of the same size and type as src .
@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive,it is computed from sigmaSpace.
@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting in larger areas of semi-equal color.
@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that farther pixels will influence each other as long as their colors are close enough (see sigmaColor). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is proportional to sigmaSpace.
@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes

第一个参数:InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。 
第二个参数:OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。 
第三个参数:int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。 
第四个参数:double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。 
第五个参数:double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。 
第六个参数:int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。

cv2.bilateralFilter() 能在保持边界清晰的情况下有效的去除噪音。但是这种操作与其他滤波器相比会比较慢。我们已经知道高斯滤波器是求中心点邻近区域像素的高斯加权平均值。这种高斯滤波器只考虑像素之间的空间关系,而不会考虑像素值之间的关系(像素的相似度)。所以这种方法不会考虑一个像素是否位于边界。因此边界也会被模糊掉,而这正不是我们想要。
  双边滤波同时使用空间高斯权重和灰度值相似性高斯权重。空间高斯函数确保只有邻近区域的像素对中心点有影响,灰度值相似性高斯函数确保只有与中心像素灰度值相近的才会被用来做模糊运算。所以这种方法会确保边界不会被模糊掉,因为边界处的灰度值变化比较大。 

双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。 
双边滤波器的好处是可以做边缘保存(edge preserving),一般过去用的维纳滤波或者高斯滤波去降噪,都会较明显地模糊边缘,对于高频细节的保护效果并不明显。双边滤波器顾名思义比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。 
在双边滤波器中,输出像素的值依赖于邻域像素值的加权值组合: 

使用代码:

void imgProc(Mat imgSrc, int i)
{
    
    if(i%2==0) i++;//在高斯滤波和中值滤波中,i不能为偶数
    Mat imgSrc = myImg;
    //不同共用一个变量,否则内存会崩溃
    //均值滤波
    Mat imgDst1 = imgSrc.clone ();
    blur(imgSrc,imgDst1,Size(i,i),Point(-1,-1));


    //高斯滤波
    Mat imgDst2 = imgSrc.clone ();

    GaussianBlur (imgSrc,imgDst2,Size(i,i),0,0);

    //中值滤波
    Mat imgDst3 = imgSrc.clone ();
    medianBlur (imgSrc,imgDst3,i);

    //双边滤波
    Mat imgDst4 = imgSrc.clone ();
    bilateralFilter (imgSrc,imgDst4,i,i*2,i/2);

    //方框滤波
    Mat imgDst5 = imgSrc.clone ();
    boxFilter (imgSrc,imgDst5,-1,Size(i,i));

}

 效果:

总结:

  1)均值模糊无法克服边缘像素信息丢失的缺陷,原因是均值滤波是基于平均权重的。

  2)高斯模糊部分克服了该缺陷,但无法完全避免,因为没有考虑像素值的不同。

  3)高斯双边模糊-是边缘保留额滤波方法,避免了边缘信息丢失,保留了图像轮廓不变,但容易导致高频噪声无法完全去除。

  4)在实际应用时,应根据噪声的特点、期望的图像和边缘特征等来选择合适的滤波器,这样才能发挥图像滤波的最大优点。

滤波器种类基本原理特点
均值滤波使用模板内所有像素的平均值代替模板中心像素灰度值易收到噪声的干扰,不能完全消除噪声,只能相对减弱噪声
中值滤波计算模板内所有像素中的中值,并用所计算出来的中值体改模板中心像素的灰度值对噪声不是那么敏感,能够较好的消除椒盐噪声,但是容易导致图像的不连续性
高斯滤波对图像邻域内像素进行平滑时,邻域内不同位置的像素被赋予不同的权值对图像进行平滑的同时,同时能够更多的保留图像的总体灰度分布特征

 参考文章

图像的各种滤波函数的介绍

OpenCV-图像平滑-卷积、平均、高斯模糊、中值模糊、双边滤波 卷积

OpenCV高斯滤波GaussianBlur

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值