Mat矩阵乘积——A*B
Opencv重载了运算符“*”,称之为Mat矩阵乘法,其中一个重载声明为:
CV_EXPORTS MatExpr operator * (const Mat& a, const Mat& b);
点乘说明:
- A*B是以数学运算中矩阵相乘的方式实现的,即Mat矩阵A和B被当做纯粹的矩阵做乘法运算,这就要求A的列数等 于B的行数时,才能定义两个矩阵相乘。如A是m×n矩阵,B是n×p矩阵,它们的乘积AB是一个m×p矩阵。
- 参与点乘的两个Mat矩阵的数据类型(type)只能是
CV_32F
、CV_64FC1
、CV_32FC2
、CV_64FC2
这4种类 型中的一种。若选用其他类型,比如CV_8UC1
,编译器会报错:
Opencv验证:
定义两个Mat矩阵A和B点乘,A为2行3列,B为3行2列:
#include "core/core.hpp"
#include "iostream"
using namespace std;
using namespace cv;
int main(int argc,char *argv[])
{
Mat A=Mat::ones(2,3,CV_32FC1);
Mat B=Mat::ones(3,2,CV_32FC1);
Mat AB;
A.at<float>(0,0)=1;
A.at<float>(0,1)=2;
A.at<float>(0,2)=3;
A.at<float>(1,0)=4;
A.at<float>(1,1)=5;
A.at<float>(1,2)=6;
B.at<float>(0,0)=1;
B.at<float>(0,1)=2;
B.at<float>(1,0)=3;
B.at<float>(1,1)=4;
B.at<float>(2,0)=5;
B.at<float>(2,1)=6;
AB=A*B;
cout<<"A=\n"<<A<<endl<<endl;
cout<<"B=\n"<<B<<endl<<endl;
cout<<"AB=\n"<<AB<<endl<<endl;
system("pause");
}
务必保证两个Mat矩阵中第一个矩阵A的列数等于第二个矩阵B的行数。
Mat矩阵dot——A.dot(B)
Opencv中.dot操作才算得上是真正的“点乘”,A.dot(B)操作相当于数学向量运算中的点乘,也叫向量的内积、数量积。
函数声明:
//! computes dot-product
double dot(InputArray m) const;
dot说明:
-
对两个Mat类矩阵执行点乘运算,就是把整个Mat矩阵扩展成一个行(列)向量,之后执行向量的点乘运算,对应位一一相乘之后求和的操作,点乘的结果是一个标量。
-
dot方法声明中显示返回值是double,所以A.dot(B)结果是一个double类型数据,不是Mat矩阵,不能把A.dot(B)结 果赋值给Mat矩阵!
-
dot操作不对参与运算的矩阵A、B的数据类型做要求,
CV_8UC1
、CV_32FC1
等,可以是任何Opencv定义的类 型,如在2中使用的就是CV_8UC1
。 -
若参与dot运算的两个Mat矩阵是多通道的,则计算结果是所有通道单独计算各自.dot之后,再累计的和,结果仍是一个double类型数据。
Opencv验证:
#include "core/core.hpp"
#include "iostream"
using namespace std;
using namespace cv;
int main(int argc,char *argv[])
{
Mat A=Mat::ones(2,3,CV_8UC1);
Mat B=Mat::ones(2,3,CV_8UC1);
A.at<uchar>(0,0)=1;
A.at<uchar>(0,1)=2;
A.at<uchar>(0,2)=3;
A.at<uchar>(1,0)=4;
A.at<uchar>(1,1)=5;
A.at<uchar>(1,2)=6;
B.at<uchar>(0,0)=1;
B.at<uchar>(0,1)=2;
B.at<uchar>(0,2)=3;
B.at<uchar>(1,0)=4;
B.at<uchar>(1,1)=5;
B.at<uchar>(1,2)=6;
double AB=A.dot(B);
cout<<"A=\n"<<A<<endl<<endl;
cout<<"B=\n"<<B<<endl<<endl;
cout<<"double类型的AB=\n"<<AB<<endl<<endl;
system("pause");
}
Mat矩阵mul——A.mul(B)
Opencv中mul会计算两个Mat矩阵对应位的乘积,所以要求参与运算的矩阵A的行列和B的行列数一致。计算结果是跟A或B行列数一致的一个Mat矩阵。
Opencv中mul声明:
//! per-element matrix multiplication by means of matrix expressions
MatExpr mul(InputArray m, double scale=1) const;
mul说明:
-
mul操作不对参与运算的两个矩阵A、B有数据类型上的要求,但要求A,B类型一致,不然报错;
-
Mat AB=A.mul(B)
,若声明AB时没有定义AB的数据类型,则默认AB的数据类型跟A和B保存一致; -
若AB精度不够,可能产生溢出,溢出的值被置为当前精度下的最大值;
Opencv验证:
#include "core/core.hpp"
#include "iostream"
using namespace std;
using namespace cv;
int main(int argc,char *argv[])
{
Mat A=Mat::ones(2,3,CV_8UC1);
Mat B=Mat::ones(2,3,CV_8UC1);
A.at<uchar>(0,0)=60;
A.at<uchar>(0,1)=2;
A.at<uchar>(0,2)=3;
A.at<uchar>(1,0)=4;
A.at<uchar>(1,1)=5;
A.at<uchar>(1,2)=6;
B.at<uchar>(0,0)=60;
B.at<uchar>(0,1)=2;
B.at<uchar>(0,2)=3;
B.at<uchar>(1,0)=4;
B.at<uchar>(1,1)=5;
B.at<uchar>(1,2)=6;
Mat AB=A.mul(B);
cout<<"A=\n"<<A<<endl<<endl;
cout<<"B=\n"<<B<<endl<<endl;
cout<<"AB=\n"<<AB<<endl<<endl;
system("pause");
}
输出:
AB中第一个元素应该为60*60=360,但AB默认的类型为CV_8UC1,即最大值只能是255;所以执行mul运算一定要定义AB足够的精度,防止溢出