3.3 元素级矩阵操作
基于元素的(元素级)矩阵操作是计算机视觉中的一类数学函数和算法,它处理矩阵的各个元素,或者说,图像中的每个像素。注意基于元素的操作可以并行化,因此矩阵元素的处理顺序不重要。这个特点是本节函数和算法与本章的后续小节中的函数和算法的重要区别。
3.3.1 基本操作
OpenCV提供了所有必要的函数和重载操作符来进行两个矩阵之间或矩阵和标量之间的加减乘除操作。
3.3.1.1 加法操作
函数add和运算符+可用于两个矩阵间元素相加或一个矩阵的元素与一个标量相加,如下例所示:
可以使用以下代码替换前面代码中的最后一行:
下图显示了两个图像相加后的结果:
如果你想给Mat对象的每个元素都加上一个标量值,可以用类似如下代码:
如果在灰度图像上执行上述代码,结果将比源图像有更高的亮度。请注意,如果图像有三个通道,则必须使用包含三个元素的向量而不是单个值。例如,为了使RGB图像更亮,你可以使用如下代码:
下图展示了上述代码执行之后的效果,处理后的图像亮度比源图像提高了:
在前面的示例代码中,仅通过在每个像素上增加一个数值即可获得更亮的图像。
3.3.1.2 加权加法
除了简单将两个图像相加,你还可以使用加权加法,加权加法会对每个图像增加权重之后再相加。这相当于对加法的每个参与者分别设置不透明度级别。要进行加权加法,你可以使用addWeighted函数:
如果使用此代码来处理上一节中的示例图片,结果将类似于下图:
透明文本类似于通常在照片编辑程序使用的水印。你注意到代码中对alpha、beta和gamma值的注释了吗?显然,如果beta值为1.0则上面的例子就跟普通的图像叠加函数完全相同,此时叠加文本没有透明度。
3.3.1.3 减法操作
与两个Mat对象叠加类似,你也可以使用substract函数或-运算符从一个图像的所有元素中减去另一个图像的所有元素。请看下例:
上面代码中的最后一行也可以替换为:
如果我们使用前面示例中的图像,则减法操作的结果如下:
从源图像中减去较高像素值(较亮像素)会生成深色的叠加文本。另外,与加法不同,减法运算结果与其操作数的顺序相关。尝试交换操作数,自己看看会发生什么。
就像图像加法一样,也可以让图像的所有像素减去一个常数。你可以猜到,从所有像素中减去常量值将生成更暗的图像(取决于该值的大小),这与加法运算相反。下面展示了通过简单的减法操作使图像变得更暗的例子:
如果源图像是三通道RGB图像,则需要使用向量作为第二个操作数:
3.3.1.4 乘法和除法操作
与加法和减法类似,你还可以将Mat对象的所有元素与另一个Mat对象的所有元素相乘或相除。同样,两个操作都可以使用矩阵和标量。乘法可以使用OpenCV的multiply函数(类似于Mat :: mul函数),而除法可以使用divide函数。
见下例:
前面代码中的scale是一个附加参数,可以传给multiply和divide函数来缩放结果中Mat对象的所有元素。你还可以在矩阵乘法或除法中使用标量,如下示例所示:
显然,前面的代码将生成两个图像,一个是源图像亮度的5倍(变亮),一个是源图像亮度的1/5(变暗)。这里要注意的一点是,与加法和减法不同,乘除法得到的图像不会均匀地变亮或变暗,你应该会注意到较亮的区域变得更亮,反之亦然。其原因显然是由于乘法和除法运算的效果与加减法不同,经过乘除法操作后,较亮像素的值上升或下降要快得多。有趣的是,在大多数照片编辑应用程序中,就是使用这个技术来使图像的明亮区域变亮或变暗的。