学习浅墨大佬:教程
函数调用:
#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; //宽度和高度,常用属性
};