1. 程式人生 > >opencv Filter2D類 不可分離濾波器的實現

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等
};