opencv线性滤波:方框滤波,均值滤波,高斯滤波

学习浅墨大佬:教程

函数调用:

#include "ep_19.h"
using namespace std;
using namespace cv;

void ep_19()
{
	/*方框滤波
	*第一个参数,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,我们一般不去管它。

	void boxFilter(InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor = Point(-1, -1), boolnormalize = true, int borderType = BORDER_DEFAULT)
	*/
	Mat srcimg = imread("girl.jpg");
	Mat boximg;
	boxFilter(srcimg, boximg, -1, Size(3, 3), Point(-1, -1),0);
	namedWindow("源图像", WINDOW_AUTOSIZE);
	imshow("源图像", srcimg);
	namedWindow("方框滤波",WINDOW_AUTOSIZE);
	imshow("方框滤波",boximg);

	/*均值滤波
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
第三个参数,Size类型(对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,我们一般不去管它。
	void blur(InputArray src, OutputArraydst, Size ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT)

	*/
	Mat blurimg;
	blur(srcimg, blurimg, Size(3, 3));
	namedWindow("均值滤波", WINDOW_AUTOSIZE);
	imshow("均值滤波", blurimg);

	/*高斯滤波*/
	/*
	第一个参数,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,我们一般不去管它。
 C++: void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )
	*/
	Mat gaussimg;
	GaussianBlur(srcimg, gaussimg, Size(3, 3), 0, 0);
	namedWindow("高斯滤波", WINDOW_AUTOSIZE);
	imshow("高斯滤波", gaussimg);
	waitKey(0);                                      
}

源码解析:
文件路径:D:\opencv4.5.1\sources\modules\imgproc\src\box_filter.dispatch.cpp

void boxFilter(InputArray _src, OutputArray _dst, int ddepth,
               Size ksize, Point anchor,
               bool normalize, int borderType)
{
    CV_INSTRUMENT_REGION();

    CV_Assert(!_src.empty());

    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();//读入源图像到临时变量
    int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
	//定义int型临时变量,代表源图深度的sdepth,源图通道的引用cn
    if( ddepth < 0 )//如果用户输入的深度小于0,则采用源图深度
        ddepth = sdepth;
    _dst.create( src.size(), CV_MAKETYPE(ddepth, cn) );//使用上方获取的参数初始化目标图
    Mat dst = _dst.getMat();//拷贝目标图的形参Mat数据到临时变量,用于稍后的操作
//处理 borderType不为 BORDER_CONSTANT 且normalize为真的情况
    if( borderType != BORDER_CONSTANT && normalize && (borderType & BORDER_ISOLATED) != 0 )
    {
        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))
        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);
 //调用FilterEngine滤波引擎,正式开始滤波操作
    Ptr<FilterEngine> f = createBoxFilter( src.type(), dst.type(),
                        ksize, anchor, normalize, borderType );

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


其中,FilterEngine类是OpenCV关于图像滤波的主力军类,OpenCV图像滤波功能的核心引擎。各种滤波函数比如blur, GaussianBlur,到头来其实是就是在函数末尾处定义了一个Ptr类型的f,然后f->apply( src, dst )了一下而已。

这个类可以把几乎是所有的滤波操作施加到图像上。它包含了所有必要的中间缓存器。有很多和滤波相关的create系函数的返回值直接就是Ptr。比如cv::createSeparableLinearFilter(),

cv::createLinearFilter(),cv::createGaussianFilter(), cv::createDerivFilter(),

cv::createBoxFilter() 和cv::createMorphologyFilter().,这里给出其中一个函数的原型吧:
————————————————



Ptr<FilterEngine>createLinearFilter(int srcType, int dstType, InputArray kernel, Point_anchor=Point(-1,-1), double delta=0, int rowBorderType=BORDER_DEFAULT, intcolumnBorderType=-1, const Scalar& borderValue=Scalar() )
/**********************FilterEngine类注释********************************/
//文件路径:D:\opencv4.5.1\sources\modules\imgproc\src\filterengine.hpp
class FilterEngine
{
public:
    //! the default constructor默认构造函数
    FilterEngine();
    //! the full constructor. Either _filter2D or both _rowFilter and _columnFilter must be non-empty.
    //完整构造函数,Either _filter2D or both _rowFilter and _columnFilter必须为非空
    FilterEngine(const Ptr<BaseFilter>& _filter2D,
                 const Ptr<BaseRowFilter>& _rowFilter,
                 const Ptr<BaseColumnFilter>& _columnFilter,
                 int srcType, int dstType, int bufType,
                 int _rowBorderType = BORDER_REPLICATE,
                 int _columnBorderType = -1,
                 const Scalar& _borderValue = Scalar());
    //! the destructor默认析构函数
    virtual ~FilterEngine();
    //! reinitializes the engine. The previously assigned filters are released.重新初始化引擎,清空之前的滤波器申请的内存
    void init(const Ptr<BaseFilter>& _filter2D,
              const Ptr<BaseRowFilter>& _rowFilter,
              const Ptr<BaseColumnFilter>& _columnFilter,
              int srcType, int dstType, int bufType,
              int _rowBorderType = BORDER_REPLICATE,
              int _columnBorderType = -1,
              const Scalar& _borderValue = Scalar());

    //! starts filtering of the specified ROI of an image of size wholeSize.开始对指定了完整尺寸的图片的roi区域进行滤波操作
    virtual int start(const cv::Size &wholeSize, const cv::Size &sz, const cv::Point &ofs);
    //! starts filtering of the specified ROI of the specified image.对指定图片的指定roi区域进行滤波操作
    virtual int start(const Mat& src, const cv::Size &wsz, const cv::Point &ofs);
    //! processes the next srcCount rows of the image.处理图像的下一行
    virtual int proceed(const uchar* src, int srcStep, int srcCount,
                        uchar* dst, int dstStep);
    //! applies filter to the specified ROI of the image. if srcRoi=(0,0,-1,-1), the whole image is filtered.//对图像指定的ROI区域进行滤波操作,若srcRoi=(0,0,-1,-1),则对整个图像进行滤波操作
    virtual void apply(const Mat& src, Mat& dst, const cv::Size &wsz, const cv::Point &ofs);

    //! returns true if the filter is separable//如果滤波器可分离,则返回true
    bool isSeparable() const { return !filter2D; }
    //! returns the number//返回输入和输出行数
    int remainingInputRows() const;
    int remainingOutputRows() const;
//成员参数定义
    int srcType;
    int dstType;
    int bufType;
    Size ksize;
    Point anchor;
    int maxWidth;
    Size wholeSize;
    Rect roi;
    int dx1;
    int dx2;
    int rowBorderType;
    int columnBorderType;
    std::vector<int> borderTab;
    int borderElemSize;
    std::vector<uchar> ringBuf;
    std::vector<uchar> srcRow;
    std::vector<uchar> constBorderValue;
    std::vector<uchar> constBorderRow;
    int bufStep;
    int startY;
    int startY0;
    int endY;
    int rowCount;
    int dstY;
    std::vector<uchar*> rows;

    Ptr<BaseFilter> filter2D;
    Ptr<BaseRowFilter> rowFilter;
    Ptr<BaseColumnFilter> columnFilter;
};

Szie类:

typedef Size_<int> Size2i;
typedef Size2i Size;

Size_、Size2i、Size这三个类型名等价

//-----------------------------------【Size_类中文注释版源代码】----------------------------
//     代码作用:作为尺寸相关数据结构的Size_ 模板类
//     说明:以下代码为来自于计算机开源视觉库OpenCV的官方源代码
//     OpenCV源代码版本:2.4.8
//     源码路径:…\opencv\sources\modules\core\include\opencv2\core\core.hpp
//     源文件中如下代码的起始行数:816行
//     中文注释by浅墨
//--------------------------------------------------------------------------------------------------------
template<typename _Tp> class Size_
{
public:
   typedef _Tp value_type;
 
   //不同的构造函数定义
   Size_();
   Size_(_Tp _width, _Tp _height);
   Size_(const Size_& sz);
   Size_(const CvSize& sz);
   Size_(const CvSize2D32f& sz);
   Size_(const Point_<_Tp>& pt);
 //例如,Size(5,5),构造出的类型的宽和高都为5
   Size_& operator = (const Size_& sz);
   //区域(width*height)
   _Tp area() const;
 
   //转化另一种数据类型。
    template<typename_Tp2> operator Size_<_Tp2>() const;
 
   //转换为旧式的OpenCV类型.
   operator CvSize() const;
   operator CvSize2D32f() const;
 
   _Tp width, height; //宽度和高度,常用属性
};
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇