BaseColumnFilter 
 单列核的基础滤波器。 
 [cpp] view plaincopy 
 class BaseColumnFilter 
 { 
 public: 
 virtual ~BaseColumnFilter(); 
 // 用以被用户重写 
 // 
 // 对列的集合进行滤波操作 
 // 输入”dstcount + ksize - 1” 行,输出”dstcount” 行, 
 // 输入和输出的每行含有”width”个元素, 
 // 滤波之后的行写入缓存”dst”中. 
 virtual void operator()(const uchar** src, uchar* dst, int dststep, 
 int dstcount, int width) = 0; 
 // 重置滤波器的状态(IIR滤波器中可能用到) 
 virtual void reset(); 
 int ksize; // 核的孔径 
 int anchor; // 定位点坐标 
 // 处理过程中一般不使用 
 }; 
 类 BaseColumnFilter是使用单列核对数据滤波的基础类。滤波不一定是线性滤波,表示如下:其中 F 是滤波函数,但是用类来表示,因为类可以有其他的,如储存之前处理的数据之类的附加功能。这个类只是定义一个接口并不直接使用。作为替代,OpenCV中有一些函数(你可以添加更多)实现了特定的滤波功能并返回指向派生类的指针。这些指针通过 FilterEngine构造函数。 虽然滤波操作接口使用uchar 类型,具体实施时并限于8位数据。
BaseFilter 
 对2D图像滤波的基础类。 
 [cpp] view plaincopy 
 class BaseFilter 
 { 
 public: 
 virtual ~BaseFilter(); 
 // 用以被用户重写 
 // 
 // 对列的集合进行滤波操作 
 // 输入”dstcount + ksize.height - 1” 行,输出”dstcount” 行, 
 // 输入的每行含有”(width + ksize.width-1)*cn”个元素 
 // 输出的每行含有”width*cn”个元素, 
 // 滤波之后的行写入缓存”dst”中. 
 virtual void operator()(const uchar** src, uchar* dst, int dststep, 
 int dstcount, int width, int cn) = 0; 
 // 重置滤波器的状态(IIR滤波器中可能用到) 
 virtual void reset(); 
 Size ksize; 
 Point anchor; 
 }; 
 类 BaseFilter 是使用2D核对数据滤波的基础类。滤波不一定是线性的,可以表示如下:BaseRowFilter 
 单列核滤波器的基础类。 
 [cpp] view plaincopy 
 class BaseRowFilter 
 { 
 public: 
 virtual ~BaseRowFilter(); 
 // 用以被用户重写 
 // 
 // 对输入的单列进行滤波操作 
 // 输入列有 “width”个元素, 每个元素有 “cn” 个通道. 
 // 滤波之后的行写入缓存”dst”中. 
 virtual void operator()(const uchar* src, uchar* dst, 
 int width, int cn) = 0; 
 int ksize, anchor; 
 }; 
 类 BaseRowFilter 是使用单列核对数据滤波的基础类。滤波不一定是线性的,可以表示如下:其中 F 是滤波函数。此类只是定义了一个接口并不直接使用。这个类只是定义一个接口并不直接使用。作为替代,OpenCV中有一些函数(你可以添加更多)实现了特定的滤波功能并返回指向派生类的指针。这些指针通过 FilterEngine 构造函数。 虽然滤波操作接口使用uchar类型,具体实施时并限于8位数据。
FilterEngine 
 通用图像滤波类。 
 [cpp] view plaincopy 
 class FilterEngine 
 { 
 public: 
 // 空的构造函数 
 FilterEngine(); 
 // 构造2D的不可分的滤波器(!_filter2D.empty())或者 
 // 可分的滤波器 (!_rowFilter.empty() && !_columnFilter.empty()) 
 // 输入数据类型为 “srcType”, 输出类型为”dstType”, 
 // 中间的数据类型为 “bufType”. 
 // _rowBorderType 何 _columnBorderType 决定图像边界如何被外推扩充 
 // 只有 _rowBorderType and/or _columnBorderType 
 // == BORDER_CONSTANT 时 _borderValue 才会被用到 
 FilterEngine(const Ptr& _filter2D, 
 const Ptr& _rowFilter, 
 const Ptr& _columnFilter, 
 int srcType, int dstType, int bufType, 
 int _rowBorderType=BORDER_REPLICATE, 
 int _columnBorderType=-1, // 默认使用 _rowBorderType 
 const Scalar& _borderValue=Scalar()); 
 virtual ~FilterEngine(); 
 // 初始引擎的分割函数 
 void init(const Ptr& _filter2D, 
 const Ptr& _rowFilter, 
 const Ptr& _columnFilter, 
 int srcType, int dstType, int bufType, 
 int _rowBorderType=BORDER_REPLICATE, int _columnBorderType=-1, 
 const Scalar& _borderValue=Scalar()); 
 // 定义图像尺寸”wholeSize”为ROI开始滤波. 
 // 返回图像开始的y-position坐标. 
 virtual int start(Size wholeSize, Rect roi, int maxBufRows=-1); 
 // 另一种需要图像的开始 
 virtual int start(const Mat& src, const Rect& srcRoi=Rect(0,0,-1,-1), 
 bool isolated=false, int maxBufRows=-1); 
 // 处理源图像的另一部分 
 // 从”src”到”dst”处理”srcCount” 行 
 // 返回处理的行数 
 virtual int proceed(const uchar* src, int srcStep, int srcCount, 
 uchar* dst, int dstStep); 
 // 处理整个ROI的高层调用 
 virtual void apply( const Mat& src, Mat& dst, 
 const Rect& srcRoi=Rect(0,0,-1,-1), 
 Point dstOfs=Point(0,0), 
 bool isolated=false); 
 bool isSeparable() const { return filter2D.empty(); } 
 // 输入图中未被处理的行数 
 int remainingInputRows() const; 
 // 输入中未被处理的行数 
 int remainingOutputRows() const; 
 // 源图的开始和结束行 
 int startY, endY; 
 // 指向滤波器的指针 
 Ptr filter2D; 
 Ptr rowFilter; 
 Ptr columnFilter; 
 }; 
 类 FilterEngine 可以被用于对任何一个图像进行滤波。它包含了所有必要的缓冲区,计算需要的图像外的“虚”像素推算值等等。通过各种创建 *Filter 的函数(见下文)可以返回指向初始化的 FilterEngine 的实例,之后可以使用这些实例中的高层接口如 filter2D(), erode(),dilate() 等。因此,此类在OpenCV的很多滤波函数中起着关键的作用。 
 这个类使得滤波和其他函数结合更容易,如色彩空间转换,阈值,算术运算,等操作。将几个操作相结合在一起你可以得到更好的性能,因为数据都留在缓存中。例如以下是对浮点图像执行 Laplace 算子处理的简单例子,Laplacian() 函数可以简化为: 
 [cpp] view plaincopy 
 void laplace_f(const Mat& src, Mat& dst) 
 { 
 CV_Assert( src.type() == CV_32F ); 
 dst.create(src.size(), src.type()); 
 // get the derivative and smooth kernels for d2I/dx2. 
 // for d2I/dy2 consider using the same kernels, just swapped 
 Mat kd, ks; 
 getSobelKernels( kd, ks, 2, 0, ksize, false, ktype ); 
 // process 10 source rows at once 
 int DELTA = std::min(10, src.rows); 
 Ptr Fxx = createSeparableLinearFilter(src.type(), 
 dst.type(), kd, ks, Point(-1,-1), 0, borderType, borderType, Scalar() ); 
 Ptr Fyy = createSeparableLinearFilter(src.type(), 
 dst.type(), ks, kd, Point(-1,-1), 0, borderType, borderType, Scalar() ); 
 int y = Fxx->start(src), dsty = 0, dy = 0; 
 Fyy->start(src); 
 const uchar* sptr = src.data + y*src.step; 
 // allocate the buffers for the spatial image derivatives; 
 // the buffers need to have more than DELTA rows, because at the 
 // last iteration the output may take max(kd.rows-1,ks.rows-1) 
 // rows more than the input. 
 Mat Ixx( DELTA + kd.rows - 1, src.cols, dst.type() ); 
 Mat Iyy( DELTA + kd.rows - 1, src.cols, dst.type() ); 
 // inside the loop always pass DELTA rows to the filter 
 // (note that the “proceed” method takes care of possibe overflow, since 
 // it was given the actual image height in the “start” method) 
 // on output you can get: 
 // * < DELTA rows (initial buffer accumulation stage) 
 // * = DELTA rows (settled state in the middle) 
 // * > DELTA rows (when the input image is over, generate 
 // “virtual” rows using the border mode and filter them) 
 // this variable number of output rows is dy. 
 // dsty is the current output row. 
 // sptr is the pointer to the first input row in the portion to process 
 for( ; dsty < dst.rows; sptr += DELTA*src.step, dsty += dy ) 
 { 
 Fxx->proceed( sptr, (int)src.step, DELTA, Ixx.data, (int)Ixx.step ); 
 dy = Fyy->proceed( sptr, (int)src.step, DELTA, d2y.data, (int)Iyy.step ); 
 if( dy > 0 ) 
 { 
 Mat dstripe = dst.rowRange(dsty, dsty + dy); 
 add(Ixx.rowRange(0, dy), Iyy.rowRange(0, dy), dstripe); 
 } 
 } 
 } 
 如果你不需要对滤波过程的控制,你可以简单地使用 FilterEngine:: apply方法。 
 [cpp] view plaincopy 
 void FilterEngine::apply(const Mat& src, Mat& dst, 
 const Rect& srcRoi, Point dstOfs, bool isolated) 
 { 
 // check matrix types 
 CV_Assert( src.type() == srcType && dst.type() == dstType ); 
 // handle the “whole image” case 
 Rect _srcRoi = srcRoi; 
 if( _srcRoi == Rect(0,0,-1,-1) ) 
 _srcRoi = Rect(0,0,src.cols,src.rows); 
 // check if the destination ROI is inside dst. 
 // and FilterEngine::start will check if the source ROI is inside src. 
 CV_Assert( dstOfs.x >= 0 && dstOfs.y >= 0 && 
 dstOfs.x + _srcRoi.width <= dst.cols && 
 dstOfs.y + _srcRoi.height <= dst.rows ); 
 // start filtering 
 int y = start(src, _srcRoi, isolated); 
 // process the whole ROI. Note that “endY - startY” is the total number 
 // of the source rows to process 
 // (including the possible rows outside of srcRoi but inside the source image) 
 proceed( src.data + y*src.step, 
 (int)src.step, endY - startY, 
 dst.data + dstOfs.y*dst.step + 
 dstOfs.x*dst.elemSize(), (int)dst.step ); 
 } 
 不同于OpenCV的早期版本,现在的滤波操作支持图像ROI概念,也就是说,在ROI图像之外但在图像之内的像素点可以用于滤波操作。例如,你可以取单个像素作为ROI滤波。通过滤波器之后将范围特定的像素。然而,通过传递FilterEngine::start或FilterEngine::apply 参数 isolated=false 它有可能仍是旧的图像。你可以明确指定传递ROI给 FilterEngine::apply 函数或者构造新的矩阵头: 
 [cpp] view plaincopy 
 // compute dI/dx derivative at src(x,y) 
 // method 1: 
 // form a matrix header for a single value 
 float val1 = 0; 
 Mat dst1(1,1,CV_32F,&val1); 
 Ptr Fx = createDerivFilter(CV_32F, CV_32F, 
 1, 0, 3, BORDER_REFLECT_101); 
 Fx->apply(src, Rect(x,y,1,1), Point(), dst1); 
 // method 2: 
 // form a matrix header for a single value 
 float val2 = 0; 
 Mat dst2(1,1,CV_32F,&val2); 
 Mat pix_roi(src, Rect(x,y,1,1)); 
 Sobel(pix_roi, dst2, dst2.type(), 1, 0, 3, 1, 0, BORDER_REFLECT_101); 
 探索中的数据类型。由于它是在 BaseFilter 描述中提到的具体的滤波器,虽然 Base*Filter::operator() 除了UCHAR的指针并其他类型的信息, 但实际它可以处理任何类型的数据。为了保证所有的函数可以运行,使用以下规则: 
 在分离滤波的情况下,首先应用 FilterEngine::rowFilter 。它把输入图像数据(srcType类型)的中间结果存储在内部缓冲区(bufType类型)。然后,这些中间结果作为单通道数据由 FilterEngine:: columnFilter处理,结果存储在输出图像(dstType类型)中。因此,输入 RowFilter 类型是srcType 而输出类型是 bufType。输入 columnFilter 的类型是CV_MAT_DEPTH(bufType)而输出的类型为CV_MAT_DEPTH(dstType)。 
 在非分离滤波的情况下,bufType 必须与 srcType 类型相同。如果需要,源数据会被复制到临时缓冲区之后传递给 FilterEngine:: filter2D 。也就是说,输入filter2D 类型为 scrType(= bufType),输出类型是