图像上算数运算
1、图像加法
1.1 Numpy的加法
图像对象可以直接使用“+”号为图像的每个通道加上指定的值。
如下示例,为每个通道中的每个值加10。
# 使用“+”号进行数值计算
import cv2
img = cv2.imread("E:/tmp/img/cat.png")
# 原始数值
# img[:5, :8, 0] 表示读取前5行(h),前8列(w),B通道的值,方便结果验证
print(img[:5, :8, 0])
print("-----分割线-----")
# 相加后数值,将对每个通道中的每个值加10
img2 = img + 10
print(img2[:5, :8, 0])
cv2.imshow("test", img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
BGR值在0-255范围,在进行数值相加时有可能会出现超过255值的情况,OpenCV将自动获取超过255部分的作为结果值,如图1.1所示。
图1.1 图像加法运行结果
1.2 Numpy的加法的加法
也可以使用cv2.add()函数将两幅图像进行加法运算。需要注意,使用该方法时,需要保证两幅图像的大小、类型一致。或者第2个图像使用一个简单的常量值(类似蒙板)。
示例代码如下所示。
# 数值计算
import cv2
import numpy
cat = cv2.imread("E:/tmp/img/cat.png")
dog = cv2.imread("E:/tmp/img/dog.jpg")
h, w = cat.shape[:2]
# 根据cat图像尺寸创建空的dog画布
dog2 = numpy.zeros_like(cat)
# 截取dog图像中部分内容,赋值到dog2画布中
dog2[:h, :w] = dog[:h, :w]
# 此时cat图像与dog2图像尺寸已经一致,满足使用add()函数的条件
newImg = cv2.add(cat, dog2)
print("1、cat图像矩阵")
print(cat[0:3, 0:8, 0])
print("\n2、dog2图像矩阵")
print(dog2[0:3, 0:8, 0])
print("\n3、cat与dog2运算后的图像矩阵")
print(newImg[0:3, 0:8, 0])
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如下。
图2.1 add()函数运行结果
从上例子可以看出,add()函数也可以实现图像加法。使用add()函数这种加法要比使用“+”加法效果好一点,add()函数的加法是一种饱和操作,而Numpy的加法("+")是一种模操作,所以建议大家尽量使用OpenCV中的函数进行操作。
Numpy加法与OpenCV函数加法的区别:
Numpy加法,两个数相加,如果和大于255,将取两个值的和。
OpenCV函数的加法,两个相同尺寸的图像相加,如果和大于255,取值为255,否则取值为本身。
2、图像融合
图像融合其实也是加法,但是不同的是两幅图像的权重可以自定义,就会给人一种混合或者透明的感觉。可以使用cv2.addWeighted()函数实现图像融合,使用该函数前要求两幅图像尺寸致。
cv2.resize()函数用于根据给定的维度变化图像尺寸,它可以给定尺寸变化图像,也可以给定倍数变化图像。
2.1 根据给定尺寸变化图像
示例:将dog图像变化成cat图像一样大小
import cv2
cat = cv2.imread("E:/tmp/img/cat.png")
dog = cv2.imread("E:/tmp/img/dog.jpg")
# 获取cat图像尺寸
h, w = cat.shape[:2]
# 设置dog图像尺寸与cat图像尺寸一致,(w, h)中w为图像的宽,h为图像的高
# 重置图像尺寸
newDog = cv2.resize(dog, (w, h))
# 获取cat和newDog的尺寸
print(cat.shape)
print(newDog.shape)
cv2.imshow("cat", cat)
cv2.imshow("dog", newDog)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.2 根据比例变化图像
import cv2
dog = cv2.imread("E:/tmp/img/dog.jpg")
# 1、将dog图像缩小1倍,在使用倍数改变图像时,尺寸参数应该设置为(0,0),表示不使用尺寸更改
narrow = cv2.resize(dog, (0, 0), fx=0.2, fy=0.2)
# 2、将dog图像放大1倍
expand = cv2.resize(dog, (0, 0), fx=2, fy=2)
# 3、将dog图像的宽度缩小1倍
width_narrow = cv2.resize(dog, (0, 0), fx=0.5, fy=1)
# 展示结果
cv2.imshow("original", dog) # 原始图像
cv2.imshow("narrow", narrow) # 缩小
cv2.imshow("expand", expand) # 放大
cv2.imshow("width_narrow", width_narrow) # 宽度缩小
cv2.waitKey(0)
cv2.destroyAllWindows()
2.3 权重加法
cv2.addWeighted(img1, α , img2, β, b)
OpenCV还提供了带权重的加法,即两副图像的像素通道值相加时各自按一定的权重比例取值来相加。
假设有2个图像矩阵img1和img2,在两个图像融合时,各自的权重分别为α和β,b为偏移量,表示在亮度集上的微调,则二者融合后的目标图像dst中各像素通道值的计算公式为:
dst = α · img1 + β · img2 + b
示例:设置cat图像权重为0.7,dog图像权重为0.3,亮度集为0。
import cv2
cat = cv2.imread("E:/tmp/img/cat.png")
dog = cv2.imread("E:/tmp/img/dog.jpg")
# 获取cat图像尺寸
h, w = cat.shape[:2]
# 设置dog2尺寸与cat图像尺寸一致
dog2 = cv2.resize(dog, (w, h))
# 展示显示
cv2.imshow("cat", cat)
cv2.imshow("dog", dog2)
# 按权重将cat与dog图像融合
fusion_img = cv2.addWeighted(cat, 0.7, dog2, 0.3, 0)
cv2.imshow("Fusion Image", fusion_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行结果如下。
图2.1 addWeighted()运行结果