本文介绍在C++ 语言中,矩阵库Armadillo的mat
、vec
格式数据与计算机视觉库OpenCV的Mat
格式数据相互转换的方法。
在C++ 语言的矩阵库Armadillo与计算机视觉库OpenCV中,都有矩阵格式的数据类型;而这两个库在运行能力方面各有千秋,因此实际应用过程中,难免会遇到需要将二者的矩阵格式数据类型加以相互转换的情况。本文就对其相互转换的具体方法加以介绍。
首先,二者相互转换需要用到的代码如下。
#include <iostream>
#include <armadillo>
#include <opencv2/opencv.hpp>
using namespace std;
int main() {
// 将Armadillo的列向量vec转为OpenCV的Mat
arma::vec ar_vec = {1, 2, 3, 4};
cout << ar_vec << "\n" << endl;
cv::Mat cv_mat_1(ar_vec.n_rows, ar_vec.n_cols, CV_64FC1, ar_vec.memptr());
cout << cv_mat_1 << "\n" << endl;
// 将Armadillo的mat转为OpenCV的Mat
arma::mat ar_mat = { {1, 2, 3}, {5, 6, 7} };
cout << ar_mat << "\n" << endl;
arma::mat ar_mat_t = ar_mat.t();
cv::Mat cv_mat_2(ar_mat.n_rows, ar_mat.n_cols, CV_64FC1, ar_mat_t.memptr());
cout << cv_mat_2 << "\n" << endl;
// 将OpenCV的Mat转为Armadillo的mat
cv::Mat cv_mat = (cv::Mat_<double>(2, 3) << 1, 8, 9, 15, 22, 37);
cout << cv_mat << "\n" << endl;
arma::mat ar_mat_1_t(reinterpret_cast<double*>(cv_mat.data), cv_mat.cols, cv_mat.rows);
cout << ar_mat_1_t << "\n" << endl;
arma::mat ar_mat_1 = ar_mat_1_t.t();
cout << ar_mat_1 << "\n" << endl;
// 将OpenCV的Mat转为Armadillo的列向量vec或行向量rowvec
cv::Mat cv_mat_3 = (cv::Mat_<double>(1, 4) << 1, 3, 7, 15);
cout << cv_mat_3 << "\n" << endl;
arma::vec ar_vec_1_t(reinterpret_cast<double*>(cv_mat_3.data), cv_mat_3.cols, cv_mat_3.rows);
cout << ar_vec_1_t << "\n" << endl;
arma::rowvec ar_vec_1 = ar_vec_1_t.t();
cout << ar_vec_1 << "\n" << endl;
return 0;
}
其中,主函数中共有4
个部分,分别是将Armadillo的列向量vec
转为OpenCV的Mat
、将Armadillo的mat
转为OpenCV的Mat
、将OpenCV的Mat
转为Armadillo的mat
、将OpenCV的Mat
转为Armadillo的列向量vec
或行向量rowvec
等4
个过程的代码。
转换的整体思路也非常简单。如果我们需要将Armadillo库的矩阵数据转换为OpenCV库的矩阵数据,那么就通过cv::Mat
格式数据的构造函数,基于.memptr()
函数将Armadillo库的矩阵数据元素分别提取出,放入OpenCV库的矩阵数据即可;反之,如果需要将OpenCV库的矩阵数据转换为Armadillo库的矩阵数据,则基于arma::mat
格式数据的构造函数来实现即可。
有一点需要注意的是,Armadillo库是以列优先的方式存储矩阵数据,而OpenCV库则是以行优先的方式存储矩阵数据;因此在上述二者相互转换的代码中,我们有时需要对转换的矩阵数据做一次转置操作,从而保证数据转换无误。
关于上述代码的详细解释,具体如下。
首先,设置代码的头文件包含部分。iostream
用于输入输出操作,armadillo
与opencv2/opencv.hpp
分别就是矩阵库Armadillo与计算机视觉库OpenCV的头文件。
其次,第1
部分代码演示了将Armadillo的列向量arma::vec
转换为OpenCV的cv::Mat
对象的方法。首先,创建一个列向量ar_vec
。然后,通过指定ar_vec
的行数、列数、数据类型和数据指针创建一个对应的cv::Mat
对象cv_mat_1
。最后,使用cout
打印输出结果。
再次,第2
部分代码演示了将Armadillo的矩阵arma::mat
转换为OpenCV的cv::Mat
对象的方法。首先,创建一个矩阵ar_mat
。然后,通过获取ar_mat
的转置矩阵ar_mat_t
,指定行数、列数、数据类型和数据指针创建一个对应的cv::Mat
对象cv_mat_2
。最后,使用cout
打印输出结果。
接下来,第3
部分代码演示了将OpenCV的cv::Mat
对象转换为Armadillo的矩阵arma::mat
的方法。首先,创建一个cv::Mat
对象cv_mat
,并设置其值。然后,通过使用reinterpret_cast
将cv_mat
的数据指针转换为double*
类型,以及指定列数、行数创建一个对应的arma::mat
对象ar_mat_1_t
。最后,通过对ar_mat_1_t
进行转置,创建一个转置后的矩阵ar_mat_1
。使用cout
打印输出结果。
最后,第4
部分代码演示了将OpenCV的cv::Mat
对象转换为Armadillo的列向量arma::vec
或行向量arma::rowvec
的方法。首先,创建了一个大小为1*4
的cv::Mat
对象cv_mat_3
,并设置了其元素值为1
、3
、7
和15
。接下来,使用reinterpret_cast
将cv_mat_3
的数据指针转换为double*
类型,并通过指定列数和行数创建了一个对应的Armadillo列向量ar_vec_1_t
。这样,ar_vec_1_t
就包含了cv_mat_3
的数据。然后,通过对ar_vec_1_t
进行转置操作(.t()
),创建了一个行向量ar_vec_1
。最后,使用cout
打印输出了转换结果ar_vec_1
。
为了方便对比,我们将上述代码运行所得结果加以展示;如下图所示。
可以看到,上述三段代码可以成功地将Armadillo库、OpenCV库的矩阵数据加以相互转换。
至此,大功告成。