说明:
相对于用来存储图像的大型矩阵类型cv::Mat,固定矩阵主要应用于小型矩阵,一般是低于6×6的矩阵,对固定矩阵的操作速度非常快,所以在图像变换时常常使用固定矩阵,第二部分的固定向量类继承自固定矩阵类。固定矩阵定义为一个模板类cv::Matx<>,为了方便使用,定义了许多别名,别名没有尖括号,其定义如下:
固定矩阵别名规则:
cv::Matx{1,2,3…}{1,2,3…}{f,d}
数字表示维度,先行后列,f表示浮点型,d表示双精度型。
例:cv::Matx33d :3×3矩阵,矩阵内的元素为double类型。
注:
做矩阵运算时可以使用固定矩阵,会比较快。
无论是Mat类还是这里的固定矩阵类都对<<做了运算符重载,可以通过std::cout<< 矩阵 的方式打印来观察效果。
//使用实例
//默认构造函数
cv::Matx33f m33f; //3×3矩阵,数据类型float,下面完全类似,不再赘述
cv::Matx44d m44d;
//拷贝构造函数
cv::Mat33f m33f1(m33f);
//值构造函数
double x0 = 0, x1 = 2, x2 = 3;
cv::Matx31d m31d(x0, x1, x2);
std::cout << m31d << std<<endl; //打m21d矩阵
cv::Matx33d m33d(1, 2, 3, 4, 5, 6, 7, 8, 9);
//内置方法构造,加后缀a、b.....以区分变量,无其它含义
float x_a = 2.0;
cv::Matx33f m33f_a = cv::Matx33f::all(x_a); //矩阵元素全为x_a
cv::Matx43d m43d_a = cv::Mat43d::zeros(); //全零矩阵
cv::Matx44d m44d_a = cv::Matx44d::ones(); //全1矩阵
cv::Matx33f m33f_b = cv::Matx33f::eye(); //单位矩阵
cv::Matx33d m33d_b = cv::Matx33d::randu(); //均匀分布矩阵
cv::Matx33d m33d_c = cv::Matx33d::nrandn(); //数字呈正态分布矩阵
//成员访问
cv::Matx44f m44f_d = cv::Matx44f::ones();
float _22 = m44f_d(1, 1); //索引从零开始
//代数运算
cv::Matx33d m33d_e = cv::Matx33d::ones();
cv::Matx33d m33d_f = cv::Matx33d::eye();
cv::Matx33d m33d_efm = m33d_e * m33d_f; //矩阵乘法(数学意义上,列向量), 和差为逐元素
double m33d_efdot = m33d_e.ddot(m33d_f); //逐元素乘积并相加
//改变形状
cv::Matx33d m33d_g = cv::Matx33d::ones();
cv::Matx91d m91d_g = m33d_g.reshape<9,1>(); //注意使用列向量组织,故为9行1列
cv::Matx44d m44d_h = cv::Matx44d::eye();
//访问子矩阵, (1, 1)处2*2子矩阵
cv::Matx22d m22d_h = m44d_h.get_minor<2,2>(1,1);
//提取第1行
cv::Matx14d m14d_h = m44d_h.row(0);
//提取第1列
cv::Matx41d m41d_h = m44d_h.col(0);
//提取对角线
cv::Matx41d m41d_h_diag = m44d_h.diag();
//矩阵操作
cv::Matx33d m33d_k = cv::Matx33d::eye();
//转置矩阵
cv::Matx33d m33d_k_T = m33d_k.t();
//逆矩阵
cv::Matx33d m33d_k_inv = m33d_k.inv();
//解线性系统使用solve方法
cv::Matx31d rhs31d(1,2,3);
cv::Matx31d m31d_k_x = m33d_k.solve(rhs31d); //Ax = b; rhs31d = b, A = m33d_k
//注:不是特别好用,有时矩阵不可逆
类似于cv::Matx33d::ones()这样的函数是静态函数。
我们可以使用固定矩阵的类模板cv::Matx<>构造任意维度的矩阵,但是建议不要构造太大的固定矩阵,对于大型矩阵应该使用cv::Mat。
可能迷惑的点是像Matx33d这样的类型带有数字,在OpenCV中这种情况往往意味着别名,我们需要搞清楚别名的命名规则(如同本章开头的介绍),然后就可以放心地使用啦!