web-dev-qa-db-ja.com

OpenCVはEigenをどのように利用しますか?

ソースからOpenCVをコンパイルする場合、「Eigen3サポートを含める」というCMakeオプションWITH_EIGENがあります。しかし、ドキュメントのどこにも(またはグーグルでは)これが正確に何をするのか、そしてそれをどのように使用するのかを知ることはできません。私はいくつかのオプションを想像することができます:

Cv :: Matを使い続けることはできますか?cv :: Mat :: inv()のような特定の関数(どれですか?)はEigenのアルゴリズムの使用を開始しますか?

または、WITH_EIGENフラグは基本的に何もせず、cv :: MatをEigenに変換して(またはEigen :: Mapを使用して)、Eigenのアルゴリズムを手動で使用する必要がありますか?

15
Ela782

少し作業した後、私は答えを提供することができます:

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 *、...)を使用してデータをマップし直しました。ただし、row/col-majorフラグなどには注意してください。

18
Ela782

これが私の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;
}
5
Andrey Smorodov