OpenCV中的MAT类矩阵的各种基本运算及示例代码(加减乘点乘点除乘方累加转置等)
Posted 昊虹图像算法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV中的MAT类矩阵的各种基本运算及示例代码(加减乘点乘点除乘方累加转置等)相关的知识,希望对你有一定的参考价值。
OpenCV中的MAT类矩阵的各种基本运算及示例代码。
目录
- 01-两个矩阵相加、矩阵和标量相加
- 02-带权重(系数)的矩阵加法
- 03-两个矩阵的经典线性变换
- 04-两个矩阵相减、矩阵和标量相减
- 05- 求矩阵中每个元素的相反数
- 06-矩阵元素乘法(点乘)、矩阵与标量相乘
- 07-各种累积和
- 08-矩阵乘法
- 09-矩阵乘方
- 10-矩阵的元素除法(点除)【真除,既保留整数也保留小数】
- 11 -矩阵的元素除法(点除)取整
- 12-矩阵的元素除法(点除)取余
- 13-矩阵的转置
01-两个矩阵相加、矩阵和标量相加
可以使用函数add()实现两个矩阵相加,矩阵和标量相加。
详情见博文 https://blog.csdn.net/wenhao_ir/article/details/125246253
02-带权重(系数)的矩阵加法
可以用函数cv::addWeighted()实现带权重(系数)的矩阵加法,其官方文档介绍如下:
如果认真阅读了博文https://blog.csdn.net/wenhao_ir/article/details/125246253对函数add()的说明,应该很容易明白这个函数的使用,所以就就不做额外说明了,示例代码也不给了。
只是要注意下,它不能实现矩阵与标量的带权重(系数)的加法,并且两个相加的矩阵必须是相同尺寸和通道数的矩阵。当输出矩阵的数据类型为CV_32S时,不会对结果做saturate(饱和)操作,关于饱和操作,大家可参见博文 https://blog.csdn.net/wenhao_ir/article/details/125247806
03-两个矩阵的经典线性变换
可以用函数cv::scaleAdd()实现两个矩阵的经典线性变换,其官方文档介绍如下:
官方文档已经写得很清楚它的用法了,这里就先不上示例代码了,只要是要注意的三个矩阵的尺寸和数据类型都是一样的。
04-两个矩阵相减、矩阵和标量相减
可以用函数cv::subtract()实现两个矩阵相减、矩阵和标量相减,官方文档对其介绍如下:
从上面的文档介绍可以看出,其用法与cv::add()的用法一模一样,所以这里就不多介绍了,示例代码也暂时不给了。
05- 求矩阵中每个元素的相反数
OpenCV矩阵的元素数据类型有以下这些:
CV_8U、CV_8S、CV_16U、CV_16S、CV_32S、CV_32F、CV_64F
求相反数的话显然数据类型要为带符号的数据类型,上面的数据类型中有带符号的有:CV_8S、CV_16S、CV_32S、CV_32F、CV_64F。
可以用函数cv::subtract()的第四种形式实现求矩阵中每个元素的相反数,其第四种形式如下:
也可以直接用减号实现,当直接用减号时,实际上也是将操作符“-”重载为了函数cv::subtract()实现的。
示例代码如下:
//OpenCV版本:3.0.0
//VS版本:2013
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
int main()
cv::Mat A1(2, 3, CV_8SC1, cv::Scalar(98));
cout << "A1中的数据为:\\n" << A1 << endl << endl;
//第一种方法实现求矩阵每个元素的相反数
cv::Mat B1 = -A1;
cout << "B1中的数据为:\\n" << B1 << endl << endl;
//第二种方法实现求矩阵中每个元素的相反数
cv::Mat C1;
cv::subtract(0,A1,C1);
cout << "C1中的数据为:\\n" << C1 << endl << endl;
return(0);
运行结果如下:
06-矩阵元素乘法(点乘)、矩阵与标量相乘
可以用函数cv::multiply()和函数cv::Mat::mul()实现矩阵元素乘法(点乘)、矩阵与标量相乘。
官方文档对其介绍如下:
上面的文档对函数cv::multiply()的介绍是比较清楚了,补充说明几点:
①其两个输入矩阵要求是相同的尺寸和相同的通道数,注意数据类型可以不一样,当数据类型不一样时,还是像函数add()那样,由参数dtype来指定输出矩阵的类型。
②如何使用这个函数实现矩阵与标量相乘?很简单,按照下面这个公式:
dst
(
I
)
=
saturate
(
scale
⋅
src1
(
I
)
⋅
src2
(
I
)
)
\\textttdst (I)= \\textttsaturate ( \\textttscale \\cdot \\textttsrc1 (I) \\cdot \\textttsrc2 (I))
dst(I)=saturate(scale⋅src1(I)⋅src2(I))
我们只需要把其中一个矩阵设为全1的矩阵就行了嘛。
③函数mul()是函数multiply()的友好变体,下面这句代码:
cv::multiply(A1, B1, C1, scale1);
等效于:
cv::Mat C1 = A1.mul(2 * B1);
07-各种累积和
07-1-矩阵和的累加
可以用函数cv::accumulate()实现矩阵各元素和的累加,其官方文档介绍下:
示例代码暂时不给,要特别注意的是数据类型应该为浮点型。
07-1-对矩阵的点乘结果进行累加
可以利用函数cv::accumulateProduct()实现对矩阵各元素点乘的结果进行累加,函数cv::accumulateProduct()的官方文档如下:
同样要注意数据类型为浮点型,示例代码如下:
//OpenCV版本:3.0.0
//VS版本:2013
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
int main()
cv::Mat A1 = (cv::Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
cout << "A1中的数据为:\\n" << A1 << endl << endl;
cv::Mat B1 = (cv::Mat_<float>(2, 3) << 2, 3, 4, 5, 6, 7);
cout << "B1中的数据为:\\n" << B1 << endl << endl;
cv::Mat C1 = (cv::Mat_<float>(2, 3) << 3, 4, 5, 6, 7, 8);
cout << "没做累加前C1中的数据为:\\n" << C1 << endl << endl;
cv::accumulateProduct(A1, B1, C1);
cout << "做了累加后C1中的数据为:\\n" << C1 << endl << endl;
return(0);
运行结果如下:
07-3 按alpha比例累加(带权重的累加)
可以用函数cv::accumulateWeighted()实现矩阵元素按alpha比例累加(带权重的累加),其官方文档如下:
示例代码就不暂时不给了,同样要注意数据类型需要为浮点型。
还有上面文档中的running average我觉得可以翻译为滑动平均。
07-4 矩阵各元素平方值的累加
可以用函数accumulateSquare()实现各元素平方值的累加,其官方文档如下:
示例代码就不暂时不给了,同样要注意数据类型需要为浮点型。
08-矩阵乘法
可以用运算符“*”实现矩阵乘法,示例代码如下:
//OpenCV版本:3.0.0
//VS版本:2013
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
int main()
cv::Mat A1 = (cv::Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
cout << "A1中的数据为:\\n" << A1 << endl << endl;
cv::Mat B1 = (cv::Mat_<float>(3, 2) << 2, 3, 4, 5, 6, 7);
cout << "B1中的数据为:\\n" << B1 << endl << endl;
cv::Mat C1 = A1*B1;
cout << "C1中的数据为:\\n" << C1 << endl << endl;
return(0);
注意:类型必须为浮点型,即可以为“CV_32F或CV_64F”,而且似乎只支持一通道或两通道,三通道似乎不支持,因为我把上面的float改为uchar,那么报错如下:
运行结果如下:
我们手工验证下第一个结果:
12+24+3*6=2+8+18=28
可见的确做的是矩阵标准乘法。
09-矩阵乘方
想实现以矩阵A中的元素为底数,以矩阵B中元素为指数,但是目前没有找到相关函数。等以后找到了再写到这里吧…
10-矩阵的元素除法(点除)【真除,既保留整数也保留小数】
可以用函数cv::divide()和函数cv::mul()实现矩阵的元素除法(点除),其官方文档如下:
它的用法与函数cv::multiply()基本一样,所以它需要注意的地方请参见对函数cv::multiply()的介绍。
示例代码如下:
//OpenCV版本:3.0.0
//VS版本:2013
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
int main()
cv::Mat A1 = (cv::Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
cout << "A1中的数据为:\\n" << A1 << endl << endl;
cv::Mat B1 = (cv::Mat_<float>(2, 3) << 2, 3, 4, 5, 6, 7);
cout << "B1中的数据为:\\n" << B1 << endl << endl;
cv::Mat C1;
double scale = 2;
cv::divide(B1, A1, C1, scale);
cout << "C1中的数据为:\\n" << C1 << endl << endl;
cv::Mat C2 = B1.mul(scale / A1);
cout << "C2中的数据为:\\n" << C1 << endl << endl;
return(0);
运行结果如下:
从以上运行结果可以看出:
代码:
cv::divide(B1, A1, C1, scale);
等效于代码:
cv::Mat C2 = B1.mul(scale / A1);
我们把数据类型换为uchar,再看下结果,代码如下:
//OpenCV版本:3.0.0
//VS版本:2013
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
int main()
cv::Mat A1 = (cv::Mat_<uchar>(2, 3) << 1, 2, 3, 4, 5, 6);
cout << "A1中的数据为:\\n" << A1 << endl << endl;
cv::Mat B1 = (cv::Mat_<uchar>(2, 3) << 2, 3, 4, 5, 6, 7);
cout << "B1中的数据为:\\n" << B1 << endl << endl;
cv::Mat C1;
double scale = 2;
cv::divide(B1, A1, C1, scale);
cout << "C1中的数据为:\\n" << C1 << endl << endl;
cv::Mat C2 = B1.mul(scale / A1);
cout << "C2中的数据为:\\n" << C1 << endl << endl;
return(0);
对比浮点型的结果:
发现做得是五舍六入~
11 -矩阵的元素除法(点除)取整
这个目前博主没有发现相关函数,不过可以先做元素真除,然后用下面三个函数实现
向上取整函数cvCeil()
向下取整函数cvFloor()
四舍五入函数cvRound()
12-矩阵的元素除法(点除)取余
这个目前博主没有发现相关函数,想了下似乎只能每个元素与每个元素单独作系统库运算“%”。
13-矩阵的转置
可以用函数cv::transform()实现矩阵的转置。
官方文档如下:
示例代码如下:
//OpenCV版本:3.0.0
//VS版本:2013
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
int main()
cv::Mat A1 = (cv::Mat_<uchar>(2, 3) << 1, 2, 3, 4, 5, 6);
cout << "A1中的数据为:\\n" << A1 << endl << endl;
cv::Mat B1;
cv::transpose(A1, B1);
cout << "B1中的数据为:\\n" << B1 << endl << endl;
return(0);
运行结果如下:
延伸阅读:
Python的Numpy库中各种矩阵基本运算的示例代码(加、减、乘、点乘、点除、乘方、转置等)
归纳总结MATLAB中与矩阵运算有关的算术运算符(加、减、乘、除、点乘、点除、乘方、转置等)
以上是关于OpenCV中的MAT类矩阵的各种基本运算及示例代码(加减乘点乘点除乘方累加转置等)的主要内容,如果未能解决你的问题,请参考以下文章
opencv中Mat与IplImage,CVMat类型之间转换