图像为什么能相加

来源:互联网 发布:java脱产班 编辑:程序博客网 时间:2024/05/01 01:07

我们知道2个矩阵是可以执行加法运算的,那2个图像能不能相加呢?当然是可以的。前面提到,图像就是函数,函数可以相加,图像当然也可以相加。

我们知道2个矩阵相加必须是同一维度的,即行列相同,图像当然也一样,即宽度和高度相同。

我们看下面2副图像:
这里写图片描述

这里写图片描述

import cv2boats = cv2.imread("boats.bmp", 0)goldhill = cv2.imread("goldhill.bmp", 0)print(boats.shape)print(goldhill.shape)

输出结果:

(576, 720)(576, 720)

可以看出,这2副图像的宽度和高度分别是720和576,大小是一致的。2个图像相加就是2个矩阵相加。

unite = boats + goldhillcv2.imshow("unite", unite)cv2.waitKey()

输出结果:

这里写图片描述

不怎么样嘛!白块,黑块怎么那么多!有的地方变白了,有的地方变黑了。what’s wrong?

我们知道,图像的强度取值区间是[0, 255],opencv的图像类型是uint8类型。而numpy的矩阵加法是一种模(mod)操作,即200+60=260 % 256 = 4,所以该亮的地方反而暗淡了。

opencv自带有图像加法操作运算函数:add(x, y)。add使用的是饱和操作,即200+60=260->255。所以使用opencv自带的add()函数效果会更好。

另外,2副图像相加,我们实际上需要的2副图像相对位置强度的平均值,因此在相加前,需要各除以2,然后再相加(注意要整除)。

unite = cv2.add(boats // 2 , goldhill // 2)cv2.imshow("unite", unite)cv2.waitKey()

这里写图片描述

我们知道,除以2和乘以0.5是等价的。乘以0.5是一个数乘运算,也就是说,图像自身还可以进行这种运算(注意乘以浮点数后矩阵类型发生了改变,而opencv的图像矩阵必须转换成为uint8类型才能正常显示)。

boats20 = 0.2 * boatsboats20 = boats20.astype("uint8")cv2.imshow("boats20", boats20)cv2.waitKey()

输出结果:
这里写图片描述

可以看到,整体效果暗淡了很多。因为所有的像素点的值都乘以了0.2,强度变成了原来的20%。如果乘的数值小于1,图像整体就变暗,如果乘的数值大于1,整体就变亮。

这给了我们混合2张图像的一种比率调和方法,例如最前面2张图,我们想要看到更多的船(注意为确保2张图像的混合值小于255,系数之和应保持等于1)。

unite = 0.75 * boats + 0.25 * goldhillunite = unite.astype("uint8")cv2.imshow("unite", unite)cv2.waitKey()

这里写图片描述

当然,opencv已经为我们准备好了函数addWeighted
()。代码如下,效果是一样的。

unite = cv2.addWeighted(boats, 0.75, goldhill, 0.25, 0)cv2.imshow("unite", unite)cv2.waitKey()

那么:图像为什么要相加呢?为了混合(blend)2张图像。

实质上,图像相加还有一个用途:降噪。同一场景的不同时间采集图像通过相加平均后去除噪声,这个后面再讲。

原创粉丝点击