一、什么是图像金字塔¶
图像金字塔底部是待处理的高分辨率图像,也就是原始图像,顶部是低分辨率的近似图像。一般情况下,都是每向上移动一级,图像的宽和高都降低为原来的1/2 。
二、为什么要生成图像金字塔,图像金字塔能干啥?
三、理论基础:下采样、上采样、滤波器
如果我们通过下采样生成一个金字塔,最简单的做法就是:不断地删除图像的偶数行和偶数列,重复这个过程,就得到一个金字塔。
如果我们通过上采样生成一个金字塔,最简单的就是:在每列像素点的右边插入值为0的列,在每行像素点下面插入值为0的行,不断重复,就生成一个金字塔了。
小结:
1、下采样是图像不断变小的过程,上采样是图像不断变大的过程。
2、一个图像下采样一次,在执行一次上采样,虽然尺寸恢复到原图像的尺寸,但像素值已经改变!!!也就是这两种操作是不可逆的。
四、上下采样API:
下采样:cv2.pyrDown(img [, dstsize, borderType])
上采样:cv2.pyrUp(img [, dstsize, borderType])
默认的尺寸都是一半一半的减小,或者一倍一倍的增加。
默认的滤波器都是高斯滤波器。
#例11.1 对lena进行下采样
import cv2
import numpy as np
import matplotlib.pyplot as plt
lena0 = cv2.imread(r'C:\Users\25584\Desktop\lena.bmp', 0)
lena1 = cv2.pyrDown(lena0)
lena2 = cv2.pyrDown(lena1)
lena3 = cv2.pyrDown(lena2)
lena4 = cv2.pyrDown(lena3)
Fig=plt.figure(figsize=(16,10))
Grid=plt.GridSpec(33,33)
axes1=Fig.add_subplot(Grid[:17,:17]), plt.imshow(lena0, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes2=Fig.add_subplot(Grid[:9,17:25]), plt.imshow(lena1, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes3=Fig.add_subplot(Grid[:5,25:29]), plt.imshow(lena2, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes4=Fig.add_subplot(Grid[:3,29:31]), plt.imshow(lena3, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes5=Fig.add_subplot(Grid[:1,31:32]), plt.imshow(lena4, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
plt.show()
#例11.2 对lena进行上采样
import cv2
import numpy as np
import matplotlib.pyplot as plt
lena0 = cv2.imread(r'C:\Users\25584\Desktop\lena.bmp', 0) #512
lena1 = cv2.pyrUp(lena0) #1024
lena2 = cv2.pyrUp(lena1) #2048
lena3 = cv2.pyrUp(lena2) #4096
Fig=plt.figure(figsize=(16,10))
Grid=plt.GridSpec(16,16)
axes1=Fig.add_subplot(Grid[0,0]), plt.imshow(lena0, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes2=Fig.add_subplot(Grid[0:3,1:3]), plt.imshow(lena1, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes3=Fig.add_subplot(Grid[0:5,3:7]), plt.imshow(lena2, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes4=Fig.add_subplot(Grid[0:9,7:15]), plt.imshow(lena3, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
plt.show()
#例11.3 对lena先下采样再上采样,看结果图核原始图的差异,然后再lena先上采样再下采样,看结果图和原始图的差异
import cv2
import numpy as np
import matplotlib.pyplot as plt
lena0 = cv2.imread(r'C:\Users\25584\Desktop\lena.bmp', 0) #512
lena1 = cv2.pyrDown(lena0) #216
lena2 = cv2.pyrUp(lena1) #512
diff1 = lena2-lena0
lena11 = cv2.pyrUp(lena0) #1024
lena22 = cv2.pyrDown(lena11) #512
diff2 = lena22-lena0
Fig=plt.figure(figsize=(16,10))
Grid=plt.GridSpec(6,10)
axes1=Fig.add_subplot(Grid[:2,:2]), plt.imshow(lena0, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes2=Fig.add_subplot(Grid[0,2]), plt.imshow(lena1, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes3=Fig.add_subplot(Grid[:2,3:5]), plt.imshow(lena2, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes4=Fig.add_subplot(Grid[:2,5:7]), plt.imshow(diff1, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes21=Fig.add_subplot(Grid[2:4,:2]), plt.imshow(lena0, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes22=Fig.add_subplot(Grid[2:6,2:6]), plt.imshow(lena11, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes23=Fig.add_subplot(Grid[2:4,6:8]), plt.imshow(lena22, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes24=Fig.add_subplot(Grid[2:4,8:10]), plt.imshow(diff2, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
plt.show()
六、拉普拉斯金字塔
拉普拉斯金字塔是在高斯金字塔的基础上生成的。
为啥要发明拉普拉斯金字塔?还是因为高斯金字塔,虽然它用高斯核过滤了一遍,但或多或少还是有信息丢失,而这些丢失的信息就是拉普拉斯金字塔 。所以拉普拉斯金字塔的作用就在于能够恢复图像的细节,就是我们从高层的尺寸小的特征图中提取特征后,我们还能通过拉普拉斯金字塔数据找回高层像素点对应的底层清晰度更高的图像,就是返回来找到更多图像的细节。
Li = Gi - PyrUp( PyrDown(Gi) )
其中,Gi:原始图像 ; Li:拉普拉斯金字塔图像
#例11.4 对lena图片构造拉普拉斯金字塔
import cv2
import numpy as np
import matplotlib.pyplot as plt
lena = cv2.imread(r'C:\Users\25584\Desktop\lena.bmp', 0) #512
G0 = lena
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)
Fig=plt.figure(figsize=(16,10))
Grid=plt.GridSpec(33,33)
axes1=Fig.add_subplot(Grid[:17,:17]), plt.imshow(G0, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes2=Fig.add_subplot(Grid[:9,17:25]), plt.imshow(G1, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes3=Fig.add_subplot(Grid[:5,25:29]), plt.imshow(G2, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes4=Fig.add_subplot(Grid[:3,29:31]), plt.imshow(G3, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
Fig=plt.figure(figsize=(16,10))
Grid=plt.GridSpec(33,33)
axes1=Fig.add_subplot(Grid[:17,:17]), plt.imshow(L0, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes2=Fig.add_subplot(Grid[:9,17:25]), plt.imshow(L1, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
axes3=Fig.add_subplot(Grid[:5,25:29]), plt.imshow(L2, cmap='gray'), plt.box(), plt.xticks([]), plt.yticks([])
plt.show()
#例11.5 使用拉普拉斯金字塔和高斯金字塔恢复原始图像
import cv2
import numpy as np
import matplotlib.pyplot as plt
lena = cv2.imread(r'C:\Users\25584\Desktop\lena.bmp', 0) #512
#生成高斯金字塔
G0 = lena
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_1 = L0 + cv2.pyrUp(G1)
G1_1 = L1 + cv2.pyrUp(G2)
G2_1 = L2 + cv2.pyrUp(G3)
#确认每层是否真的复原
f0 = G0_1 - G0
f1 = G1_1 - G1
f2 = G2_1 - G2
print(np.sum(abs(f0)))
print(np.sum(abs(f1)))
print(np.sum(abs(f2)))
0 0 0