cvInvert() 方法采用标志 CV_LU 进行 LU 分解以反转输入矩阵。但是,有没有办法获得在此计算过程中形成的 L 和 U 矩阵?为 LU 分解编写一个新函数似乎毫无意义,因为 OpenCV 已经为其优化了代码。
问问题
3202 次
2 回答
2
可以使用Cholesky()
OpenCV 提供的功能(使用 2.4.6),见modules\stitching\src\autocalib.cpp
. 但它需要一些缩放才能获得与 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;
}
}
于 2013-07-11T07:40:40.417 回答
2
不幸的是,OpenCV 似乎没有为您提供访问 L 和 U 矩阵的方法。以下是该功能的实现方式。而且,出于性能原因,LU 分解似乎是就地完成的。所以,你可能不得不自己做。
编辑:看起来,在查看了 Matlab 和 Eigen 如何进行 LU 分解之后,您实际上可以在 cvInvert 调用之后检索它们。L矩阵是结果加上Identity矩阵的严格下三角矩阵,U矩阵是上三角矩阵。
编辑: Eigen实际上与 OpenCV 集成得很好。而且,他们似乎在这里实现了一个 LU 分解类。如果您自己构建 Eigen,它已经是 OpenCV 的依赖项,您应该可以使用它(它完全在头文件中实现,因此非常易于使用)。还有一个 OpenCV 标头实现了 Eigen 矩阵和 OpenCV 矩阵 @ 之间的转换#include <opencv2/core/eigen.hpp>
。
然而,至少在我的 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
希望这对您有帮助!
于 2011-10-22T19:10:21.797 回答