c++ - ¿Cómo utiliza OpenCV Eigen?
(2)
Al compilar OpenCV desde el origen, existe la opción CMake WITH_EIGEN, que dice "Incluir soporte Eigen3". Sin embargo, en ninguna parte de la documentación (o con Google, para el caso) puedo averiguar qué hace exactamente esto y cómo usarlo. Puedo imaginar algunas opciones:
¿Puedo seguir usando cv :: Mat, y ciertas funciones (¿cuáles?) Como cv :: Mat :: inv () comenzarán a usar los algoritmos de Eigen.
¿O la bandera WITH_EIGEN básicamente no hace nada y necesito convertir los cv :: Mat''s a Eigen (o usar Eigen :: Map) y luego usar los algoritmos de Eigen manualmente?
Aquí está mi ejemplo de interoperabilidad Eigen + OpenCV, espero que sea útil:
//
#define EIGEN_RUNTIME_NO_MALLOC // Define this symbol to enable runtime tests for allocations
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <vector>
#include <Eigen/IterativeLinearSolvers>
#include <iostream>
#include "opencv2/core/eigen.hpp"
#include "opencv2/opencv.hpp"
using namespace Eigen;
using namespace cv;
using namespace std;
void EnergyFilter(Mat& src,Mat& dst,double alpha)
{
int n_pixels=src.rows*src.cols;
// Image to row-vector
Mat m=src.reshape(1,n_pixels).clone();
// To double
m.convertTo(m,CV_64FC1);
// Eigen vectors
VectorXd I(n_pixels);
VectorXd u(n_pixels);
// convert image from openCV to Eigen
cv2eigen(m,I);
//
SparseMatrix<double> A(n_pixels,n_pixels);
// Fill sparse martix using triplets
typedef Eigen::Triplet<double> T;
std::vector<T> tripletList;
// Filter parameter (smoothing factor)
//double alpha=-0.1;
// Set values
for(int i=0;i<n_pixels;i++)
{
tripletList.push_back(T(i,i,1+4*alpha));
if((i+1) < n_pixels){tripletList.push_back(T(i,i+1,-alpha));} // +1
if((i-1) >= 0){tripletList.push_back(T(i,i-1,-alpha));} // -1
if((i+src.cols) < n_pixels){tripletList.push_back(T(i,i+src.cols,-alpha));} // +3
if((i-src.cols) >= 0){tripletList.push_back(T(i,i-src.cols,-alpha));} // -3
}
// Boundary values of main diag
tripletList.push_back(T(0,0,1+2*alpha));
for(int i=1;i<src.cols;i++)
{
tripletList.push_back(T(i,i,1+3*alpha));
}
//
tripletList.push_back(T(n_pixels-1,n_pixels-1,1+2*alpha));
for(int i=1;i<src.cols;i++)
{
tripletList.push_back(T(i,n_pixels-i-1,1+3*alpha));
}
// Init sparse matrix
A.setFromTriplets(tripletList.begin(),tripletList.end());
tripletList.clear();
// Solver init
ConjugateGradient<SparseMatrix<double> > cg;
cg.compute(A);
// Solve linear systyem
u = cg.solve(I);
std::cout << "#iterations: " << cg.iterations() << std::endl;
std::cout << "estimated error: " << cg.error() << std::endl;
// Get the solution
dst=Mat(n_pixels,1,CV_64FC1);
eigen2cv(u,dst);
dst=dst.reshape(1,src.rows);
dst.convertTo(dst,CV_8UC1);
}
int main(int argc, char* argv[])
{
namedWindow("image");
namedWindow("result");
Mat img=imread("d://ImagesForTest//lena.jpg",1);
imshow("image",img);
waitKey(10);
Mat res;
vector<Mat> ch;
cv::split(img,ch);
for(int i=0;i<3;i++)
{
EnergyFilter(ch[i],res,3);
res.copyTo(ch[i]);
}
cv::merge(ch,res);
// show the resilt
imshow("result",res);
waitKey(0);
return 0;
}
Después de trabajar con él por un tiempo, puedo dar la respuesta:
El indicador WITH_EIGEN no hace nada excepto que las funciones de interoperabilidad de eigen-opencv estén disponibles.
¿Puedo seguir usando cv :: Mat, y ciertas funciones (¿cuáles?) Como cv :: Mat :: inv () comenzarán a usar los algoritmos de Eigen.
No, cv :: Mat :: inv () no tiene lógica inteligente y usará los algoritmos de OpenCV.
¿O la bandera WITH_EIGEN básicamente no hace nada y necesito convertir los cv :: Mat''s a Eigen (o usar Eigen :: Map) y luego usar los algoritmos de Eigen manualmente?
Exactamente, ese es el camino a seguir. Sin embargo, no recomendaría necesariamente usar cv2eigen () y eigen2cv (). Usé Eigen :: Map para solo mapear la memoria (sin costo al copiar nada) y cv :: Mat (void *, ...) para mapear los datos. Sin embargo, tenga cuidado con las banderas de fila / col mayor y esas cosas.