在处理数据时需要对数据进行加减乘除运算,例如对图像进行滤波、增强等操作都需要对像素级别进行加减乘除运算。为了方便运算,Mat类变量支持矩阵的加减乘除运算,即我们在使用Mat类变量时,将其看做普通的矩阵即可,例如Mat类变量与常数相乘遵循矩阵与常数相乘的运算法则。Mat类与常数运算时,可以直接通过加减乘除符号实现。
Mat类的加减法运算
cv::Mat a = (cv::Mat_<int>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
cv::Mat b = (cv::Mat_<int>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
cv::Mat c = (cv::Mat_<double>(3, 3) << 1.0, 2.1, 3.2, 4.0, 5.1, 6.2, 2, 2, 2);
cv::Mat d = (cv::Mat_<double>(3, 3) << 1.0, 2.1, 3.2, 4.0, 5.1, 6.2, 2, 2, 2);
cv::Mat e, f, g, h, i;
e = a + b;
f = c - d;
g = 2 * d;
h = d / 2.0;
i = a – 1;
结果:
a =
[1, 2, 3;
4, 5, 6;
7, 8, 9]
b =
[1, 2, 3;
4, 5, 6;
7, 8, 9]
c =
[1, 2.1, 3.2;
4.3, 5.4, 6.5;
7.6, 8.699999999999999, 9.800000000000001]
d =
[1, 2.1, 3.2;
4.3, 5.4, 6.5;
7.6, 8.699999999999999, 9.800000000000001]
e =
[2, 4, 6;
8, 10, 12;
14, 16, 18]
f =
[0, 0, 0;
0, 0, 0;
0, 0, 0]
g =
[2, 4.2, 6.4;
8.6, 10.8, 13;
15.2, 17.4, 19.6]
h =
[0.5, 1.05, 1.6;
2.15, 2.7, 3.25;
3.8, 4.35, 4.9]
i =
[0, 1, 2;
3, 4, 5;
6, 7, 8]
这里需要注意的是,当两个Mat类变量加减运算时,必须保证两个矩阵中的数据类型是相同的,即两个分别保存int和double数据类型的Mat类变量不能进行加减运算。与常规的乘除法不同之处在于,常数与Mat类变量运算结果的数据类型保留Mat类变量的数据类型,例如,double类型的常数与int类型的Mat类运算,最后结果仍然为int类型。
在对图像进行卷积运算的时候,需要两个矩阵进行乘法运算,opencv不仅提供了两个Mat类矩阵的乘法运算,而且定义了两个矩阵的内积和对应位的乘法运算。
两个Mat类矩阵的乘法运算
cv::Mat j, m;
double k;
j = c*d;
k = a.dot(b);
m = a.mul(b);
运行结果:
j =
[34.35, 41.28, 48.21000000000001;
76.92, 94.73999999999999, 112.56;
119.49, 148.2, 176.91]
k =
285
m =
[1, 4, 9;
16, 25, 36;
49, 64, 81]
在上面的代码中定义了两个Mat类变量和一个double变量,分别实现了两个Mat类矩阵的乘法、内积和对应位乘法。第三行代码中的“”运算符表示两个矩阵的数学乘积,例如存在两个矩阵A3×3和B3×3,“”运算结果为C3×3,C3×3中的每一个元素表示为:
cij=ai1b1j+ai2b2j+ai3b3j,需要注意的是。“*”运算要求第一个Mat类矩阵的列数必须与第二个Mat类矩阵的行数相同,而且该运算要求Mat类中的数据类型必须是CV_32FC1、CV_64FC1、CV_32FC2、CV_64FC2这四种的一种,也就是对于一个二维的Mat类矩阵,其保存的数据类型必须是float类型或者double类型。
关于Mat类矩阵的dot运算和mul运算可以参照下面的链接:
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
【注】Mat类矩阵的dot运算是把两个矩阵每一位上对应的数相乘然后相加返回一个double类型的数值。
Mat类矩阵的mul运算是把两个矩阵每一位上对应的数相乘返回一个Mat类型的矩阵。
需要注意的是,不同于前两种乘法运算,参与mul()方法运算的两个Mat类矩阵中保存的数据在保证相同的前提下,可以使任何一种类型,并且默认的输出数据类型与两个Mat类矩阵保持一致。在图像处理领域,常用的数据类型是CV_8U,其数据范围是0-255,当两个比较大的整数相乘时就会产生结果溢出的现象,输出结果为255,因此在使用mul()方法时需要防止数据溢出的现象。