reality - OpenCV CV:: Mat y Eigen:: Matrix
opencv python tutorial pdf (4)
¡La versión de Pierluigi no me ha funcionado por completo para imágenes de 3 canales! Después de algunas investigaciones, terminé con la siguiente solución que me ha funcionado:
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;
¿Hay alguna forma reversible de convertir un objeto OpenCV cv::Mat
a Eigen::Matrix
?
por ejemplo, alguna forma de hacer:
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);
He intentado usar cv2eigen
y eigen2cv
, pero el cvMat
resultante está completamente destrozado y no estoy muy seguro de por qué. Las dimensiones son correctas, pero los gráficos están totalmente destrozados, por lo que posiblemente haya un problema de bytes por píxel o de tamaño de datos.
Debería considerar usar Eigen :: Map para envolver matrices OpenCV para que el Eigen SDK lo use directamente. Esto le permite aplicar casi todas las funcionalidades implementadas en Eigen en la matriz asignada por OpenCV
En particular, simplemente instancia un Eigen :: Map que proporciona el puntero al buffer 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() );
Para obtener más información sobre Eigen :: Map, eche un vistazo a Eigen Tutorial: Map Class
Puede mapear matrices arbitrarias entre Eigen y OpenCV (sin copiar datos).
Sin embargo, debes tener en cuenta dos cosas:
Eigen se predetermina al almacenamiento de columna principal, OpenCV almacena fila principal. Por lo tanto, utilice el indicador Eigen :: RowMajor al mapear datos de OpenCV.
La matriz OpenCV debe ser continua (es decir, ocvMatrix.isContinuous () debe ser verdadera). Este es el caso si asigna el almacenamiento para la matriz de una vez en la creación de la matriz (por ejemplo, como en mi ejemplo a continuación, o si la matriz es el resultado de una operación como Mat W = A.inv ();)
Ejemplo:
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());
Para matrices multicanal (por ejemplo, imágenes), puede usar ''Stride'' exactamente como Pierluigi sugirió en su comentario.
También puedes usar
void eigen2cv(const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst)
y
void cv2eigen(const Mat& src, Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst)
de #include <opencv2/core/eigen.hpp>
.