简体   繁体   English

如何使用OpenCV执行LU分解?

[英]How to perform LU-decomposition with OpenCV?

The cvInvert() method takes a flag CV_LU that does the LU factorisation to invert an input matrix. cvInvert()方法采用一个标志CV_LU,它执行LU分解以反转输入矩阵。 However is there any way to obtain the L and U matrices that are formed during this computation? 但是有没有办法获得在这个计算过程中形成的L和U矩阵? Is seems pointless to write a new function for LU-decomposition is OpenCV already has optimized code for it. 为LU分解编写新函数似乎毫无意义,OpenCV已经为它编写了优化代码。

It is possible to use the function Cholesky() provided by OpenCV (using 2.4.6), see source code of modules\\stitching\\src\\autocalib.cpp . 可以使用OpenCV提供的函数Cholesky() (使用2.4.6),参见modules\\stitching\\src\\autocalib.cpp源代码。 But it needs some scaling to get a comparable result with Matlab: 但它需要一些扩展来获得与Matlab相似的结果:

Mat chol = mat.clone();
if (Cholesky(chol.ptr<float>(), chol.step, chol.cols, 0, 0, 0))
{
    Mat diagElem = chol.diag();
    for (int e = 0; e < diagElem.rows; ++e)
    {
        float elem = diagElem.at<float>(e);
        chol.row(e) *= elem;
        chol.at<float>(e,e) = 1.0f / elem;
    }
}

Unfortunately, it doesn't look like OpenCV gives you a way to access the L and U matrices. 不幸的是,它看起来并不像OpenCV为您提供了访问L和U矩阵的方法。 Here is how the function is implemented. 以下是该功能的实现方式。 And, it looks like for performance reasons LU-decomposition is done in-place. 并且,出于性能原因,看起来LU分解是就地完成的。 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. 编辑:看来,在查看Matlab和Eigen如何进行LU分解后,您可以在cvInvert调用后实际检索它们。 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. L矩阵是结果的严格下三角矩阵加上Identity矩阵,U矩阵是上三角矩阵。

EDIT: Eigen actually integrates fairly well with OpenCV. 编辑: Eigen实际上与OpenCV很好地集成。 And, it appears they have an LU decomposition class implemented here . 并且,它们似乎在这里实现了LU分解类。 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). 如果您自己构建,Eigen已经是OpenCV的依赖项,您应该可以使用它(它完全在头文件中实现,因此使其非常易于使用)。 There is also an OpenCV header implementing the conversion between Eigen matrices and OpenCV matrices @ #include <opencv2/core/eigen.hpp> . 还有一个OpenCV头实现了特征矩阵和OpenCV矩阵@ #include <opencv2/core/eigen.hpp>之间的转换。

However, at least on my SVN build, this header didn't work right, so I made my own: 但是,至少在我的SVN版本中,这个标题不能正常工作,所以我自己做了:

#ifndef __OPENCV_CORE_EIGEN_HPP__
#define __OPENCV_CORE_EIGEN_HPP__

#ifdef __cplusplus

#include "opencv/cxcore.h"
#include <eigen3/Eigen/Dense>

namespace cv
{

template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
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<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
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<typename _Tp>
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<typename _Tp>
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<typename _Tp>
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! 希望这对你有所帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM