我有几个存储在cv::Mat
中的特征向量,其中每一行都是一个特征向量(这里有几行像这样:[ x1 y1 x2 y2 x3 y3.... ]
)。我必须在每个特征向量上应用SVD,为此我使用特征库。但是,在应用SVD之前,必须将特征矩阵转换为Eigen::Matrix
形式。
稍后,我必须将SVD结果转换回cv::Mat
。
有人可以建议一个很好的方法吗?我需要cv::Mat
形式的原因是因为我必须在OpenCV中将其输入到神经网络,并且只允许cv::Mat
个输入矩阵。
感谢!!!
答案 0 :(得分:5)
来自http://forum.kde.org/viewtopic.php?f=74&t=97516的示例:
#include <opencv2/core/eigen.hpp>
cv::Mat_<float> a = Mat_<float>::ones(2,2);
Eigen::Matrix<float,Dynamic,Dynamic> b;
cv2eigen(a,b);
此外,OpenCV CV::Mat and Eigen::Matrix有一个使用Eigen :: Map的解决方案。
答案 1 :(得分:3)
尝试使用此代码将eigen转换为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, cv::Mat& dst)
{
if (!(src.Flags & Eigen::RowMajorBit))
{
cv::Mat _src(src.cols(), src.rows(), cv::DataType<_Tp>::type,
(void*)src.data(), src.stride() * sizeof(_Tp));
cv::transpose(_src, dst);
}
else
{
cv::Mat _src(src.rows(), src.cols(), cv::DataType<_Tp>::type,
(void*)src.data(), src.stride() * sizeof(_Tp));
_src.copyTo(dst);
}
}
如您所见,这会执行副本。使用小的矩阵你不应该关心,但你可以改变代码。要获取第一列,请使用cv::Mat::column()
。
尝试使用其中一种方法将cv用于特征:
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());
}
}
来源:此代码来自OpenCV本身,它们在内部使用它,因为OpenCV可以在内部使用libeigen来完成某些任务。我不明白为什么格式转换到这样的库和Qt不会通过API公开。
答案 2 :(得分:1)
查看Mapping data from Eigen to OpenCV and back文章。它描述了如何以较少的开销映射数据。在最简单的情况下,根本就没有副本。它也处理特征表达式:
// Unsharp mask
Eigen::ArrayXXd img, blur;
eigen2cv(img) = cv::imread("lena.jpg");
cv::GaussianBlur(eigen2cv(img), eigen2cv(blur));
cv::imshow("sharpened", eigen2cv(1.5 * img - 0.5 * blur));