图像的算术运算有很多种,比如两幅图像可以相加,相减,相乘,相除,位运算,平方根,对数,绝对值等;图像也可以放大,缩小,旋转,还可以截取其中的一部分作为ROI(感兴趣区域)进行操作,各个颜色通道还可以分别提取对各个颜色通道进行各种运算操作。总之,对图像可以进行的算术运算非常的多。这里先学习图片间的数学运算,图像混合,按位运算。
6.1 cv2.add()图像矩阵加法
作用:函数 cv2.add() 对两张相同大小和类型的图像进行加法运算,或对一张图像与一个标量进行加法运算。
原型:cv2.add(src1, src2 [, dst[, mask[, dtype]]) → dst
参数:
- scr1, scr2:进行加法运算的图像,或一张图像与一个 numpy array 标量
- dst:输出的图像,可选项,默认值为 None
- mask:掩模图像,8位灰度格式;掩模图像数值为 0 的像素,输出图像对应像素的各通道值也为 0。可选项,默认值为 None
- dtype:图像数组的深度,即每个像素值的位数,可选项
返回值:dst,运算结果图像,ndarray 多维数组
注意:OpenCV中的加法与Numpy的加法是有所不同的,OpenCV的加法是一种饱和操作,而Numpy的加法是一种模操作。
Numpy库的加法
其运算方法是:目标图像 = 图像1 + 图像2,运算结果进行取模运算
- 当像素值 小于等于 255 时,结果为:“图像1 + 图像2”,例如:120+48=168
- 当像素值 大于255 时,结果为:对255取模的结果,例如:(255 + 64) % 255 = 64
OpenCV的加法
其运算方法是:目标图像 = cv2.add(图像1, 图像2)
- 当像素值 小于等于 255 时,结果为:“图像1 + 图像2”,例如:120+48=168
- 当像素值 大于255 时,结果为:255,例如:255 + 64 = 255
示例
import cv2
import numpy as np
# 【读取图片】
original = cv2.imread('C:\\Users\\xxx\\Downloads\\lena.jpg')
img = original.copy()
test = original.copy()
result1 = img + test # Numpy加法运算
result2 = cv2.add(img, test) # OpenCV加法运算
#all_pic = np.column_stack((img, result1, result2))
# 【显示图像】
#cv2.imshow('img result1 result2', all_pic)
cv2.imshow("original", img)
cv2.imshow("result1=Numpy+", result1)
cv2.imshow("result2=cv2.add()", result2)
# 【等待显示】
cv2.waitKey(0)
cv2.destroyAllWindows()
6.2 cv2.addWeighted()图像混合
线性混合操作 也是一种典型的二元(两个输入)的 像素操作 :
distx=α∙src1x+β∙src2x+γ
原型:dst=cv2.addWeigthted(src1, α,src2, β, γ)
参数:
- src1、src2:图像1、图像2
- α、β:图像1、图像2的权重
- γ:亮度调节量
作用:图像融合通常是指将2张或者两张以上的图像信息融合到1张图像上,融合的图像含有更多的信息,能够更方便人们观察或计算机处理。图像融合是在图像加法的基础上增加了系数和亮度调节量。
图像融合:目标图像 = 图像1*权重1 + 图像2*权重2 + 亮度调节量
图像混合 cv2.addWeighted() 也是一种图片相加的操作,只不过两幅图片的权重不一样, γ相当于一个修正值:
返回值:dst = α*src1 + β*src2 + γ, 当 α 和 β 都等于1,则相当于图片相加。
注意:两张图片的尺寸必须一致。若不一致,则需要用cv2.resize()调整为一致。
示例
import cv2
import numpy as np
img1 = cv2.imread('C:\\Users\\xxx\\Downloads\\picture1.jpeg')
img2 = cv2.imread('C:\\Users\\xxx\\Downloads\\picture2.jpeg')
#print(img1.shape, img2.shape) # (900, 1440, 3) (1500, 1200, 3)
img1 = cv2.resize(img1, (900, 600)) # 将两个图片的大小设置为一样
img2 = cv2.resize(img2, (900, 600))
#print(img1.shape, img2.shape) #(600, 900, 3) (600, 900, 3)
res = cv2.addWeighted(img1, 0.6, img2, 0.4, 0)
cv2.imshow("img1", img1)
cv2.imshow("img2", img2)
cv2.imshow("(img1*0.6+img2*0.4+0)", res)
cv2.waitKey(0)
cv2.destroyAllWindows()
6.3
cv2.subtract()
图像矩阵减法
图像矩阵减法与加法其实类似。
原型
:
cv2.subtract
(src1, src2 [, dst[, mask[, dtype]]) → dst
参数:
- src1:作为被减数的图像数组或一个标量
- src2:作为减数的图像数组或一个标量
- dst:可选参数,输出结果保存的变量,默认值为None,如果为非None,输出图像保存到dst对应实参中,其大小和通道数与输入图像相同,图像的深度(即图像像素的位数)由dtype参数或输入图像确
- mask:图像掩膜,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0
- dtype:可选参数,输出图像数组的深度,即图像单个像素值的位数(如RGB用三个字节表示,则为24位)。
返回值:相减的结果图像
四种运用场景:
- 两个图像矩阵相减, 要求两个矩阵必须有相同大小和通道数:dst(I)=saturate(src1(I)-src2(I)) if mask(I)≠0
- 1个图像矩阵和1个标量相减, 要求src2是标量或者与src1的通道数相同的元素个数,经实际测试应该是一个四元组,如果src1是3通道的,则按通道顺序依次与该四元组的前3个元素相减:dst(I)=saturate(src1(I)-src2)if mask(I)≠0
- 1个标量和一个图像数组相减, 要求src1是标量或者与src1的通道数相同的元素个数:dst(I)=saturate(src1-src2(I))if mask(I)≠0
- 在给定值减去矩阵的SubRS情况下,为1个标量和一个图像数组相减的反向差,这是第二种场景的一种特殊解读:dst(I)=saturate(src2-src1(I))if mask(I)≠0
注意:OpenCV中的减法与Numpy的减法是有所不同的,OpenCV的减法是一种饱和操作,而Numpy的加法是一种模操作。
Numpy库的减法
其运算方法是:目标图像 = 图像1 - 图像2,运算结果进行取模运算
- 当像素值 大于等于 0 时,结果为:“图像1 - 图像2”,例如:120-48=72
- 当像素值 小于0 时,结果为:对256相加的结果,例如:(48-120)+ 256 = 184
OpenCV的加法
其运算方法是:目标图像 = cv2.subtract(图像1, 图像2)
- 当像素值 大于于等于 0 时,结果为:“图像1 - 图像2”,例如:120-48=72
- 当像素值 小于0 时,结果为:0,例如:48-120 = 0
示例
import cv2
import numpy as np
# 【读取图片】
img1 = cv2.imread('C:\\Users\\xxx\\Downloads\\picture1.jpeg')
img2 = cv2.imread('C:\\Users\\xxx\\Downloads\\picture2.jpeg')
#print(img1.shape, img2.shape) # (900, 1440, 3) (1500, 1200, 3)
# 【将两个图片的大小设置为一样】
img1 = cv2.resize(img1, (900, 600))
img2 = cv2.resize(img2, (900, 600))
result1 = img1 - img2 # Numpy减法运算
result2 = cv2.subtract(img, test) # OpenCV减法运算
# 【显示图像】
cv2.imshow("original1", img1)
cv2.imshow("original2", img2)
cv2.imshow("result1=Numpy-", result1)
cv2.imshow("result2=cv2.subtract()", result2)
# 【等待显示】
cv2.waitKey(0)
cv2.destroyAllWindows()
6.4 图片质量比较之PSNR和SSIM
PSNR
PSNR,Peak Signal-to-Noise Ratio,峰值信噪比,是一个表示信号最大可能功率和影响它的表示精度的破坏性噪声功率的比值的工程术语。由于许多信号都有非常宽的动态范围,峰值信噪比常用对数分贝单位来表示。
PSNR 是用于衡量图像质量的指标,比如在图像压缩、超分辨率重建图像等领域,其是一种重要的指标.
PSNR 常简单的通过均方误差(MSE)来定义. 比如,对于两张单色图像 I 和 K,如果一个为另外一个的噪声近似,则二者之间的均方误差定义为:
而峰值信噪比PSNR 的定义为:
其中,MaxI 表示图像点颜色的最大数值,如果每个采样点用 8 位表示,则最大数值为 255.
更通用的表示是,如果每个采样点用 B 位线性脉冲编码调制表示,则 ,即
类似地,对于每点有 RGB 三个值的彩色图像来说,PSNR 的定义也是类似的,只是均方误差是所有方差之和除以图像尺寸再除以3。
MSE 越小,则 PSNR 越大;PSNR越大,代表着图像质量越好。
- PSNR高于40dB说明图像质量极好(即非常接近原始图像)
- 在30-40dB通常表示图像质量是好的(即失真可以察觉但可以接受)
- 在20-30dB说明图像质量差
- 低于20dB图像不可接受
SSIM
SSIM,Structural Similarity,结构相似性. 也是衡量两幅图片相似性的指标。
结构相似性的基本原理是,认为自然图像时高度结构化的,即相邻像素间具有很强的关联性,而这种关联性表达了场景中物体的结构信息. 人类视觉系统对于图像已经具有很强的理解与信息抽取能力,所以在衡量图像质量时,结构性失真是很重要的考量.。