How to perform LU-decomposition with OpenCV?

后端 未结 2 1959
隐瞒了意图╮
隐瞒了意图╮ 2021-01-16 00:52

The cvInvert() method takes a flag CV_LU that does the LU factorisation to invert an input matrix. However is there any way to obtain the L and U matrices that are formed du

2条回答
  •  野的像风
    2021-01-16 00:58

    Unfortunately, it doesn't look like OpenCV gives you a way to access the L and U matrices. Here is how the function is implemented. And, it looks like for performance reasons LU-decomposition is done in-place. So, you will probably have to do it on your own.

    EDIT: It appears that after looking at both how Matlab and Eigen do LU-decomposition you can actually retrieve them after the cvInvert call. The L matrix is the strictly lower-triangle matrix of the result plus the Identity matrix, and the U matrix is the upper triangle matrix.

    EDIT: Eigen actually integrates fairly well with OpenCV. And, it appears they have an LU decomposition class implemented here. Eigen is already a dependency for OpenCV if you built it yourself, you should have it available to use (it's completely implemented in header files, so that makes it really easy to use). There is also an OpenCV header implementing the conversion between Eigen matrices and OpenCV matrices @ #include .

    However, at least on my SVN build, this header didn't work right, so I made my own:

    #ifndef __OPENCV_CORE_EIGEN_HPP__
    #define __OPENCV_CORE_EIGEN_HPP__
    
    #ifdef __cplusplus
    
    #include "opencv/cxcore.h"
    #include 
    
    namespace cv
    {
    
    template
    void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst )
    {
        if( !(src.Flags & Eigen::RowMajorBit) )
        {
            Mat _src(src.cols(), src.rows(), DataType<_Tp>::type,
                  (void*)src.data(), src.stride()*sizeof(_Tp));
            transpose(_src, dst);
        }
        else
        {
            Mat _src(src.rows(), src.cols(), DataType<_Tp>::type,
                     (void*)src.data(), src.stride()*sizeof(_Tp));
            _src.copyTo(dst);
        }
    }
    
    template
    void cv2eigen( const Mat& src,
                   Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst )
    {
        CV_DbgAssert(src.rows == _rows && src.cols == _cols);
        if( !(dst.Flags & Eigen::RowMajorBit) )
        {
            Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
                     dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            if( src.type() == _dst.type() )
                transpose(src, _dst);
            else if( src.cols == src.rows )
            {
                src.convertTo(_dst, _dst.type());
                transpose(_dst, _dst);
            }
            else
                Mat(src.t()).convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
        else
        {
            Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
                     dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            src.convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
    }
    
    template
    void cv2eigen( const Mat& src,
                   Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst )
    {
        dst.resize(src.rows, src.cols);
        if( !(dst.Flags & Eigen::RowMajorBit) )
        {
            Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
                 dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            if( src.type() == _dst.type() )
                transpose(src, _dst);
            else if( src.cols == src.rows )
            {
                src.convertTo(_dst, _dst.type());
                transpose(_dst, _dst);
            }
            else
                Mat(src.t()).convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
        else
        {
            Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
                     dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            src.convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
    }
    
    
    template
    void cv2eigen( const Mat& src,
                   Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst )
    {
        CV_Assert(src.cols == 1);
        dst.resize(src.rows);
    
        if( !(dst.Flags & Eigen::RowMajorBit) )
        {
            Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
                     dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            if( src.type() == _dst.type() )
                transpose(src, _dst);
            else
                Mat(src.t()).convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
        else
        {
            Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
                     dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            src.convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
    }
    
    
    template
    void cv2eigen( const Mat& src,
                   Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst )
    {
        CV_Assert(src.rows == 1);
        dst.resize(src.cols);
        if( !(dst.Flags & Eigen::RowMajorBit) )
        {
            Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
                     dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            if( src.type() == _dst.type() )
                transpose(src, _dst);
            else
                Mat(src.t()).convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
        else
        {
            Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
                     dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
            src.convertTo(_dst, _dst.type());
            CV_DbgAssert(_dst.data == (uchar*)dst.data());
        }
    }
    
    }
    
    #endif
    
    #endif
    

    Hopefully that is helpful to you!

提交回复
热议问题