Python版本是Python3.7.3,OpenCV版本OpenCV.3.4.1,开发环境为PyCharm
前面我们介绍了高斯金字塔,高斯金字塔是通过对一幅图像一系列的向下采样所产生的。有时,我们希望通过对金字塔中的小图像进行向上采样以获取完整的大尺寸高分辨率图像,这时就需要用到拉普拉斯金字塔。
11.5.1 定义
前面我们已经介绍过,一幅图像在经过向下采样后,再对其进行向上采样,是无法恢复为原始状态的。对此,我们也用程序进行了验证。向上采样并不是向下采样的逆运算。这是很明显的,因为向下采样时在使用高斯滤波器处理后还要抛弃偶数行和偶数列,不可避免地要丢失一些信息。
为了在向上采样时能够恢复具有较高分辨率的原始图像,就要获取在采样过程中所丢失的信息,这些丢失的信息就构成了拉普拉斯金字塔。
拉普拉斯金字塔的定义形式为:
Li=Gi - pyrUp(Gi+ 1)
式中:
● Li表示拉普拉斯金字塔中的第i层。
● Gi表示高斯金字塔中的第i层。
拉普拉斯金字塔中的第i层,等于“高斯金字塔中的第i层”与“高斯金字塔中的第i+1层的向上采样结果”之差。下图展示了高斯金字塔和拉普拉斯金字塔的对应关系。
eg1:使用函数cv2.pyrDown()和cv2.pyrUp()构造拉普拉斯金字塔。
程序如下:
import cv2
O=cv2.imread("lena.bmp")
G0=O
G1=cv2.pyrDown(G0)
G2=cv2.pyrDown(G1)
G3=cv2.pyrDown(G2)
L0=G0-cv2.pyrUp(G1)
L1=G1-cv2.pyrUp(G2)
L2=G2-cv2.pyrUp(G3)
print("L0.shape=",L0.shape)
print("L1.shape=",L1.shape)
print("L2.shape=",L2.shape)
cv2.imshow("L0",L0)
cv2.imshow("L1",L1)
cv2.imshow("L2",L2)
cv2.waitKey()
cv2.destroyAllWindows()
程序运行后,会输出如下运行结果:
L0.shape= (512, 512, 3)
L1.shape= (256, 256, 3)
L2.shape= (128, 128, 3)
程序还会显示如下图所示图像。
● ( a )图是通过语句“L0=G0-cv2.pyrUp(G1)”,用“原始图像G0”减去“图像G1的向上采样结果”,得到的拉普拉斯金字塔的第0层L0。
● ( b )图是通过语句“L1=G1-cv2.pyrUp(G2)”,用“图像G1”减去“图像G2的向上采样结果”,得到的拉普拉斯金字塔的第1层L1。
● ( c )图是通过语句“L2=G2-cv2.pyrUp(G3)”,用“图像G2”减去“图像G3的向上采样结果”,得到的拉普拉斯金字塔的第2层L2。
11.5.2 应用
拉普拉斯金字塔的作用在于,能够恢复高分辨率的图像。下图演示了如何通过拉普拉斯金字塔恢复高分辨率图像。其中,右图是对左图的简化。
图中的各个标记的含义如下:
● G0、G1、G2、G3分别是高斯金字塔的第0层、第1层、第2层、第3层。
● L0、L1、L2分别是拉普拉斯金字塔的第0层、第1层、第2层。
● 向下的箭头表示向下采样操作(对应cv2.pyrDown()函数)。
● 向右上方的箭头表示向上采样操作(对应cv2.pyrUp()函数)。
● 加号“+”表示加法操作。
● 减号“-”表示减法操作。
在图中,描述的操作及关系有:
● 向下采样(高斯金字塔的构成)
G1=cv2.pyrDown(G0)
G2=cv2.pyrDown(G1)
G3=cv2.pyrDown(G2)
● 拉普拉斯金字塔
L0=G0-cv2.pyrUp(G1)
L1=G1-cv2.pyrUp(G2)
L2=G2-cv2.pyrUp(G3)
● 向上采样恢复高分辨率图像
G0=L0+cv2.pyrUp(G1)
G1=L1+cv2.pyrUp(G2)
G2=L2+cv2.pyrUp(G3)
上述关系是通过数学运算推导得到的。例如,已知L0=G0-cv2.pyrUp(G1),将表达式右侧的cv2.pyrUp(G1)移到左侧,就得到了表达式G0=L0+cv2.pyrUp(G1)。除此之外,G1和G2都可以通过拉普拉斯金字塔的构造表达式得到。在前面已经介绍过了,构造拉普拉斯金字塔的目的就是为了恢复高分辨率的图像。
eg2:编写程序,使用拉普拉斯金字塔及高斯金字塔恢复原始图像。
程序如下:
import cv2
import numpy as np
O=cv2.imread("lena.bmp")
G0=O
G1=cv2.pyrDown(G0)
L0=O-cv2.pyrUp(G1)
RO=L0+cv2.pyrUp(G1) #通过拉普拉斯图像复原的原始图像
print("O.shape=",O.shape)
print("RO.shape=",RO.shape)
result=RO-O #将o和ro做减法
#计算result的绝对值,避免求和时负负为正3+(-3)=0
result=abs(result)
#计算result所有元素的和
print("原始图像O与恢复图像RO差值的绝对值和:",np.sum(result))
本程序中:
● 第4行将原始图像O赋值给G0,对原始图像重命名,方便后续进行观察和说明。
● 第5行对图像G0(高斯金字塔的第0层)进行向下采样,得到向下采样的结果,即高斯金字塔的第1层G1。
● 第6行使用原始图像O减去图像G1的向上采样,得到拉普拉斯金字塔的第0层L0。
● 第7行使用L0加上图像G1的向上采样结果,得到恢复的原始图像RO。
● 第10行计算原始图像O与恢复的图像RO之差。如果差值图像result的元素值全部为0,则说明图像RO和图像O内的像素值完全一致;否则,不一致。
● 第12行计算result内所有元素值的绝对值,然后计算result内所有值的和是否为零,以此判断其所有元素值是否都为零。这样写是为了避免result内的正数值和与负数值之和正好抵消的情况。比如,result中存在两个不为零的值,一个为正值“3”,另一个为负值“-3”,虽然并非所有元素都为零,但是它们相加求和的结果是零。在这种情况,通过和为零来判断所有元素都是零,显然是不正确的。而取绝对值后再求和,通过绝对值和是否为零来判断是否所有元素都是零,则避免了可能的误判情况。
程序运行后,会输出如下运行结果:
O.shape= (512, 512, 3)
RO.shape= (512, 512, 3)
原始图像O与恢复图像RO差值的绝对值和: 0
从程序运行结果可以看到,原始图像与恢复图像差值的绝对值和为“0”。这说明使用拉普拉斯金字塔恢复的图像与原始图像完全一致。
eg3:编写程序,使用拉普拉斯金字塔及高斯金字塔恢复高斯金字塔内的多层图像。
:程序如下:
import cv2
import numpy as np
O=cv2.imread("lena.bmp")
#=================生成高斯金字塔======================
G0=O
G1=cv2.pyrDown(G0)
G2=cv2.pyrDown(G1)
G3=cv2.pyrDown(G2)
#===============生成拉普拉斯金字塔====================
L0=G0-cv2.pyrUp(G1) #拉普拉斯金字塔第0层
L1=G1-cv2.pyrUp(G2) #拉普拉斯金字塔第1层
L2=G2-cv2.pyrUp(G3) #拉普拉斯金字塔第2层
#=================复原G0======================
RG0=L0+cv2.pyrUp(G1) #通过拉普拉斯图像复原的原始图像G0
print("G0.shape=",G0.shape)
print("RG0.shape=",RG0.shape)
result=RG0-G0 #将RG0和G0做减法
#计算result的绝对值,避免求和时负负为正3+(-3)=0
result=abs(result)
#计算result所有元素的和
print("原始图像G0与恢复图像RG0差值的绝对值和:",np.sum(result))
#=================复原G1======================
RG1=L1+cv2.pyrUp(G2) #通过拉普拉斯图像复原G1
print("G1.shape=",G1.shape)
print("RG1.shape=",RG1.shape)
result=RG1-G1 #将o和ro做减法
print("原始图像G1与恢复图像RG1差值的绝对值和:",np.sum(abs(result)))
#=================复原G2======================
RG2=L2+cv2.pyrUp(G3) #通过拉普拉斯图像复原G2
print("G2.shape=",G2.shape)
print("RG2.shape=",RG2.shape)
result=RG2-G2 #将o和ro做减法
print("原始图像G2与恢复图像RG2差值的绝对值和:",np.sum(abs(result)))
本程序中:
● 第14行通过“拉普拉斯金字塔的第0层L0”与“高斯金字塔第1层G1向上采样的结果cv2.pyrUp(G1)”之和,恢复了原始图像G0,得到RG0。
● 第23行通过“拉普拉斯金字塔的第1层L1”与“高斯金字塔第2层G2向上采样的结果cv2.pyrUp(G2)”之和,恢复了原始图像G1,得到RG1。
● 第29行通过“拉普拉斯金字塔的第2层L2”与“高斯金字塔第3层G3向上采样的结果cv2.pyrUp(G3)”之和,恢复了原始图像G2,得到RG2。
程序运行后,会输出如下运行结果:
G0.shape= (512, 512, 3)
RG0.shape= (512, 512, 3)
原始图像G0与恢复图像RG0差值的绝对值和: 0
G1.shape= (256, 256, 3)
RG1.shape= (256, 256, 3)
原始图像G1与恢复图像RG1差值的绝对值和: 0
G2.shape= (128, 128, 3)
RG2.shape= (128, 128, 3)
原始图像G2与恢复图像RG2差值的绝对值和: 0
从程序运行结果可以看到,在每一层中,原始图像与恢复图像差值的绝对值和都为“0”。这说明使用拉普拉斯金字塔恢复的图像与原始图像完全一致。