boxFilter滤波器(opencv) blur滤波器 ,sqrBoxFilter滤波器

  • 结构图

暂且不画

里面涉及到的滤波器引擎,参考 https://blog.csdn.net/u014676657/article/details/82970932

  • 边界类型

//! Various border types, image boundaries are denoted with `|`
//! @see borderInterpolate, copyMakeBorder 插值边界 复制制作边框
enum BorderTypes {
    BORDER_CONSTANT    = 0, //!< `iiiiii|abcdefgh|iiiiiii`  with some specified `i` 常量
    BORDER_REPLICATE   = 1, //!< `aaaaaa|abcdefgh|hhhhhhh`  最外面
    BORDER_REFLECT     = 2, //!< `fedcba|abcdefgh|hgfedcb`  最外面对称
    BORDER_WRAP        = 3, //!< `cdefgh|abcdefgh|abcdefg`  反向填充
    BORDER_REFLECT_101 = 4, //!< `gfedcb|abcdefgh|gfedcba`
    BORDER_TRANSPARENT = 5, //!< `uvwxyz|abcdefgh|ijklmno`

    BORDER_REFLECT101  = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_DEFAULT     = BORDER_REFLECT_101, //!< same as BORDER_REFLECT_101
    BORDER_ISOLATED    = 16 //!< do not look outside of ROI
};
  • boxFilter函数

  • //盒状滤波器
    //函数采用元素全为1的核去平滑图像
    //
    inline CV_EXPORTS_W void boxFilter(InputArray src, //输入图像
    OutputArray dst, //输出图像,大小和类型和输入图像一样
    int ddepth,  //输出图像的深度,(-1时,使用src.depth())
    Size ksize,   //核大小
    Point anchor = Point(-1,-1),//锚点,default=(-1,-1),为核的中心
    bool normalize = true,    //指定是否由核的面积归一化,
    int borderType = BORDER_DEFAULT)//边界类型,确定超出图像的外推像素
    {
    	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) //目标图像的深度默认值时,与原图像一致
    		ddepth = sdepth;
    	_dst.create(src.size(), CV_MAKETYPE(ddepth, cn));//创建目标实际图像矩阵
    	Mat dst = _dst.getMat();//获取目标图像矩阵
    	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.row-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<FilterEngine> f = createBoxFilter(src.type(), dst.type(),
    		ksize, anchor, normalize, borderType);
    
    	f->apply(src, dst, wsz, ofs);//对图像进行滤波
    }
  • createBoxFilter

//! returns box filter engine 返回盒状滤波器引擎
Ptr<FilterEngine> createBoxFilter( int srcType,//原图像类型
 int dstType, //目标图像类型 
 Size ksize,  //核大小
 Point anchor = Point(-1,-1),//锚点
 bool normalize = true,  //是否归一化
 int borderType = BORDER_DEFAULT) //边界类型 
{
    int sdepth = CV_MAT_DEPTH(srcType);//获取原图像的深度
    int cn = CV_MAT_CN(srcType), sumType = CV_64F;//通道数,缓冲类型(中间数据类型)
    if( sdepth == CV_8U && CV_MAT_DEPTH(dstType) == CV_8U &&
        ksize.width*ksize.height <= 256 )  //如果核面积小于256,且原图像和目标图像类型都是8位的uchar则中间数据类型为16位的数据类型
        sumType = CV_16U;
    else if( sdepth <= CV_32S && (!normalize ||
        ksize.width*ksize.height <= (sdepth == CV_8U ? (1<<23) :
            sdepth == CV_16U ? (1 << 15) : (1 << 16))) )
        sumType = CV_32S;
    sumType = CV_MAKETYPE( sumType, cn );
    //获取行滤波器
    Ptr<BaseRowFilter> rowFilter = getRowSumFilter(srcType, sumType, ksize.width, anchor.x );
    //获取列滤波器
    Ptr<BaseColumnFilter> columnFilter = getColumnSumFilter(sumType,
        dstType, ksize.height, anchor.y, normalize ? 1./(ksize.width*ksize.height) : 1);
    //返回盒状滤波器
    return makePtr<FilterEngine>(Ptr<BaseFilter>(), rowFilter, columnFilter,
           srcType, dstType, sumType, borderType );
}

 

  •  blur滤波器

           在opencv中,blur滤波器其实就是boxFilter的一种特殊情况,就是调用盒状滤波器实现的。实现代码如下:

void cv::blur(InputArray src, OutputArray dst,
           Size ksize, Point anchor, int borderType )
{
    CV_INSTRUMENT_REGION()//这个不用管,现在好多东西不会,只能分析到这里了

    boxFilter( src, dst, -1, ksize, anchor, true, borderType );
}
  • sqrBoxFilter滤波器

        sqrBoxFilter滤波器的实现和BoxFilter滤波器区别不大,唯一的区别就是行滤波器,sqrBoxFilter滤波器获取的是SqrRowSum滤波器,而后者使用的是RowSum滤波器,注释不写,SqrRowSum和RowSum滤波器,详见:https://blog.csdn.net/u014676657/article/details/82994552


void cv::sqrBoxFilter( InputArray _src, OutputArray _dst, int ddepth,
                       Size ksize, Point anchor,
                       bool normalize, int borderType )
{
    CV_INSTRUMENT_REGION()

    int srcType = _src.type(), sdepth = CV_MAT_DEPTH(srcType), cn = CV_MAT_CN(srcType);
    Size size = _src.size();

    if( ddepth < 0 )
        ddepth = sdepth < CV_32F ? CV_32F : CV_64F;

    if( borderType != BORDER_CONSTANT && normalize )
    {
        if( size.height == 1 )
            ksize.height = 1;
        if( size.width == 1 )
            ksize.width = 1;
    }

    CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
               ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize, true))

    int sumDepth = CV_64F;
    if( sdepth == CV_8U )
        sumDepth = CV_32S;
    int sumType = CV_MAKETYPE( sumDepth, cn ), dstType = CV_MAKETYPE(ddepth, cn);

    Mat src = _src.getMat();
    _dst.create( size, dstType );
    Mat dst = _dst.getMat();

    Ptr<BaseRowFilter> rowFilter = getSqrRowSumFilter(srcType, sumType, ksize.width, anchor.x );
    Ptr<BaseColumnFilter> columnFilter = getColumnSumFilter(sumType,
                                                            dstType, ksize.height, anchor.y,
                                                            normalize ? 1./(ksize.width*ksize.height) : 1);

    Ptr<FilterEngine> f = makePtr<FilterEngine>(Ptr<BaseFilter>(), rowFilter, columnFilter,
                                                srcType, dstType, sumType, borderType );
    Point ofs;
    Size wsz(src.cols, src.rows);
    src.locateROI( wsz, ofs );

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

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值