C++ OpenCV如何利用Eigen?

C++ OpenCV如何利用Eigen?,c++,opencv,eigen,C++,Opencv,Eigen,当从源代码处编译OpenCV时,有一个带有_-EIGEN的CMake选项,上面写着“包括Eigen3支持”。然而,在文档中(或者谷歌的文档中),我找不到它的确切用途以及如何使用它。我可以想象一些选择: 我是否可以继续使用cv::Mat,某些函数(哪些函数?)如cv::Mat::inv()将开始使用Eigen中的算法 或者WITH_EIGEN标志基本上不起作用,我需要将cv::Mat转换为EIGEN(或使用EIGEN::Map),然后手动使用EIGEN算法吗?这是我的EIGEN+OpenCV互操作

当从源代码处编译OpenCV时,有一个带有_-EIGEN的CMake选项,上面写着“包括Eigen3支持”。然而,在文档中(或者谷歌的文档中),我找不到它的确切用途以及如何使用它。我可以想象一些选择:

我是否可以继续使用cv::Mat,某些函数(哪些函数?)如cv::Mat::inv()将开始使用Eigen中的算法


或者WITH_EIGEN标志基本上不起作用,我需要将cv::Mat转换为EIGEN(或使用EIGEN::Map),然后手动使用EIGEN算法吗?

这是我的EIGEN+OpenCV互操作性示例,希望它有用:

//
#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;
}
//
#定义EIGEN_RUNTIME_NO_MALLOC//定义此符号以启用分配的运行时测试
#包括
#包括
#包括
#包括
#包括
#包括“opencv2/core/eigen.hpp”
#包括“opencv2/opencv.hpp”
使用名称空间特征;
使用名称空间cv;
使用名称空间std;
真空能量过滤器(Mat和src、Mat和dst、双阿尔法)
{
int n_pixels=src.rows*src.cols;
//图像到行向量
Mat m=src.reformate(1,n_像素).clone();
//加倍
m、 convertTo(m,CV_64FC1);
//特征向量
矢量xd I(n_像素);
矢量xd u(n_像素);
//将图像从openCV转换为Eigen
cv2eigen(m,I);
// 
稀疏矩阵A(n_像素,n_像素);
//使用三元组填充稀疏的martix
typedef本征::三重态T;
std::向量三元组列表;
//滤波器参数(平滑因子)
//双α=-0.1;
//设定值
对于(inti=0;i=0){triplelist.push_-back(T(i,i-1,-alpha));}/-1
if((i+src.cols)=0){triplelist.push_back(T(i,i-src.cols,-alpha));}/-3
}
//主对角线的边值
三重列表。向后推(T(0,0,1+2*alpha));

对于(int i=1;i在使用它一段时间后,我可以提供以下答案:

WITH_EIGEN标志除了使EIGEN opencv互操作性函数可用外,什么都不做

我是否可以继续使用cv::Mat,某些函数(哪些函数?)如cv::Mat::inv()将开始使用Eigen中的算法

否,cv::Mat::inv()没有智能逻辑,将使用OpenCV算法

或者WITH_EIGEN标志基本上不起作用,我需要将cv::Mat转换为EIGEN(或者使用EIGEN::Map),然后手动使用EIGEN算法

没错,这就是路。
不过,我不一定推荐使用cv2eigen()和eigen2cv()。我使用Eigen::Map只是映射内存(复制任何内容都不需要花费成本)和cv::Mat(void*,…)要映射回数据。请小心使用行/列主标志和其他内容。

是的,这很有用,谢谢您提供的示例。但是,我知道这类示例,但它并没有回答我的问题:OCV如何使用eGen。我猜答案是:没有!使用_eGen编译只意味着您将有权访问interop-f函数和特征头。除非有人知道的比我多。要在不复制数据的情况下正确映射特征和cv::Mat,请参见我的答案: