图像处理(一):平滑滤波

平滑处理,有时也称模糊处理,是图像处理领域最常用的操作。平滑的目的主要是用来去除噪声。通常平滑操作是通过卷积操作(注:实际上是相关操作,后面的叙述对这两个操作不加区分)完成。下面介绍几种常用的平滑滤波操作。

均值滤波

  • 均值滤波是最简单的一种滤波操作,每个被滤波像素通过它邻近像素均值计算得到。

  • 均值滤波的kernel如下:

高斯滤波

  • 高斯滤波的核是通过高斯函数构建,越靠近中心的像素的值越大,这也反映了图像空域间关系,越邻近的像素相关性越强。

  • 二维高斯函数如下:

中值滤波

  • 以kernel里像素的中值作为被滤波后像素的值。

  • 中值滤波法是一种非线性平滑技术。

  • 中值滤波法对消除椒盐噪音非常有效。

双边滤波

  • 上面的滤波方法在平滑图像时不仅会平滑噪声,往往还会模糊图像边缘。这是由于它们构造kernel时只用了空间位置信息。

  • 双边滤波构造kernel不仅使用空间位置信息,还会使用颜色信息。

在opencv里提供了各种滤波器的调用接口,代码如下:

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
​
int main()
{
    namedWindow("Smoothing Demo", WINDOW_AUTOSIZE);
    Mat src = imread("G:\\opencvDemo\\lena.jpg");
    Mat blurImg;
    Mat gaussianImg;
    Mat medianImg;
    Mat bilteralImg;
    Mat boxImg;
    Mat filter2DImg;
​
    blur(src, blurImg, Size(5, 5));
    boxFilter(src, boxImg, -1, Size(5, 5), Point(-1, -1), true);
    GaussianBlur(src, gaussianImg, Size(5, 5),0,0);
    medianBlur(src, medianImg, 5);
    bilateralFilter(src, bilteralImg, 5, 10, 2.5);
    
    Mat kernal = Mat::ones(Size(5, 5), CV_8UC1);
    filter2D(src, filter2DImg, -1, kernal);
    
    //imshow("Smoothing Demo", bilteralImg);
    imwrite("blurImg55.jpg", blurImg);
    imwrite("boxImg55.jpg", boxImg);
    imwrite("gaussianImg55.jpg", gaussianImg);
    imwrite("medianImg55.jpg", medianImg);
    imwrite("bilteralImg55.jpg", bilteralImg);
    imwrite("filter2DImg55.jpg", filter2DImg);
    //waitKey(0);
​
    return 0;
}

实验效果:

原始图像lena.jpg如下:

均值滤波:

滤波函数:blur()

​
void cv::blur   (   InputArray  src,
                    OutputArray     dst,
                    Size    ksize,
                    Point   anchor = Point(-1,-1),
                    int     borderType = BORDER_DEFAULT 
                )   
    src   :  输入图像
    dst   :  输出图像
    ksize :  kernel尺寸
    anchor:  被滤波像素在kernel中的位置,默认Point(-1,-1)表示在kernel中心
    borderType:图像边界填充方式

下图分别是kernel大小为3x3和5x5时的实验效果:

高斯滤波:

滤波函数:GaussianBlur()

void cv::GaussianBlur   (   InputArray  src,
                            OutputArray     dst,
                            Size    ksize,
                            double  sigmaX,
                            double  sigmaY = 0,
                            int     borderType = BORDER_DEFAULT 
                            )   
    src   :  输入图像
    dst   :  输出图像
    ksize :  kernel尺寸
    sigmaX:  Gaussian kernel在X方向的标准差
    sigmaY:  Gaussian kernel在Y方向的标准差,如果sigmaY=0则sigmaY会被设为和sigmaX相等。如果sigmaX和sigmaY都为0,则它们会根据ksize.width和ksize.height计算得出。
    borderType:图像边界填充方式

下图分别是kernel大小为3x3和5x5时的实验效果:

中值滤波:

滤波函数:medianBlur()

void cv::medianBlur (   InputArray  src,
                        OutputArray     dst,
                        int     ksize 
                        )   
    src   :  输入图像
    dst   :  输出图像
    ksize :  kernel尺寸

下图分别是kernel大小为3x3和5x5时的实验效果:

双边滤波:

函数:bilateralFilter()

void cv::bilateralFilter    (   InputArray  src,
                                OutputArray     dst,
                                int     d,
                                double  sigmaColor,
                                double  sigmaSpace,
                                int     borderType = BORDER_DEFAULT 
                                )   
    src   :  输入图像
    dst   :  输出图像
    d     :  计算滤波时邻域像素的直径,如果非正数将通过sigmaSpace计算得到。
    sigmaColor:颜色空间的影响因子。
    sigmaSpace:空域的影响因子。
    borderType:图像边界填充方式

下图分别是kernel大小为3x3和5x5时的实验效果:

补充:

下面补充两个滤波函数:

boxFilter()filter2D()

1、boxFilter()

void cv::boxFilter  (   InputArray  src,
                        OutputArray     dst,
                        int     ddepth,
                        Size    ksize,
                        Point   anchor = Point(-1,-1),
                        bool    normalize = true,
                        int     borderType = BORDER_DEFAULT 
                        )   
    normalize = true时,计算结果和均值滤波相同
    normalize = false时,滤波后像素值为kernel内像素值的和

kernel如下:

下图是normalize = false,ksize为3x3时的结果:

2、filter2D()

void cv::filter2D   (   InputArray  src,
                        OutputArray     dst,
                        int     ddepth,
                        InputArray  kernel,
                        Point   anchor = Point(-1,-1),
                        double  delta = 0,
                        int     borderType = BORDER_DEFAULT 
                        )   
    kernel是要使用的滤波核,可以自己根据需求随意构建

下图构建了一个3x3全1的滤波核,可以验证结果与上图相同:

小结

以上便是平滑滤波的基本内容,关键在于滤波核的选择。

欢迎留言交流。

发布了87 篇原创文章 · 获赞 108 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/Dillon2015/article/details/95068685