eigen 列向量转矩阵_快速入门矩阵运算——开源库Eigen
矩陣是數(shù)學(xué)中一個(gè)重要的工具,廣泛應(yīng)用于各種場(chǎng)景下的數(shù)值分析,例如,數(shù)字信號(hào)處理,圖像處理等。我們?nèi)绾卧诔绦蛑惺褂镁仃囘M(jìn)行運(yùn)算呢?本文將為大家介紹一個(gè)開(kāi)源的矩陣運(yùn)算工具——Eigen。
Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms.
Eigen是一個(gè)用于線性運(yùn)算的C++ 模板庫(kù),支持 矩陣和矢量運(yùn)算,數(shù)值分析及其相關(guān)的算法。
安裝Eigen比較簡(jiǎn)單需要,從官網(wǎng)下載源碼并解壓即可,我現(xiàn)在的是最新的eigen-3.3.7版本。
官網(wǎng)下載地址:
http://eigen.tuxfamily.org/index.php?title=Main_Page
我們可以進(jìn)入Eigen目錄,可以發(fā)現(xiàn)Eigen庫(kù)主要包括如下幾個(gè)模塊組成:
- Core:Matrix和Array類,基礎(chǔ)的線性代數(shù)運(yùn)算和數(shù)組操作;
- Geometry:旋轉(zhuǎn),平移,縮放,2維和3維的各種變換;
- LU:求逆,行列式,LU分解;
- Cholesky:LLT和LDLT Cholesky分解;
- Householder:Householder變換;
- SVD:SVD分解;
- QR:QR分解。
- Eigenvalues:特征值,特征向量分解。
- Sparse:稀疏矩陣的存儲(chǔ)和運(yùn)算。
- Dense:包含了Core、Geometry、LU、Cholesky、SVD、QR、Eigenvalues等模塊。
- Eigen:包含了Dense和Sparse模塊。
Eigen的食用方法非常之簡(jiǎn)單,在使用時(shí)我們只需要從解壓后的文件目錄中找到需要使用的庫(kù),然后,在源代碼中包含相應(yīng)的庫(kù)即可食用了。因?yàn)镋igen是用模板寫(xiě)的模板庫(kù),所以只能把頭文件包含進(jìn)來(lái)使用。W君是在工程工作目錄解壓的,請(qǐng)參考如下代碼包含Eigen庫(kù)。
#include "eigen_3_3_7/Eigen/Eigen"Matrix和Array模板類
Eigen庫(kù)提供有Matrix和Array兩種模板類。它們定義如下:
typedef Matrix MyMatrixType;typedef Array MyArrayType;其中,通常我們會(huì)根據(jù)需要設(shè)置前三個(gè)參數(shù),其它為默認(rèn)值即可。
- Scalar:指定元素類型,比如,float, double, bool, int 等。
- RowsAtCompileTime:指定行數(shù)或者設(shè)置成動(dòng)態(tài)(Dynamic);
- ColsAtCompileTime:指定列數(shù)或者設(shè)置成動(dòng)態(tài)(Dynamic);
- Options:標(biāo)志位,可以是ColMajor或RowMajor,默認(rèn)是ColMajor;
從上面可以看出,行數(shù)和列數(shù)是允許固定大小,也允許動(dòng)態(tài)大小的,所以下面的幾種類型是可以的。
MatrixMatrixMatrixMatrixArrayArray另外,我們還可以使用Eigen庫(kù)已經(jīng)重定義的類型,下面是一些簡(jiǎn)單的例子可參考。
矩陣的定義和初始化
下面我們先看看Matrix模板類,它包含矩陣(Matrix)和向量(Vector),對(duì)于Vector來(lái)說(shuō),它也是一個(gè)矩陣,不過(guò)特殊的是行或者列數(shù)為1,我們稱作行向量或者列向量。接下來(lái)我們來(lái)寫(xiě)個(gè)程序來(lái)看一下。
#include #include "eigen_3_3_7/Eigen/Eigen"int main(){ Eigen::MatrixXf matrix1(3,4); //定義了矩陣的大小,但是沒(méi)有初始化。 Eigen::Vector3f vector1; matrix1 = Eigen::MatrixXf::Zero(3,4); //對(duì)矩陣進(jìn)行初始化。 vector1 = Eigen::Vector3f::Ones(); std::cout << "------ matrix1 ------" << std::endl << matrix1 << std::endl; std::cout << "------ vector1 ------" << std::endl << vector1 << std::endl;}在上面的代碼中,MatrixXf是一個(gè)行列可動(dòng)態(tài)設(shè)置的矩陣,Vector3f是一個(gè)有3個(gè)元素的列向量。
typedef Matrix MatrixXf;typedef Matrix Vector3f;需要注意到是在定義矩陣大小時(shí)是沒(méi)有初始化矩陣的,需要重新對(duì)矩陣進(jìn)行初始化,這里是用Zero和Ones函數(shù)對(duì)其初始化,Zero是初始化為全0,而Ones是初始化為全1。最后,我們看一下執(zhí)行結(jié)果。
當(dāng)然,我們也可以給定任意值,每個(gè)值用逗號(hào)隔開(kāi),不過(guò),這種方法只能適用于確定矩陣大小的情況下使用。
Eigen::MatrixXf matrix1(3,4); Eigen::Vector3f vector1; matrix1 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12; vector1 << 1, 2, 3;執(zhí)行結(jié)果如下:
另外,我們還可以用()對(duì)某個(gè)元素進(jìn)行訪問(wèn),我們可以對(duì)其可讀和可寫(xiě)。
Eigen::MatrixXf matrix1(3,4); Eigen::Vector3f vector1; matrix1 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12; vector1 << 1, 2, 3; matrix1(1,3) = 100; vector1(1) = 100;我們將matrix1的第2行,第4列修改成100;vector1的第2行修改成100,程序執(zhí)行結(jié)果如下:
矩陣的基本運(yùn)算
學(xué)習(xí)了矩陣的定義,那我們下面來(lái)看一下幾個(gè)基本的矩陣運(yùn)算。Matrix重載了+,+=,-,-+,×,×=,/,/=這幾個(gè)基本的四則運(yùn)算。
對(duì)于加減運(yùn)算,需要注意一下幾點(diǎn):
- 左右矩陣的行列對(duì)應(yīng)相等;
- 數(shù)據(jù)的類型也要相同,因?yàn)榫仃囘\(yùn)算不支持隱式類型轉(zhuǎn)換;
- 不支持和標(biāo)量進(jìn)行加減運(yùn)算。
我們來(lái)看一個(gè)例子:
#include #include "eigen_3_3_7/Eigen/Eigen"int main(){ Eigen::MatrixXf matrix1(2,3); Eigen::MatrixXf matrix2(2,3); matrix1 << 1, 2, 3, 5, 6, 7; matrix2 << 1, 1, 2, 2, 1, 1; std::cout << "------ matrix1 ------" << std::endl << matrix1 << std::endl; std::cout << "------ matrix2 ------" << std::endl << matrix1 << std::endl; std::cout << "------ matrix1 + matrix2 ------" << std::endl << matrix1 + matrix2 << std::endl;}執(zhí)行結(jié)果如下:
關(guān)于乘除法運(yùn)算,矩陣支持矩陣和標(biāo)量之間的乘除法運(yùn)算,標(biāo)量和矩陣中的每個(gè)元素相運(yùn)算。
#include #include "eigen_3_3_7/Eigen/Eigen"int main(){ Eigen::MatrixXf matrix1(2,3); Eigen::MatrixXf matrix2(2,3); matrix1 << 1, 2, 3, 5, 6, 7; matrix2 << 1, 1, 2, 2, 1, 1; std::cout << "------ matrix1 ------" << std::endl << matrix1 << std::endl; std::cout << "------ matrix2 ------" << std::endl << matrix2 << std::endl; std::cout << "------ matrix1 * 2 ------" << std::endl << matrix1 * 2 << std::endl; std::cout << "------ matrix2 / 2 ------" << std::endl << matrix2 / 2 << std::endl;}執(zhí)行結(jié)果如下:
關(guān)于矩陣和矩陣之間的乘法,兩個(gè)矩陣只有當(dāng)左邊的矩陣的列數(shù)等于右邊矩陣的行數(shù)時(shí),兩個(gè)矩陣才可以進(jìn)行矩陣的乘法運(yùn)算 。如下圖,左邊矩陣第i行的元素逐個(gè)和右邊矩陣第j列的元素相乘,乘積再相加,就是第i行,第j列的結(jié)果。對(duì)于Eigen庫(kù)來(lái)說(shuō),它通過(guò)重載*運(yùn)算符幫我們實(shí)現(xiàn)了這個(gè)運(yùn)算過(guò)程,我們直接使用*運(yùn)算符即可。
#include #include "eigen_3_3_7/Eigen/Eigen"int main(){ Eigen::MatrixXf matrix1(2,3); Eigen::MatrixXf matrix2(3,2); matrix1 << 1, 2, 3, 5, 6, 7; matrix2 << 1, 1, 2, 1, 3, 1; std::cout << "------ matrix1 ------" << std::endl << matrix1 << std::endl; std::cout << "------ matrix2 ------" << std::endl << matrix2 << std::endl; std::cout << "------ matrix1 * matrix2 ------" << std::endl << matrix1 * matrix2 << std::endl;}執(zhí)行結(jié)果如下:
另外,還包括矩陣的轉(zhuǎn)置、共軛和共軛轉(zhuǎn)置等矩陣運(yùn)算,在Eigen中分別是有transpose()、conjugate()、adjoint()函數(shù)可實(shí)現(xiàn)。
#include #include "eigen_3_3_7/Eigen/Eigen"int main(){ Eigen::MatrixXf matrix1(2, 3); Eigen::MatrixXf matrix2(2, 3); matrix1 << 1, 2, 3, 4, 5, 6; std::cout << "------ matrix1 ------" << std::endl << matrix1 << std::endl; // 轉(zhuǎn)置 std::cout << "------ matrix1 transpose------" << std::endl << matrix1.transpose() << std::endl; // 共軛 std::cout << "------ matrix1 conjugate------" << std::endl << matrix1.conjugate() << std::endl; // 共軛轉(zhuǎn)置 std::cout << "------ matrix1 adjoint------" << std::endl << matrix1.adjoint() << std::endl;}執(zhí)行結(jié)果如下,不過(guò),代碼中實(shí)數(shù)的共軛還是其本身。
數(shù)組的定義和初始化
有的時(shí)候我們并不需要做線性代數(shù)矩陣運(yùn)算,而只是做元素級(jí)的操作,這個(gè)時(shí)候就需要用到Array了。對(duì)Array來(lái)說(shuō),它和Matrix的定義和初始化的方式是一樣的。
#include #include "eigen_3_3_7/Eigen/Eigen"int main(){ Eigen::ArrayXXf array1(2,3); Eigen::ArrayXXf array2(3,3); Eigen::ArrayXXf array3(5,10); array1(0,0) = 1; array1(0,1) = 2; array1(0,2) = 2; array1(1,0) = 1; array1(1,1) = 2; array1(1,2) = 2; array2 << 1, 2, 3, 4, 5, 6, 7, 8, 9; array3 = Eigen::ArrayXXf::Ones(5, 10); std::cout << "------ array1 ------" << std::endl << array1 << std::endl; std::cout << "------ array2 ------" << std::endl << array2 << std::endl; std::cout << "------ array3 ------" << std::endl << array3 << std::endl;}這里的ArrayXXf也是Eigen庫(kù)重定義的,它行和列數(shù)可以動(dòng)態(tài)設(shè)置。我們可以看到Array的初始化和Matrix也是類似的 。
typedef?Array??ArrayXXf;下面是執(zhí)行結(jié)果:
數(shù)組的基本運(yùn)算
Array同樣也重載了四則運(yùn)算,但是,這里數(shù)據(jù)只是對(duì)數(shù)組內(nèi)的元素做算術(shù)運(yùn)算,而不是矩陣線性運(yùn)算。所以,對(duì)于Array來(lái)數(shù),兩個(gè)數(shù)據(jù)的大小相同,即行數(shù)和行數(shù)相同,列數(shù)和列數(shù)相同,它的四則運(yùn)算就是取兩個(gè)數(shù)組相應(yīng)位置的元素參與運(yùn)算,運(yùn)算的結(jié)果就是對(duì)應(yīng)位置的值。
當(dāng)然,也支持和標(biāo)量之間的運(yùn)算,數(shù)組中的每個(gè)元素都乘以這個(gè)標(biāo)量,這個(gè)和矩陣一樣。
#include #include "eigen_3_3_7/Eigen/Eigen"int main(){ Eigen::ArrayXXf array1(2, 3); Eigen::ArrayXXf array2(2, 3); array1 << 1, 2, 3, 4, 5, 6; array2 << 1, 2, 1, 1, 1, 2; std::cout << "------ array1 ------" << std::endl << array1 << std::endl; std::cout << "------ array2 ------" << std::endl << array2 << std::endl; std::cout << "------ array1 + array2 ------" << std::endl << array1 + array2 << std::endl; std::cout << "------ array1 - array2 ------" << std::endl << array1 - array2 << std::endl; std::cout << "------ array1 * array2 ------" << std::endl << array1 * array2 << std::endl; std::cout << "------ array1 / array2 ------" << std::endl << array1 / array2 << std::endl; std::cout << "------ array1 * 2 ------" << std::endl << array1 * 2 << std::endl;}執(zhí)行結(jié)果:
Matrix和Array兩者是可以相互轉(zhuǎn)換的。Matrix類有array()方法,可將Matrix轉(zhuǎn)換為Array。Array類有matrix()方法,可將Array轉(zhuǎn)換成Matrix。
總之,Eigen是一個(gè)很不錯(cuò)的開(kāi)源庫(kù),官網(wǎng)還有更加詳細(xì)的文檔,大家可以參考:
http://eigen.tuxfamily.org/dox/GettingStarted.html
http://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html
http://eigen.tuxfamily.org/dox/group__QuickRefPage.html
http://eigen.tuxfamily.org/dox/Eigen2ToEigen3.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的eigen 列向量转矩阵_快速入门矩阵运算——开源库Eigen的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用matlab实现sift算法,sift
- 下一篇: 水调歌头明月几时有赏析