Ejemplo n.º 1
0
CV_IMPL  double
cvPseudoInv( CvArr* srcarr, CvArr* dstarr, int flags )
{
    uchar* buffer = 0;
    int local_alloc = 0;
    double condition_number = 0;

    CV_FUNCNAME( "cvPseudoInv" );

    __BEGIN__;

    CvMat astub, *a = (CvMat*)srcarr;
    CvMat bstub, *b = (CvMat*)dstarr;
    CvMat ustub, *u = &ustub;
    CvMat vstub, *v = &vstub;
    CvMat tmat;
    uchar* tw = 0;
    int type, n, m, nm, mn;
    int buf_size, pix_size;

    if( !CV_IS_ARR( a ))
        CV_CALL( a = cvGetMat( a, &astub ));

    if( !CV_IS_ARR( b ))
        CV_CALL( b = cvGetMat( b, &bstub ));

    if( !CV_ARE_TYPES_EQ( a, b ))
        CV_ERROR( CV_StsUnmatchedSizes, "" );

    n = a->width;
    m = a->height;

    nm = MIN( n, m );
    mn = MAX( n, m );

    if( n != b->height || m != b->width )
        CV_ERROR( CV_StsUnmatchedSizes, "" );

    type = CV_ARR_TYPE( a->type );
    pix_size = icvPixSize[type];

    buf_size = nm*2 + mn + m*mn + n*n;

    if( !(flags & CV_SVD_MODIFY_A) )
        buf_size += m*n;

    buf_size *= pix_size;

    if( buf_size <= CV_MAX_LOCAL_SIZE )
    {
        buffer = (uchar*)alloca( buf_size );
        local_alloc = 1;
    }
    else
    {
        CV_CALL( buffer = (uchar*)cvAlloc( buf_size ));
    }

    if( !(flags & CV_SVD_MODIFY_A) )
    {
        cvInitMatHeader( &tmat, a->height, a->width, type,
                         buffer + buf_size - n*m*pix_size );
        cvCopy( a, &tmat );
        a = &tmat;
    }

    tw = buffer + (nm + mn)*pix_size;

    cvInitMatHeader( u, m, m, type, tw + nm*pix_size );
    cvInitMatHeader( v, n, n, type, u->data.ptr + m*mn*pix_size );

    if( type == CV_32FC1 )
    {
        IPPI_CALL( icvSVD_32f( a->data.fl, a->step/sizeof(float), (float*)tw,
                               u->data.fl, u->step/sizeof(float),
                               v->data.fl, v->step/sizeof(float),
                               icvGetMatSize(a), (float*)buffer ));
    }
    else if( type == CV_64FC1 )
    {
        IPPI_CALL( icvSVD_64f( a->data.db, a->step/sizeof(double), (double*)tw,
                               u->data.db, u->step/sizeof(double),
                               v->data.db, v->step/sizeof(double),
                               icvGetMatSize(a), (double*)buffer ));
    }
    else
    {
        CV_ERROR( CV_StsUnsupportedFormat, "" );
    }

    cvT( v, v );
    cvGetRow( u, &tmat, 0 );

    if( type == CV_32FC1 )
    {
        for( int i = 0; i < nm; i++ )
        {
            double t = ((float*)tw)[i];
            tmat.data.ptr = u->data.ptr + i*u->step;
            t = t > FLT_EPSILON ? 1./t : 0;
            if( i == mn - 1 )
                condition_number = t != 0 ? ((float*)tw)[0]*t : DBL_MAX;
            cvScale( &tmat, &tmat, t );
        }
    }
    else
    {
        for( int i = 0; i < nm; i++ )
        {
            double t = ((double*)tw)[i];
            tmat.data.ptr = u->data.ptr + i*u->step;
            t = t > DBL_EPSILON ? 1./t : 0;
            if( i == mn - 1 )
                condition_number = t != 0 ? ((double*)tw)[0]*t : DBL_MAX;
            cvScale( &tmat, &tmat, t );
        }
    }

    u->height = n;
    if( n > m )
    {
        cvGetSubArr( u, &tmat, cvRect( 0, m, m, n - m ));
        cvSetZero( &tmat );
    }
    
    cvMatMulAdd( v, u, 0, b );

    CV_CHECK_NANS( b );

    __END__;

    if( buffer && !local_alloc )
        cvFree( (void**)&buffer );

    return condition_number;
}
Ejemplo n.º 2
0
CV_IMPL  void
cvSVD( CvArr* aarr, CvArr* warr, CvArr* uarr, CvArr* varr, int flags )
{
    uchar* buffer = 0;
    int local_alloc = 0;

    CV_FUNCNAME( "cvSVD" );

    __BEGIN__;

    CvMat astub, *a = (CvMat*)aarr;
    CvMat wstub, *w = (CvMat*)warr;
    CvMat ustub, *u;
    CvMat vstub, *v;
    CvMat tmat;
    uchar* tw = 0;
    int type;
    int a_buf_offset = 0, u_buf_offset = 0, buf_size, pix_size;
    int temp_u = 0, /* temporary storage for U is needed */
        t_svd; /* special case: a->rows < a->cols */
    int m, n;
    int w_rows, w_cols;
    int u_rows = 0, u_cols = 0;
    int w_is_mat = 0;

    if( !CV_IS_MAT( a ))
        CV_CALL( a = cvGetMat( a, &astub ));

    if( !CV_IS_MAT( w ))
        CV_CALL( w = cvGetMat( w, &wstub ));

    if( !CV_ARE_TYPES_EQ( a, w ))
        CV_ERROR( CV_StsUnmatchedFormats, "" );

    if( a->rows >= a->cols )
    {
        m = a->rows;
        n = a->cols;
        w_rows = w->rows;
        w_cols = w->cols;
        t_svd = 0;
    }
    else
    {
        CvArr* t;
        CV_SWAP( uarr, varr, t );

        flags = (flags & CV_SVD_U_T ? CV_SVD_V_T : 0)|
                (flags & CV_SVD_V_T ? CV_SVD_U_T : 0);
        m = a->cols;
        n = a->rows;
        w_rows = w->cols;
        w_cols = w->rows;
        t_svd = 1;
    }

    u = (CvMat*)uarr;
    v = (CvMat*)varr;

    w_is_mat = w_cols > 1 && w_rows > 1;

    if( !w_is_mat && CV_IS_MAT_CONT(w->type) && w_cols + w_rows - 1 == n )
        tw = w->data.ptr;

    if( u )
    {
        if( !CV_IS_MAT( u ))
            CV_CALL( u = cvGetMat( u, &ustub ));

        if( !(flags & CV_SVD_U_T) )
        {
            u_rows = u->rows;
            u_cols = u->cols;
        }
        else
        {
            u_rows = u->cols;
            u_cols = u->rows;
        }

        if( !CV_ARE_TYPES_EQ( a, u ))
            CV_ERROR( CV_StsUnmatchedFormats, "" );

        if( u_rows != m || (u_cols != m && u_cols != n))
            CV_ERROR( CV_StsUnmatchedSizes, !t_svd ? "U matrix has unappropriate size" :
                                                     "V matrix has unappropriate size" );
            
        temp_u = (u_rows != u_cols && !(flags & CV_SVD_U_T)) || u->data.ptr==a->data.ptr;

        if( w_is_mat && u_cols != w_rows )
            CV_ERROR( CV_StsUnmatchedSizes, !t_svd ? "U and W have incompatible sizes" :
                                                     "V and W have incompatible sizes" );
    }
    else
    {
        u = &ustub;
        u->data.ptr = 0;
        u->step = 0;
    }

    if( v )
    {
        int v_rows, v_cols;

        if( !CV_IS_MAT( v ))
            CV_CALL( v = cvGetMat( v, &vstub ));

        if( !(flags & CV_SVD_V_T) )
        {
            v_rows = v->rows;
            v_cols = v->cols;
        }
        else
        {
            v_rows = v->cols;
            v_cols = v->rows;
        }

        if( !CV_ARE_TYPES_EQ( a, v ))
            CV_ERROR( CV_StsUnmatchedFormats, "" );

        if( v_rows != n || v_cols != n )
            CV_ERROR( CV_StsUnmatchedSizes, t_svd ? "U matrix has unappropriate size" :
                                                    "V matrix has unappropriate size" );

        if( w_is_mat && w_cols != v_cols )
            CV_ERROR( CV_StsUnmatchedSizes, t_svd ? "U and W have incompatible sizes" :
                                                    "V and W have incompatible sizes" );
    }
    else
    {
        v = &vstub;
        v->data.ptr = 0;
        v->step = 0;
    }

    type = CV_MAT_TYPE( a->type );
    pix_size = CV_ELEM_SIZE(type);
    buf_size = n*2 + m;

    if( !(flags & CV_SVD_MODIFY_A) )
    {
        a_buf_offset = buf_size;
        buf_size += a->rows*a->cols;
    }

    if( temp_u )
    {
        u_buf_offset = buf_size;
        buf_size += u->rows*u->cols;
    }

    buf_size *= pix_size;

    if( buf_size <= CV_MAX_LOCAL_SIZE )
    {
        buffer = (uchar*)cvStackAlloc( buf_size );
        local_alloc = 1;
    }
    else
    {
        CV_CALL( buffer = (uchar*)cvAlloc( buf_size ));
    }
    
    if( !(flags & CV_SVD_MODIFY_A) )
    {
        cvInitMatHeader( &tmat, m, n, type,
                         buffer + a_buf_offset*pix_size );
        if( !t_svd )
            cvCopy( a, &tmat );
        else
            cvT( a, &tmat );
        a = &tmat;
    }

    if( temp_u )
    {
        cvInitMatHeader( &ustub, u_cols, u_rows, type, buffer + u_buf_offset*pix_size );
        u = &ustub;
    }

    if( !tw )
        tw = buffer + (n + m)*pix_size;

    if( type == CV_32FC1 )
    {
        icvSVD_32f( a->data.fl, a->step/sizeof(float), a->rows, a->cols,
                   (float*)tw, u->data.fl, u->step/sizeof(float), u_cols,
                   v->data.fl, v->step/sizeof(float), (float*)buffer );
    }
    else if( type == CV_64FC1 )
    {
        icvSVD_64f( a->data.db, a->step/sizeof(double), a->rows, a->cols,
                    (double*)tw, u->data.db, u->step/sizeof(double), u_cols,
                    v->data.db, v->step/sizeof(double), (double*)buffer );
    }
    else
    {
        CV_ERROR( CV_StsUnsupportedFormat, "" );
    }

    if( tw != w->data.ptr )
    {
        int shift = w->cols != 1;
        cvSetZero( w );
        if( type == CV_32FC1 )
            for( int i = 0; i < n; i++ )
                ((float*)(w->data.ptr + i*w->step))[i*shift] = ((float*)tw)[i];
        else
            for( int i = 0; i < n; i++ )
                ((double*)(w->data.ptr + i*w->step))[i*shift] = ((double*)tw)[i];
    }

    if( uarr )
    {
        if( !(flags & CV_SVD_U_T))
            cvT( u, uarr );
        else if( temp_u )
            cvCopy( u, uarr );
        /*CV_CHECK_NANS( uarr );*/
    }

    if( varr )
    {
        if( !(flags & CV_SVD_V_T))
            cvT( v, varr );
        /*CV_CHECK_NANS( varr );*/
    }

    CV_CHECK_NANS( w );

    __END__;

    if( buffer && !local_alloc )
        cvFree( &buffer );
}
Ejemplo n.º 3
0
CV_IMPL  void
cvSVD( CvArr* aarr, CvArr* warr, CvArr* uarr, CvArr* varr, int flags )
{
    uchar* buffer = 0;
    int local_alloc = 0;

    CV_FUNCNAME( "cvSVD" );

    __BEGIN__;

    CvMat astub, *a = (CvMat*)aarr;
    CvMat wstub, *w = (CvMat*)warr;
    CvMat ustub, *u = (CvMat*)uarr;
    CvMat vstub, *v = (CvMat*)varr;
    CvMat tmat;
    uchar* tw = 0;
    int type, nm, mn;
    int buf_size, pix_size;
    int t_svd = 0; // special case: a->rows < a->cols

    if( !CV_IS_ARR( a ))
        CV_CALL( a = cvGetMat( a, &astub ));

    if( !CV_IS_ARR( w ))
        CV_CALL( w = cvGetMat( w, &wstub ));

    if( !CV_ARE_TYPES_EQ( a, w ))
        CV_ERROR( CV_StsUnmatchedFormats, "" );

    nm = MIN( a->width, a->height );
    mn = MAX( a->width, a->height );

    if( (w->width == 1 || w->height == 1) &&
        CV_IS_ARR_CONT( w->type ) && w->width*w->height == nm )
    {
        tw = w->data.ptr;
    }
    else if( !CV_ARE_SIZES_EQ( w, a ))
    {
        CV_ERROR( CV_StsBadSize, "W must be either continuous vector of "
                                 "size MIN(A->width,A->height) or matrix of "
                                 "the same size as A" );
    }

    if( u )
    {
        if( !CV_IS_ARR( u ))
            CV_CALL( u = cvGetMat( u, &ustub ));

        if( !CV_ARE_TYPES_EQ( a, u ))
            CV_ERROR( CV_StsUnmatchedFormats, "" );

        if( u->width != u->height || u->height != a->height )
            CV_ERROR( CV_StsUnmatchedSizes, "U matrix must be square and have the same "
                                            "linear size as number of rows in A" );

        if( u->data.ptr == a->data.ptr )
            CV_ERROR( CV_StsBadArg, "U can not be equal A" );
    }
    else
    {
        u = &ustub;
        u->data.ptr = 0;
        u->step = 0;
    }

    if( v )
    {
        if( !CV_IS_ARR( v ))
            CV_CALL( v = cvGetMat( v, &vstub ));

        if( !CV_ARE_TYPES_EQ( a, v ))
            CV_ERROR( CV_StsUnmatchedFormats, "" );

        if( v->width != v->height || v->width != a->width )
            CV_ERROR( CV_StsUnmatchedSizes, "V matrix must be square and have the same "
                                            "linear size as number of columns in A" );

        if( v->data.ptr == a->data.ptr || v->data.ptr == u->data.ptr )
            CV_ERROR( CV_StsBadArg, "V can not be equal U or A" );
    }
    else
    {
        v = &vstub;
        v->data.ptr = 0;
        v->step = 0;
    }

    type = CV_ARR_TYPE( a->type );
    pix_size = icvPixSize[type];
    buf_size = nm*2 + mn;

    if( a->rows < a->cols )
    {
        CvMat* t;
        CV_SWAP( u, v, t );

        flags = (flags & CV_SVD_U_T ? CV_SVD_V_T : 0)|
                (flags & CV_SVD_V_T ? CV_SVD_U_T : 0);

        t_svd = 1;
    }

    if( !(flags & CV_SVD_MODIFY_A) )
        buf_size += a->width*a->height;

    buf_size *= pix_size;

    if( buf_size <= CV_MAX_LOCAL_SIZE )
    {
        buffer = (uchar*)alloca( buf_size );
        local_alloc = 1;
    }
    else
    {
        CV_CALL( buffer = (uchar*)cvAlloc( buf_size ));
    }
    
    if( !(flags & CV_SVD_MODIFY_A) )
    {
        if( !t_svd )
        {
            cvInitMatHeader( &tmat, a->height, a->width, type,
                             buffer + (nm*2 + mn)*pix_size );
            cvCopy( a, &tmat );
        }
        else
        {
            cvInitMatHeader( &tmat, a->width, a->height, type,
                             buffer + (nm*2 + mn)*pix_size );
            cvT( a, &tmat );
        }
        a = &tmat;
    }

    if( !tw )
        tw = buffer + (nm + mn)*pix_size;

    if( type == CV_32FC1 )
    {
        IPPI_CALL( icvSVD_32f( a->data.fl, a->step/sizeof(float), (float*)tw,
                               u->data.fl, u->step/sizeof(float),
                               v->data.fl, v->step/sizeof(float),
                               icvGetMatSize(a), (float*)buffer ));
    }
    else if( type == CV_64FC1 )
    {
        IPPI_CALL( icvSVD_64f( a->data.db, a->step/sizeof(double), (double*)tw,
                               u->data.db, u->step/sizeof(double),
                               v->data.db, v->step/sizeof(double),
                               icvGetMatSize(a), (double*)buffer ));
    }
    else
    {
        CV_ERROR( CV_StsUnsupportedFormat, "" );
    }

    if( tw != w->data.ptr )
    {
        cvSetZero( w );
        if( type == CV_32FC1 )
            for( int i = 0; i < nm; i++ )
                ((float*)(w->data.ptr + i*w->step))[i] = ((float*)tw)[i];
        else
            for( int i = 0; i < nm; i++ )
                ((double*)(w->data.ptr + i*w->step))[i] = ((double*)tw)[i];
    }

    if( u->data.ptr )
    {
        if( !(flags & CV_SVD_U_T))
            cvT( u, u );
        CV_CHECK_NANS( u );
    }

    if( v->data.ptr)
    {
        if( !(flags & CV_SVD_V_T))
            cvT( v, v );
        CV_CHECK_NANS( v );
    }

    CV_CHECK_NANS( w );

    __END__;

    if( buffer && !local_alloc )
        cvFree( (void**)&buffer );
}