⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cvfilter.cpp

📁 将OpenCV移植到DSP上
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    CvBaseImageFilter::clear();
}


CvSepFilter::~CvSepFilter()
{
    clear();
}


#undef FILTER_BITS
#define FILTER_BITS 8

void CvSepFilter::init( int _max_width, int _src_type, int _dst_type,
                        const CvMat* _kx, const CvMat* _ky,
                        CvPoint _anchor, int _border_mode,
                        CvScalar _border_value )
{
    CV_FUNCNAME( "CvSepFilter::init" );

    __BEGIN__;

    CvSize _ksize;
    int filter_type;
    int i, xsz, ysz;
    int convert_filters = 0;
    double xsum = 0, ysum = 0;
    const float eps = FLT_EPSILON*100.f;

    if( !CV_IS_MAT(_kx) || !CV_IS_MAT(_ky) ||
        _kx->cols != 1 && _kx->rows != 1 ||
        _ky->cols != 1 && _ky->rows != 1 ||
        CV_MAT_CN(_kx->type) != 1 || CV_MAT_CN(_ky->type) != 1 ||
        !CV_ARE_TYPES_EQ(_kx,_ky) )
        CV_ERROR( CV_StsBadArg,
        "Both kernels must be valid 1d single-channel vectors of the same types" );

    if( CV_MAT_CN(_src_type) != CV_MAT_CN(_dst_type) )
        CV_ERROR( CV_StsUnmatchedFormats, "Input and output must have the same number of channels" );

    filter_type = MAX( CV_32F, CV_MAT_DEPTH(_kx->type) );

    _ksize.width = _kx->rows + _kx->cols - 1;
    _ksize.height = _ky->rows + _ky->cols - 1;

    CV_CALL( CvBaseImageFilter::init( _max_width, _src_type, _dst_type, 1, _ksize,
                                      _anchor, _border_mode, _border_value ));

    if( !(kx && CV_ARE_SIZES_EQ(kx,_kx)) )
    {
        cvReleaseMat( &kx );
        CV_CALL( kx = cvCreateMat( _kx->rows, _kx->cols, filter_type ));
    }

    if( !(ky && CV_ARE_SIZES_EQ(ky,_ky)) )
    {
        cvReleaseMat( &ky );
        CV_CALL( ky = cvCreateMat( _ky->rows, _ky->cols, filter_type ));
    }

    CV_CALL( cvConvert( _kx, kx ));
    CV_CALL( cvConvert( _ky, ky ));

    xsz = kx->rows + kx->cols - 1;
    ysz = ky->rows + ky->cols - 1;
    kx_flags = ky_flags = ASYMMETRICAL + SYMMETRICAL + POSITIVE + SUM_TO_1 + INTEGER;
    
    if( !(xsz & 1) )
        kx_flags &= ~(ASYMMETRICAL + SYMMETRICAL);
    if( !(ysz & 1) )
        ky_flags &= ~(ASYMMETRICAL + SYMMETRICAL);

    for( i = 0; i < xsz; i++ )
    {
        float v = kx->data.fl[i];
        xsum += v;
        if( v < 0 )
            kx_flags &= ~POSITIVE;
        if( fabs(v - cvRound(v)) > eps )
            kx_flags &= ~INTEGER;
        if( fabs(v - kx->data.fl[xsz - i - 1]) > eps )
            kx_flags &= ~SYMMETRICAL;
        if( fabs(v + kx->data.fl[xsz - i - 1]) > eps )
            kx_flags &= ~ASYMMETRICAL;
    }

    if( fabs(xsum - 1.) > eps )
        kx_flags &= ~SUM_TO_1;
    
    for( i = 0; i < ysz; i++ )
    {
        float v = ky->data.fl[i];
        ysum += v;
        if( v < 0 )
            ky_flags &= ~POSITIVE;
        if( fabs(v - cvRound(v)) > eps )
            ky_flags &= ~INTEGER;
        if( fabs(v - ky->data.fl[ysz - i - 1]) > eps )
            ky_flags &= ~SYMMETRICAL;
        if( fabs(v + ky->data.fl[ysz - i - 1]) > eps )
            ky_flags &= ~ASYMMETRICAL;
    }

    if( fabs(ysum - 1.) > eps )
        ky_flags &= ~SUM_TO_1;

    x_func = 0;
    y_func = 0;

    if( CV_MAT_DEPTH(src_type) == CV_8U )
    {
        if( CV_MAT_DEPTH(dst_type) == CV_8U &&
            ((kx_flags&ky_flags) & (SYMMETRICAL + POSITIVE + SUM_TO_1)) == SYMMETRICAL + POSITIVE + SUM_TO_1 )
        {
            x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32s;
            y_func = (CvColumnFilterFunc)icvFilterColSymm_32s8u;
            kx_flags &= ~INTEGER;
            ky_flags &= ~INTEGER;
            convert_filters = 1;
        }
        else if( CV_MAT_DEPTH(dst_type) == CV_16S &&
            (kx_flags & (SYMMETRICAL + ASYMMETRICAL)) && (kx_flags & INTEGER) &&
            (ky_flags & (SYMMETRICAL + ASYMMETRICAL)) && (ky_flags & INTEGER) )
        {
            x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32s;
            y_func = (CvColumnFilterFunc)icvFilterColSymm_32s16s;
            convert_filters = 1;
        }
        else
        {
            if( CV_MAT_DEPTH(dst_type) > CV_32F )
                CV_ERROR( CV_StsUnsupportedFormat, "8u->64f separable filtering is not supported" );

            if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
                x_func = (CvRowFilterFunc)icvFilterRowSymm_8u32f;
            else
                x_func = (CvRowFilterFunc)icvFilterRow_8u32f;
        }
    }
    else if( CV_MAT_DEPTH(src_type) == CV_16U )
    {
        if( CV_MAT_DEPTH(dst_type) > CV_32F )
            CV_ERROR( CV_StsUnsupportedFormat, "16u->64f separable filtering is not supported" );

        if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
            x_func = (CvRowFilterFunc)icvFilterRowSymm_16u32f;
        else
            x_func = (CvRowFilterFunc)icvFilterRow_16u32f;
    }
    else if( CV_MAT_DEPTH(src_type) == CV_16S )
    {
        if( CV_MAT_DEPTH(dst_type) > CV_32F )
            CV_ERROR( CV_StsUnsupportedFormat, "16s->64f separable filtering is not supported" );

        if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
            x_func = (CvRowFilterFunc)icvFilterRowSymm_16s32f;
        else
            x_func = (CvRowFilterFunc)icvFilterRow_16s32f;
    }
    else if( CV_MAT_DEPTH(src_type) == CV_32F )
    {
        if( CV_MAT_DEPTH(dst_type) != CV_32F )
            CV_ERROR( CV_StsUnsupportedFormat, "When the input has 32f data type, the output must also have 32f type" );

        if( kx_flags & (SYMMETRICAL + ASYMMETRICAL) )
            x_func = (CvRowFilterFunc)icvFilterRowSymm_32f;
        else
            x_func = (CvRowFilterFunc)icvFilterRow_32f;
    }
    else
        CV_ERROR( CV_StsUnsupportedFormat, "Unknown or unsupported input data type" );

    if( !y_func )
    {
        if( CV_MAT_DEPTH(dst_type) == CV_8U )
        {
            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f8u;
            else
                y_func = (CvColumnFilterFunc)icvFilterCol_32f8u;
        }
        else if( CV_MAT_DEPTH(dst_type) == CV_16U )
        {
            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f16u;
            else
                y_func = (CvColumnFilterFunc)icvFilterCol_32f16u;
        }
        else if( CV_MAT_DEPTH(dst_type) == CV_16S )
        {
            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f16s;
            else
                y_func = (CvColumnFilterFunc)icvFilterCol_32f16s;
        }
        else if( CV_MAT_DEPTH(dst_type) == CV_32F )
        {
            if( ky_flags & (SYMMETRICAL + ASYMMETRICAL) )
                y_func = (CvColumnFilterFunc)icvFilterColSymm_32f;
            else
                y_func = (CvColumnFilterFunc)icvFilterCol_32f;
        }
        else
            CV_ERROR( CV_StsUnsupportedFormat, "Unknown or unsupported input data type" );
    }

    if( convert_filters )
    {
        int scale = kx_flags & ky_flags & INTEGER ? 1 : (1 << FILTER_BITS);
        int sum;
        
        for( i = sum = 0; i < xsz; i++ )
        {
            int t = cvRound(kx->data.fl[i]*scale);
            kx->data.i[i] = t;
            sum += t;
        }
        if( scale > 1 )
            kx->data.i[xsz/2] += scale - sum;

        for( i = sum = 0; i < ysz; i++ )
        {
            int t = cvRound(ky->data.fl[i]*scale);
            ky->data.i[i] = t;
            sum += t;
        }
        if( scale > 1 )
            ky->data.i[ysz/2] += scale - sum;
        kx->type = (kx->type & ~CV_MAT_DEPTH_MASK) | CV_32S;
        ky->type = (ky->type & ~CV_MAT_DEPTH_MASK) | CV_32S;
    }

    __END__;
}


void CvSepFilter::init( int _max_width, int _src_type, int _dst_type,
                        bool _is_separable, CvSize _ksize,
                        CvPoint _anchor, int _border_mode,
                        CvScalar _border_value )
{
    CvBaseImageFilter::init( _max_width, _src_type, _dst_type, _is_separable,
                             _ksize, _anchor, _border_mode, _border_value );
}


static void
icvFilterRowSymm_8u32s( const uchar* src, int* dst, void* params )
{
    const CvSepFilter* state = (const CvSepFilter*)params;
    const CvMat* _kx = state->get_x_kernel();
    const int* kx = _kx->data.i;
    int ksize = _kx->cols + _kx->rows - 1;
    int i = 0, j, k, width = state->get_width();
    int cn = CV_MAT_CN(state->get_src_type());
    int ksize2 = ksize/2, ksize2n = ksize2*cn;
    int is_symm = state->get_x_kernel_flags() & CvSepFilter::SYMMETRICAL;
    const uchar* s = src + ksize2n;

    kx += ksize2;
    width *= cn;

    if( is_symm )
    {
        if( ksize == 1 && kx[0] == 1 )
        {
            for( i = 0; i <= width - 2; i += 2 )
            {
                int s0 = s[i], s1 = s[i+1];
                dst[i] = s0; dst[i+1] = s1;
            }
            s += i;
        }
        else if( ksize == 3 )
        {
            if( kx[0] == 2 && kx[1] == 1 )
                for( ; i <= width - 2; i += 2, s += 2 )
                {
                    int s0 = s[-cn] + s[0]*2 + s[cn], s1 = s[1-cn] + s[1]*2 + s[1+cn];
                    dst[i] = s0; dst[i+1] = s1;
                }
            else if( kx[0] == 10 && kx[1] == 3 )
                for( ; i <= width - 2; i += 2, s += 2 )
                {
                    int s0 = s[0]*10 + (s[-cn] + s[cn])*3, s1 = s[1]*10 + (s[1-cn] + s[1+cn])*3;
                    dst[i] = s0; dst[i+1] = s1;
                }
            else if( kx[0] == 2*64 && kx[1] == 1*64 )
                for( ; i <= width - 2; i += 2, s += 2 )
                {
                    int s0 = (s[0]*2 + s[-cn] + s[cn]) << 6;
                    int s1 = (s[1]*2 + s[1-cn] + s[1+cn]) << 6;
                    dst[i] = s0; dst[i+1] = s1;
                }
            else
            {
                int k0 = kx[0], k1 = kx[1];
                for( ; i <= width - 2; i += 2, s += 2 )
                {
                    int s0 = s[0]*k0 + (s[-cn] + s[cn])*k1, s1 = s[1]*k0 + (s[1-cn] + s[1+cn])*k1;
                    dst[i] = s0; dst[i+1] = s1;
                }
            }
        }
        else if( ksize == 5 )
        {
            int k0 = kx[0], k1 = kx[1], k2 = kx[2];
            if( k0 == 6*16 && k1 == 4*16 && k2 == 1*16 )
                for( ; i <= width - 2; i += 2, s += 2 )
                {
                    int s0 = (s[0]*6 + (s[-cn] + s[cn])*4 + (s[-cn*2] + s[cn*2])*1) << 4;
                    int s1 = (s[1]*6 + (s[1-cn] + s[1+cn])*4 + (s[1-cn*2] + s[1+cn*2])*1) << 4;
                    dst[i] = s0; dst[i+1] = s1;
                }
            else
                for( ; i <= width - 2; i += 2, s += 2 )
                {
                    int s0 = s[0]*k0 + (s[-cn] + s[cn])*k1 + (s[-cn*2] + s[cn*2])*k2;
                    int s1 = s[1]*k0 + (s[1-cn] + s[1+cn])*k1 + (s[1-cn*2] + s[1+cn*2])*k2;
                    dst[i] = s0; dst[i+1] = s1;
                }
        }
        else
            for( ; i <= width - 4; i += 4, s += 4 )
            {
                int f = kx[0];
                int s0 = f*s[0], s1 = f*s[1], s2 = f*s[2], s3 = f*s[3];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -