Eigen是一个C++开源库,支持线性代数,矩阵运算,数值分析,矢量计算等一系列算法,方便使用者实现一些复杂的运算
Eigen 头文件说明如下:
部分函数用法:
MatrixXd : 定义一个二维矩阵,行列未知,初始化时需指定数组的行和列(double型)
Matrix2cf:定义2x2的方阵(复数,float型)
Matrix2f :定义2x2的方阵(float型) Matrix2i: 定义2x2的方阵(int型) Matrix2Xf : 定义2行N列的矩阵(float型,N值不确定) 数字代表nn方阵的大小,‘X’代表这个矩阵不是方阵,是一个mn的矩阵,‘d’代表double,‘f’代表float, ‘i’代表整数,‘c’代表complex,即复数; 简单用法: 1、数据初始化与访问 MatrixXf tmp = MatrixXf::Random(3,4); //定义3x4的float型的随机数矩阵 cout<<"tmp:\n"<<tmp<<endl;
Matrix4f result = Matrix4f(); //定义一个4*4的 float 的方阵 result(0,1)=1; //单个元素访问赋值 cout<<"result\n"<<result<<endl;
Matrix2Xd res= Matrix2Xd(2,3); //初始化一个2行n列的数组,第一个参数必须是2,否则报错 cout<<"res\n"<<res<<endl<<" res.szie:"<<res.size()<<" " <<"res.row\\col:"<<res.rows()<<","<<res.cols()<<endl; //res.size() 返回的是总的元素个数,不是矩阵的shape (获取行列用res.rows(),res.cols())
MatrixXd m = MatrixXd::Constant(7, 7, 0); //初始化一个矩阵7*7 初始值全为0 cout << "EigenMat:" << endl << m << endl; m(1,1) =1; //直接访问修改 m(2,2) = m(0,0)+m(0,1); //矩阵元素做加法 cout << "EigenModify:" << endl << m << endl; MatrixXd m1 = MatrixXd::Random(3, 3); //初始化3*3 大小的随机矩阵,范围都在(-1,1)之间 m1 = (m1 + MatrixXd::Constant(3, 3, 2)) * 50; //将m1每个元素加上常数2再乘50,随机数会变为(50,150)之间
2、元素级操作(取绝对值,开方),将Matrix矩阵与常数比较
float th =0.2; //比较阈值 MatrixXf p1= MatrixXf::Constant(3, 4, 0.5); //定义一个3*4的常量数组0.5 cout<<"tmparr: \n"<<tmp.array()<<endl<<"sqrt(temp):\n"<<sqrt(abs(tmp.array()))<<endl;//元素级别操作需要转换到array ,这里的tmp 上面已经定义过 cout<<p1.array().min(tmp.array().abs().sqrt())<<endl; //返回p1和tmp.abs().sqrt()两个数组中对应元素较小的那个值(这里即将所有元素和0.5进行比较,取小的值) MatrixXf p2 = p1.array().min(tmp.array().abs().sqrt()).matrix(); //将得到的比较结果转换回MatrixXf类型 cout<<"p2 -MatrixXf\n"<<p2<<endl; auto mapp = tmp.array()>th; //将整个矩阵和某个阈值比较,满足条件,返回1,否者返回0 cout<<"mapp:\n"<<mapp<<endl;
3、tensor 定义及操作,Matrix转换成Tensor
Eigen::Tensor<float,2> pd1(3,4); //定义一个3*4的tensor ,2代表维度 pd1(0,2) = 3; pd1(1,2) = 4; auto cmp = pd1>2; //auto自动接收类型 找出pd1中值大于2的元素,其余值赋0 ,tensor可以直接和常数比较,Matrix 不行,需要先转成array cout<<"pd1: \n"<<pd1<<endl; Eigen::Tensor<float, 2> cmp2 = cmp.cast<float>(); //有文档说需要实例化变量类型转换一下,否则会编译报错(不过我这里直接输出cmp也是可以的) cout<<"cmp: \n"<<cmp<<endl; //直接输出比较矩阵 cout<<"cmp2: \n"<<cmp2<<endl; //将auto 转换为 Tensor<float,2> 2维张量输出
Matrix矩阵转换成tensor (TensorMap) TensorMap<Tensor<float,2>> MatrixXtoTensor(tmp.data(),3,4);//将MatrixXf 转换为3*4的二维tensor cout<<"MatrixXtoTensor :\n"<<MatrixXtoTensor<<endl;
4、向量初始化与操作,向量转换成tensor 或 Matrix
VectorXd v(3);//初始化一条向量(长度为3) v<<1,2,3; cout<<"v:\n"<<v<<endl; Vector3f v1(5.5,4.3,6.7);//定义三行1列的向量,数据个数要和变量类型对应上 cout<<"v1= "<<v1<<endl; auto eigenTensorMap =TensorMap<Tensor<float, 2, Eigen::RowMajor>> (v1.data(), 2,2); //将vector v1 转换成2*2的Tensor 行优先,不足的元素,会自动填充 cout<<"eigenTensorMap RowMajor: \n"<<eigenTensorMap<<endl; auto eigenTensorMap1 =TensorMap<Tensor<float, 2, Eigen::ColMajor>> (v1.data(), 2,2);//将vector v1 转换成2*2的Tensor 列优先 ,不足的元素,会自动填充 cout<<"eigenTensorMap ColMajor: \n"<<eigenTensorMap1<<endl; auto eigenMap = Eigen::Map<MatrixX<float>> (v1.data(), 3,3); //将vector v1转换为MatrixX类型 3*3的 cout<<"eigenMap :\n"<<eigenMap<<endl;
5、Opencv::Mat 与 Eigen::MatrixX 互相转换 ,Matrix数据块操作 注意:头文件顺序不能写反,否则编译失败
#include <Eigen/Dense> #include <opencv2/core/eigen.hpp> cv::Mat ImageMat, OutPutMat; ImageMat = cv::imread("D:/pic/test.png", 0); cv::imshow("原图", ImageMat); cv::waitKey(0); Mat Min=Mat(round(ImageMat.rows*0.1),round(ImageMat.cols*0.1),CV_16S); //定义缩小后的图片大小 short型16bit cv::Size dsize = cv::Size(Min.rows,Min.cols); // cv::Size 定义 cv::resize(ImageMat,Min,dsize,0.1,0.1); //resize ImageMat大小变为1/10,行、列分别缩小1/10 imshow("min",Min); cv::waitKey(0); Eigen::MatrixXd Matrixs(Min.rows, Min.cols); cv2eigen(Min, Matrixs); //将缩小后的图像Min 转换为eigen::MatrixXd cout<<"cv2eigen:"<<endl<<Min<<endl; //如下所示为行列各缩小为1/10 后的图像数据
MatrixXd mmm = MatrixXd::Constant(30,30,0); //定义30*30的0矩阵 mmm(1,1)=1; mmm(1,2)=1; mmm(2,1)=1; mmm(2,2)=1 ; mmm.block(3,3,10,10) = MatrixXd::Constant(10,10,1); //块操作 以(3,3)为起点(左上角点),10x10块区域内赋值常数1 mmm.block<4,4>(15,15) = MatrixXd::Constant(4,4,1); //和上面一样也是块操作,另一种表达方式,以(15,15)为起点,4x4区域内赋值常数1 cv::Mat cvm = Mat(30, 30, CV_8U); //定义Mat大小,接收数据 eigen2cv(mmm, cvm); imshow("cvm",cvm); waitKey(0); cout << "cvMat:" << endl << cvm << endl; 如下图所示在30*30区域内显示为白色的,就是修改为1的部分。
6、Matrix 行列单独操作, 矩阵边角矩阵获取(左上,右下,前N行,后N列)
MatrixXd tt = MatrixXd::Constant(4,4,1); tt.row(1)+= tt.row(2); cout<<"行列操作:\n"<<tt<<endl; //边角子矩阵提取 左上角:topLeftCorner(p,q) 左下角:bottomLeftCorner(p,q) 右上角:topRightCorner(p,q) 右下角:topRightCorner(p,q) //前p行:topRows(p) 后p行:bottomRows(p) 前q列:leftCols(q) 后q列:leftCols(q) cout<<"tt左上(2,2):\n"<<tt.topLeftCorner(2,2)<<"\ntt前两行:\n"<<tt.topRows(2)<<endl;
7、切片操作,向量vector和Matrix矩阵切片都是通过 Map 实现 (Eigen默认采用列主导(column major)的数据存储形式)
RowVectorXf p = RowVectorXf::LinSpaced(20,0,19); //行向量 长度20,范围[0,19] cout << "Input:" << endl << p << endl; Map<RowVectorXf,0,InnerStride<2> > v2(p.data(), p.size()/2); //步长为2进行获取 v.data() 长度为v.size/2 //参数0代表数据对其格式,参数InnerStride代表沿着数据存储的方向间隔2步长取值 cout << "Even:" << v2 << endl; MatrixXf M1 = MatrixXf::Random(3,8); //默认存储方式列优先 //innerStride既表示沿着矩阵的数据存储方向移动一个元素的位置,在内存中需要移动的次数。outerStride的含义就是不沿着数据存储方向移动一个位置,在内存中需要移动的次数 cout << "Column major input:" << endl << M1 << "\n"; cout<<"innerStride="<<M1.innerStride()<<endl; cout<<"outerstride=" <<M1.outerStride()<<endl; Map<MatrixXf,0,OuterStride<> > M2(M1.data(), M1.rows(), (M1.cols()/3+1),OuterStride<>(M1.outerStride() * 3)); //代表 将M1矩阵的元素映射到M2,行不变,列为间隔3列取,在M1上取元素需要在行方向上一次移动步长为原来的3倍(因为是列优先存储的,间隔9个才取下一列) cout << "间隔3列切片 M2" << endl << M2 << endl;
标签:定义,Eigen,Min,cout,矩阵,笔记,学习,cv,MatrixXd From: https://www.cnblogs.com/victorywr/p/16986227.html