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

Stella981
• 阅读 981

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

2016年09月02日 00:00:36 -牧野- 阅读数:59593 标签: Opencv矩阵相乘点乘dotmul 更多

个人分类: OpenCV

所属专栏: OpenCV从入门到转行

版权声明:本文为博主原创文章,转载请注明出处。 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矩阵。

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

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

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

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

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. }

输出:

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

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

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

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

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

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

函数声明:

  1. //! computes dot-product

  2. double dot(InputArray m) const;

dot说明:

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

对于向量a和向量b:

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

a和b的点积公式为:

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

要求向量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( 0,0)=1;

  10. A.at( 0,1)=2;

  11. A.at( 0,2)=3;

  12. A.at( 1,0)=4;

  13. A.at( 1,1)=5;

  14. A.at( 1,2)=6;

  15. B.at( 0,0)=1;

  16. B.at( 0,1)=2;

  17. B.at( 0,2)=3;

  18. B.at( 1,0)=4;

  19. B.at( 1,1)=5;

  20. B.at( 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. }

运行结果:

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

若对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:

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

对A和B执行mul运算:

Opencv中Mat矩阵相乘——点乘、dot、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( 0,0)=60;

  10. A.at( 0,1)=2;

  11. A.at( 0,2)=3;

  12. A.at( 1,0)=4;

  13. A.at( 1,1)=5;

  14. A.at( 1,2)=6;

  15. B.at( 0,0)=60;

  16. B.at( 0,1)=2;

  17. B.at( 0,2)=3;

  18. B.at( 1,0)=4;

  19. B.at( 1,1)=5;

  20. B.at( 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. }

输出:

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

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

点赞
收藏
评论区
推荐文章
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
小森森 小森森
4个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Wesley13 Wesley13
1年前
Java爬虫之JSoup使用教程
title:Java爬虫之JSoup使用教程date:201812248:00:000800update:201812248:00:000800author:mecover:https://imgblog.csdnimg.cn/20181224144920712(https://www.oschin
Wesley13 Wesley13
1年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
1年前
Angular material mat
IconIconNamematiconcode_add\_comment_addcommenticon<maticonadd\_comment</maticon_attach\_file_attachfileicon<maticonattach\_file</maticon_attach\
Wesley13 Wesley13
1年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue