cvInvert()メソッドは、入力行列を反転するためにLU分解を行うフラグCV_LUを取ります。しかし、この計算中に形成されるLおよびU行列を取得する方法はありますか?LU分解のための新しい関数を書くことは無意味に思えます。OpenCVはすでにそれのために最適化されたコードを持っています。
2 に答える
残念ながら、OpenCVがLおよびUマトリックスにアクセスする方法を提供しているようには見えません。関数の実装方法は次のとおりです。また、パフォーマンス上の理由から、LU分解はインプレースで行われているように見えます。だから、あなたはおそらくあなた自身でそれをしなければならないでしょう。
編集: MatlabとEigenの両方がLU分解を行う方法を確認した後、cvInvert呼び出し後に実際にそれらを取得できるようです。L行列は、結果と単位行列の厳密に下三角行列であり、U行列は上三角行列です。
編集: Eigenは実際にはOpenCVとかなりうまく統合されています。そして、ここにLU分解クラスが実装されているようです。Eigenは、自分でビルドした場合、すでにOpenCVの依存関係になっているので、使用できるようにする必要があります(ヘッダーファイルに完全に実装されているため、非常に使いやすくなっています)。Eigen行列とOpenCV行列@の間の変換を実装する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
うまくいけば、それはあなたに役立つでしょう!
OpenCVが提供する機能Cholesky()
(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;
}
}