opencv Filter2D类 不可分离滤波器的实现

//二维不可分滤波器核心算法 
template<typename ST, class CastOp, class VecOp> struct Filter2D : public BaseFilter
{
    typedef typename CastOp::type1 KT; //源类型
    typedef typename CastOp::rtype DT;  //目标类型
	//完全构造函数
    Filter2D( const Mat& _kernel, Point _anchor,
        double _delta, const CastOp& _castOp=CastOp(),
        const VecOp& _vecOp=VecOp() )
    {
        anchor = _anchor;//锚点
        ksize = _kernel.size();//核大小
        delta = saturate_cast<KT>(_delta);//偏移常量
        castOp0 = _castOp; //类型转换类
        vecOp = _vecOp;   //不同实现类
        CV_Assert( _kernel.type() == DataType<KT>::type );
        preprocess2DKernel( _kernel, coords, coeffs );//调用核预处理函数系数
        ptrs.resize( coords.size() );//更新指针向量大小
    }
	//进行滤波操作
    void operator()(const uchar** src, uchar* dst, int dststep, int count, int width, int cn) CV_OVERRIDE
    {
        KT _delta = delta;//偏移
        const Point* pt = &coords[0];//取非零核元素坐标
        const KT* kf = (const KT*)&coeffs[0];//取核系数
        const ST** kp = (const ST**)&ptrs[0];//取指针向量的地址,这个指针向量用来保存,每一计算行,核非零元素对应的源图像元素的位置
        int i, k, nz = (int)coords.size();
        CastOp castOp = castOp0;//类型转换对象

        width *= cn;//宽度 roi.width*cn
        for( ; count > 0; count--, dst += dststep, src++ ) //count表示要计算目标多少行
        {
            DT* D = (DT*)dst; //取目标一行的首地址

            for( k = 0; k < nz; k++ ) //更新指针向量,存储要计算目标对应行对应的原图像上非零核元素对应的原图像元素的位置,并以这些元素的位置作为起始数据的位置
                kp[k] = (const ST*)src[pt[k].y] + pt[k].x*cn;

            i = vecOp((const uchar**)kp, dst, width);//其他 具体类型的按行滤波计算实现,如果存在具体类型的行滤波方法,则i的值会不小于width,后面的for循环通用行滤波器将不会进行操作
            #if CV_ENABLE_UNROLLED
            for( ; i <= width - 4; i += 4 )
            {
                KT s0 = _delta, s1 = _delta, s2 = _delta, s3 = _delta;

                for( k = 0; k < nz; k++ )
                {
                    const ST* sptr = kp[k] + i;
                    KT f = kf[k];
                    s0 += f*sptr[0];
                    s1 += f*sptr[1];
                    s2 += f*sptr[2];
                    s3 += f*sptr[3];
                }

                D[i] = castOp(s0); D[i+1] = castOp(s1);
                D[i+2] = castOp(s2); D[i+3] = castOp(s3);
            }
            #endif
            for( ; i < width; i++ )
            {
                KT s0 = _delta;
                for( k = 0; k < nz; k++ )
                    s0 += kf[k]*kp[k][i];
                D[i] = castOp(s0);
            }
        }
    }

    std::vector<Point> coords; //非零元素下标
    std::vector<uchar> coeffs; //核系数
    std::vector<uchar*> ptrs;   //指针向量,临时变量,进行行滤波计算时,存储每行核非零对应的原图像的元素的位置
    KT delta;  //偏移
    CastOp castOp0;//类型转换类对象
    VecOp vecOp;//其他按行滤波 这个一般是用作优化的 例如 FilterVec_32f等
};

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值