C++ OpenCV CV::Mat 和 Eigen::Matrix
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14783329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
OpenCV CV::Mat and Eigen::Matrix
提问by Yeraze
Is there a reversible way to convert an OpenCV cv::Mat
object to an Eigen::Matrix
?
是否有可逆的方式将 OpenCVcv::Mat
对象转换为Eigen::Matrix
?
e.g., Some way of doing:
例如,某种做法:
cv::Mat cvMat;
Eigen::Matrix eigMat;
camera->retrieve(cvMat);
// magic to convert cvMat to eigMat
// work on eigMat
// convert eigMat back to cvMat
imshow("Image", cvMat);
I've tried using cv2eigen
and eigen2cv
, but the resulting cvMat
is completely mangled and I'm not exactly sure why. The dimensions are correct, but the graphics are totally trashed, so possibly a bytes-per-pixel or datasize issue?
我试过使用cv2eigen
and eigen2cv
,但结果cvMat
完全混乱,我不确定为什么。尺寸是正确的,但图形完全被破坏了,所以可能是每像素字节或数据大小问题?
采纳答案by Pierluigi
You should consider using Eigen::Map to wrap OpenCV matrices in order to be used directly by the Eigen SDK. This allows you to apply almost all functionalities implemented in Eigen on matrix allocated by OpenCV
您应该考虑使用 Eigen::Map 来包装 OpenCV 矩阵,以便由 Eigen SDK 直接使用。这允许您将 Eigen 中实现的几乎所有功能应用到 OpenCV 分配的矩阵上
In particular you simply instantiate an Eigen::Map providing the pointer to the cv::Mat buffer:
特别是,您只需实例化一个 Eigen::Map 提供指向 cv::Mat 缓冲区的指针:
//allocate memory for a 4x4 float matrix
cv::Mat cvT(4,4,CV_32FC1);
//directly use the buffer allocated by OpenCV
Eigen::Map<Matrix4f> eigenT( cvT.data() );
for more information on Eigen::Map take a look at Eigen Tutorial: Map Class
有关 Eigen::Map 的更多信息,请查看 Eigen 教程:地图类
回答by CodeFinder
You can also use
你也可以使用
void eigen2cv(const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst)
and
和
void cv2eigen(const Mat& src, Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst)
from #include <opencv2/core/eigen.hpp>
.
从#include <opencv2/core/eigen.hpp>
.
回答by Ela782
You can map arbitrary matrices between Eigen and OpenCV (without copying data).
您可以在 Eigen 和 OpenCV 之间映射任意矩阵(无需复制数据)。
You have to be aware of two things though:
不过,你必须注意两件事:
Eigen defaults to column-major storage, OpenCV stores row-major. Therefore, use the Eigen::RowMajor flag when mapping OpenCV data.
The OpenCV matrix has to be continuous (i.e. ocvMatrix.isContinuous() needs to be true). This is the case if you allocate the storage for the matrix in one go at the creation of the matrix (e.g. as in my example below, or if the matrix is the result of a operation like Mat W = A.inv();)
Eigen 默认为列优先存储,OpenCV 存储行优先。因此,在映射 OpenCV 数据时使用 Eigen::RowMajor 标志。
OpenCV 矩阵必须是连续的(即 ocvMatrix.isContinuous() 需要为真)。如果您在创建矩阵时一次性为矩阵分配存储,就会出现这种情况(例如,在我下面的示例中,或者如果矩阵是像 Mat W = A.inv(); 这样的操作的结果)
Example:
例子:
Mat A(20, 20, CV_32FC1);
cv::randn(A, 0.0f, 1.0f); // random data
// Map the OpenCV matrix with Eigen:
Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> A_Eigen(A.ptr<float>(), A.rows, A.cols);
// Do something with it in Eigen, create e.g. a new Eigen matrix:
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> B = A_Eigen.inverse();
// create an OpenCV Mat header for the Eigen data:
Mat B_OpenCV(B.rows(), B.cols(), CV_32FC1, B.data());
For multi-channel matrices (e.g. images), you can use 'Stride' exactly as Pierluigi suggested in his comment!
对于多通道矩阵(例如图像),您可以完全按照 Pierluigi 在他的评论中建议的那样使用“Stride”!
回答by GPrathap
This works for me,
这对我有用,
#include <opencv2/core/eigen.hpp>
cv::Mat image;
image = cv::imread("/dataset/images/15207_angle_image.jpg", CV_LOA D_IMAGE_GRAYSCALE); // Read the file
Eigen::Matrix<float,Eigen::Dynamic, Eigen::Dynamic> eigen_mat;
cv::cv2eigen(image, eigen_mat);
回答by Benjamin J?hn
Pierluigi's version has not worked for me completely for 3 channel images! After some investigation I ended with the following solution which has worked for me:
对于 3 通道图像,Pierluigi 的版本对我来说并不完全适用!经过一番调查,我以以下对我有用的解决方案结束:
using namespace Eigen;
constexpr uint32_t height = 3;
constexpr uint32_t width = 7;
cv::Mat img(height, width, CV_32FC3, cv::Scalar(1.0f, 2.0f, 3.0f));
using MatrixXfRowMajor = Matrix<float, Dynamic, Dynamic, RowMajor>;
using C3Stride = Stride<Dynamic, 3>;
C3Stride c3Stride(width *3,3);
using cvMap = Map<MatrixXfRowMajor, Unaligned, C3Stride >;
cvMap imgC1(reinterpret_cast<float*>(img.data) + 0, img.rows, img.cols, c3Stride);
cvMap imgC2(reinterpret_cast<float*>(img.data) + 1, img.rows, img.cols, c3Stride);
cvMap imgC3(reinterpret_cast<float*>(img.data) + 2, img.rows, img.cols, c3Stride);
std::cout << imgC1 << std::endl << std::endl;
std::cout << imgC2 << std::endl << std::endl;
std::cout << imgC3 << std::endl << std::endl;