[英]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.