Opencv中Mat矩阵相乘——点乘、dot、mul运算

转载于:https://blog.csdn.net/dcrmg/article/details/52404580


Mat矩阵点乘——A*B


Opencv重载了运算符“*”,姑且称之为Mat矩阵“点乘”,其中一个重载声明为:


CV_EXPORTS MatExpr operator * (const Mat& a, const Mat& b);
  
  


点乘说明:


1.  A*B是以数学运算中矩阵相乘的方式实现的,即Mat矩阵A和B被当做纯粹的矩阵做乘法运算,这就要求A的列数等       于B的行数时,才能定义两个矩阵相乘。如A是m×n矩阵,B是n×p矩阵,它们的乘积AB是一个m×p矩阵。



如上图所示,C=AB。C中第i行第j列所在元素C(i,j)等于A中第i行所有元素跟B中第j列所有元素一一对应的乘积之和。

更具有代表性的的:对于A、B都是2行2列矩阵的情况:


Opencv验证:

定义两个Mat矩阵A和B点乘,A为2行3列,B为3行2列:



  
  
  1. #include "core/core.hpp"
  2. #include "iostream"
  3. using namespace std;
  4. using namespace cv;
  5. int main(int argc,char *argv[])
  6. {
  7. Mat A=Mat::ones( 2, 3,CV_32FC1);
  8. Mat B=Mat::ones( 3, 2,CV_32FC1);
  9. Mat AB;
  10. A.at< float>( 0, 0)= 1;
  11. A.at< float>( 0, 1)= 2;
  12. A.at< float>( 0, 2)= 3;
  13. A.at< float>( 1, 0)= 4;
  14. A.at< float>( 1, 1)= 5;
  15. A.at< float>( 1, 2)= 6;
  16. B.at< float>( 0, 0)= 1;
  17. B.at< float>( 0, 1)= 2;
  18. B.at< float>( 1, 0)= 3;
  19. B.at< float>( 1, 1)= 4;
  20. B.at< float>( 2, 0)= 5;
  21. B.at< float>( 2, 1)= 6;
  22. AB=A*B;
  23. cout<< "A=\n"<<A<< endl<< endl;
  24. cout<< "B=\n"<<B<< endl<< endl;
  25. cout<< "AB=\n"<<AB<< endl<< endl;
  26. system( "pause");
  27. }


输出:


务必保证两个Mat矩阵中第一个矩阵A的列数等于第二个矩阵B的行数。


2.  参与点乘的两个Mat矩阵的数据类型(type)只能是 CV_32F、 CV_64FC1、 CV_32FC2、 CV_64FC2 这4种类        型中的一种。若选用其他类型,比如CV_8UC1,编译器会报错:





Mat矩阵dot——A.dot(B)


Opencv中.dot操作才算得上是真正的“点乘”,A.dot(B)操作相当于数学向量运算中的点乘,也叫向量的内积、数量积。


函数声明:



  
  
  1. //! computes dot-product
  2. double dot(InputArray m) const;


dot说明:


1.  对两个向量执行点乘运算,就是对这两个向量对应位一一相乘之后求和的操作,点乘的结果是一个标量。 

  

对于向量a和向量b:


                                                           


a和b的点积公式为:



要求向量a和向量b的行列数相同。


Mat矩阵的dot方法扩展了一维向量的点乘操作,把整个Mat矩阵扩展成一个行(列)向量,之后执行向量的点乘运算,仍然要求参与dot运算的两个Mat矩阵的行列数完全一致


2.  dot方法声明中显示返回值是double,所以A.dot(B)结果是一个double类型数据,不是Mat矩阵,不能把A.dot(B)结       果赋值给Mat矩阵!


Opencv验证:



  
  
  1. #include "core/core.hpp"
  2. #include "iostream"
  3. using namespace std;
  4. using namespace cv;
  5. int main(int argc,char *argv[])
  6. {
  7. Mat A=Mat::ones( 2, 3,CV_8UC1);
  8. Mat B=Mat::ones( 2, 3,CV_8UC1);
  9. A.at<uchar>( 0, 0)= 1;
  10. A.at<uchar>( 0, 1)= 2;
  11. A.at<uchar>( 0, 2)= 3;
  12. A.at<uchar>( 1, 0)= 4;
  13. A.at<uchar>( 1, 1)= 5;
  14. A.at<uchar>( 1, 2)= 6;
  15. B.at<uchar>( 0, 0)= 1;
  16. B.at<uchar>( 0, 1)= 2;
  17. B.at<uchar>( 0, 2)= 3;
  18. B.at<uchar>( 1, 0)= 4;
  19. B.at<uchar>( 1, 1)= 5;
  20. B.at<uchar>( 1, 2)= 6;
  21. double AB=A.dot(B);
  22. cout<< "A=\n"<<A<< endl<< endl;
  23. cout<< "B=\n"<<B<< endl<< endl;
  24. cout<< "double类型的AB=\n"<<AB<< endl<< endl;
  25. system( "pause");
  26. }


运行结果:



若对AB声明为Mat,则在编译阶段就会报错。


3.  dot操作不对参与运算的矩阵A、B的数据类型做要求,CV_8UC1、CV_32FC1等,可以是任何Opencv定义的类         型,如在2中使用的就是CV_8UC1。


4.  若参与dot运算的两个Mat矩阵是多通道的,则计算结果是所有通道单独计算各自.dot之后,再累计的和,结果仍是一个double类型数据。


Mat矩阵mul——A.mul(B)


Opencv中mul会计算两个Mat矩阵对应位的乘积,所以要求参与运算的矩阵A的行列和B的行列数一致。计算结果是跟A或B行列数一致的一个Mat矩阵。


Opencv中mul声明:



  
  
  1. //! per-element matrix multiplication by means of matrix expressions
  2. MatExpr mul(InputArray m, double scale=1) const;


以简单的情况为例,对于2*2大小的Mat矩阵A和B:


对A和B执行mul运算:



mul说明:


1.  mul操作不对参与运算的两个矩阵A、B有数据类型上的要求,但要求A,B类型一致,不然报错;

2.  Mat AB=A.mul(B),若声明AB时没有定义AB的数据类型,则默认AB的数据类型跟A和B保存一致

3.  若AB精度不够,可能产生溢出,溢出的值被置为当前精度下的最大值;


Opencv验证:



  
  
  1. #include "core/core.hpp"
  2. #include "iostream"
  3. using namespace std;
  4. using namespace cv;
  5. int main(int argc,char *argv[])
  6. {
  7. Mat A=Mat::ones( 2, 3,CV_8UC1);
  8. Mat B=Mat::ones( 2, 3,CV_8UC1);
  9. A.at<uchar>( 0, 0)= 60;
  10. A.at<uchar>( 0, 1)= 2;
  11. A.at<uchar>( 0, 2)= 3;
  12. A.at<uchar>( 1, 0)= 4;
  13. A.at<uchar>( 1, 1)= 5;
  14. A.at<uchar>( 1, 2)= 6;
  15. B.at<uchar>( 0, 0)= 60;
  16. B.at<uchar>( 0, 1)= 2;
  17. B.at<uchar>( 0, 2)= 3;
  18. B.at<uchar>( 1, 0)= 4;
  19. B.at<uchar>( 1, 1)= 5;
  20. B.at<uchar>( 1, 2)= 6;
  21. Mat AB=A.mul(B);
  22. cout<< "A=\n"<<A<< endl<< endl;
  23. cout<< "B=\n"<<B<< endl<< endl;
  24. cout<< "AB=\n"<<AB<< endl<< endl;
  25. system( "pause");
  26. }


输出:




AB中第一个元素应该为60*60=360,但AB默认的类型为CV_8UC1,即最大值只能是255;所以执行mul运算一定要定义AB足够的精度,防止溢出。


        </div>
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值