opencv学习(五)线性滤波之方框滤波、均值滤波、高斯滤波

滤波的目的:

1、抽出对象的特征作为图像识别的特征模式

2、适应图像处理的要求,消除图像数字化时所混入的噪声

平滑滤波是低频增强的空间域滤波技术,一般用来模糊图像或者消除噪声

这里我们简单谈空间域的滤波处理,主要是把滤波器想象成一个包含加权系数的窗口,平滑是,进行加权平均,得到像素点的值

1、方框滤波之BoxBlur函数

opencv学习(五)线性滤波之方框滤波、均值滤波、高斯滤波_第1张图片

boxblur函数的作用是使用boxfilter(方框滤波器),从src输入,dst输出,如下:

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 );

各参数如下:

第一个参数、InputArray src:输入图像,Mat 类的对象

第二个参数、OutputArray dst:目标图像

第三个参数、int ddepth: 输入图像的深度,-1代表使用原图的深度

第四个参数、Size kize: 内核的大小,一般用Size(w,h)表示内核的大小

第五个参数、Point:默认值为(-1,-1)代表核的中心,其他的是需要被平滑的那个点

第六个参数、bool normalize:默认true。表示是否归一化,如果是的话,就相当于均值滤波

第七个参数、int borderType:这个不是很清楚,一般不管

2、均值滤波之blur函数

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

具体参数和1方框滤波一样

第一个参数、InputArray src:输入图像,Mat 类的对象

第二个参数、OutputArray dst:目标图像

第三个参数、Size kize: 内核的大小,一般用Size(w,h)表示内核的大小

第四个参数、Point:默认值为(-1,-1)代表核的中心,其他的是需要被平滑的那个点

3、高斯滤波

先简单谈一下关于高斯滤波,之前我转过一篇文章

关于高斯滤波器的核参数获取

想了解相关原理的可以看看

这里先简单提一下

高斯滤波函数为:

离散的高斯卷积核H: (2k+1)×(2k+1)维,其元素计算方法为:

       其中Sigma为方差,k确定核矩阵的维数,关于这两个取值,在下文进行分析。

opencv中,关于高斯函数,有有两个设置方差的参数,具体如下

opencv学习(五)线性滤波之方框滤波、均值滤波、高斯滤波_第2张图片

简单提了一个高斯函数,来具体看看Opencv是怎么实现的

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

第一个参数、InputArray src:输入图像,Mat 类的对象

第二个参数、OutputArray dst:目标图像

第三个参数、Size kize: 内核的大小,其中ksize.width金额ksize.height可以不同,但是必须是整数和奇数,或者0.腰要算sigma的

第四个参数、sigmaX:表示高斯核在X方向的标准偏差

第五个参数、sigmaY,表示高斯核在Y方向的标准偏差,如果为0,则设置为sigmaX,如果两个都是0,则有kisze的width和height计算出来

简单看一下个函数的使用情况吧,下面是一段小程序

#include "stdafx.h"

#include
using namespace cv;
using namespace std;


int main()
{
	Mat img = imread("F:/Digital-image-project/BMPimages/24-512-512.bmp");

	imshow("原图", img);
	Mat dstImg;

	boxFilter(img, dstImg, img.depth(), Size(5, 5));
	imshow("方框滤波", dstImg);

	blur(img, dstImg, Size(3, 3));
	imshow("均值滤波", dstImg);

	GaussianBlur(img, dstImg, Size(3, 3), 0,0);
	imshow("高斯滤波", dstImg);

	waitKey(0);
	return 0;
}

效果如下

opencv学习(五)线性滤波之方框滤波、均值滤波、高斯滤波_第3张图片

现在来看看方框滤波的源码

void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth,
                Size ksize, Point anchor,
                bool normalize, int borderType )
/*第一个参数、InputArray src:输入图像,Mat 类的对象

第二个参数、OutputArray dst:目标图像

第三个参数、int ddepth: 输入图像的深度,-1代表使用原图的深度

第四个参数、Size kize: 内核的大小,一般用Size(w,h)表示内核的大小

第五个参数、Point:默认值为(-1,-1)代表核的中心,其他的是需要被平滑的那个点

第六个参数、bool normalize:默认true。表示是否归一化,如果是的话,就相当于均值滤波

第七个参数、int borderType:这个不是很清楚,一般不管*/
{
    CV_INSTRUMENT_REGION()

    CV_OCL_RUN(_dst.isUMat() &&
               (borderType == BORDER_REPLICATE || borderType == BORDER_CONSTANT ||
                borderType == BORDER_REFLECT || borderType == BORDER_REFLECT_101),
               ocl_boxFilter3x3_8UC1(_src, _dst, ddepth, ksize, anchor, borderType, normalize))

    CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize))

    Mat src = _src.getMat();//复制原图的形参Mat数据到临时变量
    int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);//得到深度、通道数
    if( ddepth < 0 )//处理depth小于0的情况
        ddepth = sdepth;
    _dst.create( src.size(), CV_MAKETYPE(ddepth, cn) );//初始化目标图
    Mat dst = _dst.getMat();//复制目标图的形参Mat数据到临时变量
    if( borderType != BORDER_CONSTANT && normalize && (borderType & BORDER_ISOLATED) != 0 )//处理borederType不为BORDER_CONSTANT等其他情况
    {
        if( src.rows == 1 )
            ksize.height = 1;
        if( src.cols == 1 )
            ksize.width = 1;
    }

    Point ofs;
    Size wsz(src.cols, src.rows);
    if(!(borderType&BORDER_ISOLATED))//处理borederType不为
        src.locateROI( wsz, ofs );

    CALL_HAL(boxFilter, cv_hal_boxFilter, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn,
             ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
             anchor.x, anchor.y, normalize, borderType&~BORDER_ISOLATED);

    CV_OVX_RUN(true,
               openvx_boxfilter(src, dst, ddepth, ksize, anchor, normalize, borderType))

    CV_IPP_RUN_FAST(ipp_boxfilter(src, dst, ksize, anchor, normalize, borderType));

    borderType = (borderType&~BORDER_ISOLATED);

    Ptr f = createBoxFilter( src.type(), dst.type(),//重点来看这个函数吧,调用DilterEngine引擎,正式开始滤波操作,Ptr是只能分配动态指针的模板类
                        ksize, anchor, normalize, borderType );

    f->apply( src, dst, wsz, ofs );//
}

从上面我们可以看到FilterEngine引擎承担了很大的作用,关于这个引擎的具体实现,笔者截止目前也没有搞清楚,就不献丑了,有兴趣的同学可以多查查资料

看一下均值滤波的源码

void cv::blur( InputArray src, OutputArray dst,
           Size ksize, Point anchor, int borderType )
{
    CV_INSTRUMENT_REGION()

    boxFilter( src, dst, -1, ksize, anchor, true, borderType );
}

哈哈,是不是很简单,直接调用方框滤波就可以了,只不过第6个参数设置成true,即方框滤波的标准化操作

高斯滤波的源码暂时看不懂

你可能感兴趣的:(个人笔记,opencv3.4.1深入浅出)