0%

opencv_11_图像金字塔

图像金字塔

图像金字塔是同一图像不同分辨率的子图集合,是通过对原图像不断地下采样而产生的,即由高分辨率的图像(大尺寸)产生低分辨率的近似图像(小尺寸)。

导入基本软件包和库

1
2
3
import cv2
import matplotlib.pyplot as plt
import numpy as np

读取图像

1
2
A = cv2.imread('apple.jpg')
B = cv2.imread('orange.jpg')
1
A.shape
(360, 360, 3)
1
B.shape
(360, 360, 3)

查看图像

1
2
3
4
5
plt.subplot(1,2,1)
plt.imshow(A[:, :, ::-1])
plt.subplot(1,2,2)
plt.imshow(B[:, :, ::-1])
plt.show()

11output_9_0

图像拼接

1
cols, rows, channle = A.shape
1
res = np.hstack((A[:, :cols//2], B[:, cols//2:]))
1
2
plt.imshow(res[:, :, ::-1])
plt.show()


11output_13_0

下采样

1
2
img = cv2.imread('dog.jpg')
img = cv2.resize(img, (460, 460))
1
2
img1 = cv2.pyrDown(img)
img2 = cv2.pyrDown(img1) # 由于下采样图像的长宽每次都是变为原来的一半。随意在采样时应该注意该问题。
1
2
3
4
5
6
7
8
plt.figure(figsize=(30, 10))
plt.subplot(1,3,1)
plt.imshow(img[:, :, ::-1])
plt.subplot(1,3,2)
plt.imshow(img1[:, :, ::-1])
plt.subplot(1,3,3)
plt.imshow(img2[:, :, ::-1])
plt.show()

11output_17_0

1
2
3
print(img.shape)
print(img1.shape)
print(img2.shape)
(460, 460, 3)
(230, 230, 3)
(115, 115, 3)

上采样

1
2
image1 = cv2.pyrUp(img2)
image2 = cv2.pyrUp(image1)
1
2
3
4
5
6
7
8
plt.figure(figsize=(30, 10))
plt.subplot(1,3,1)
plt.imshow(img2[:, :, ::-1])
plt.subplot(1,3,2)
plt.imshow(image1[:, :, ::-1])
plt.subplot(1,3,3)
plt.imshow(image2[:, :, ::-1])
plt.show()

11output_21_0

1
2
3
print(img2.shape)
print(image1.shape)
print(image2.shape)
(115, 115, 3)
(230, 230, 3)
(460, 460, 3)

采样可逆性研究

将下采样后的图像上采样回原来的像素大小,图像的清晰度没有还原,说明下采样和上采样不是互逆的,即使达到了同样的像素大小,但是像素值无法还原。

1
2
3
down = cv2.pyrDown(img)
up = cv2.pyrUp(down)
diff = img - up # 构造diff图像,查看up和img的区别
1
2
print(img.shape)
print(diff.shape)
(460, 460, 3)
(460, 460, 3)
1
2
3
4
5
6
7
8
plt.figure(figsize=(30, 10))
plt.subplot(1,3,1)
plt.imshow(img[:, :, ::-1])
plt.subplot(1,3,2)
plt.imshow(up[:, :, ::-1])
plt.subplot(1,3,3)
plt.imshow(diff[:, :, ::-1])
plt.show()

11output_27_0

1
2
3
up = cv2.pyrUp(img)
down = cv2.pyrDown(up)
diff = img - down # 构造diff图像,查看up和img的区别
1
2
print(img.shape)
print(diff.shape)
(460, 460, 3)
(460, 460, 3)
1
2
3
4
5
6
7
8
plt.figure(figsize=(30, 10))
plt.subplot(1,3,1)
plt.imshow(img[:, :, ::-1])
plt.subplot(1,3,2)
plt.imshow(down[:, :, ::-1])
plt.subplot(1,3,3)
plt.imshow(diff[:, :, ::-1])
plt.show()


11output_30_0

拉普拉斯金字塔

为了恢复原始图像就需要获取在采样中丢失的信息,这些丢失的信息被称为拉普拉斯金字塔

  • 例如下采样2次构成的拉普拉斯金字塔和高斯金字塔如下
1
2
3
4
5
6
down1 = cv2.pyrDown(img)
down2 = cv2.pyrDown(down1)
up1 = cv2.pyrUp(down1)
up2 = cv2.pyrUp(down2)
diff1 = img - up1
diff2 = down1 - up2

高斯金字塔

1
2
3
4
5
6
7
8
plt.figure(figsize=(20, 10))
plt.subplot(1,3,1)
plt.imshow(img[:, :, ::-1])
plt.subplot(1,3,2)
plt.imshow(down1[:, :, ::-1])
plt.subplot(1,3,3)
plt.imshow(down2[:, :, ::-1])
plt.show()


11output_36_0

拉普拉斯金字塔

1
2
3
4
5
6
plt.figure(figsize=(10, 5))
plt.subplot(1,3,1)
plt.imshow(diff1[:, :, ::-1])
plt.subplot(1,3,2)
plt.imshow(diff2[:, :, ::-1])
plt.show()

11output_38_0

使用拉普拉斯金字塔恢复分辨率

1
lp = cv2.pyrUp(down1) + diff1
1
2
plt.imshow(lp[:, :, ::-1])
plt.show()


11output_41_0

1
lp = cv2.pyrUp(down2) + diff2
1
2
plt.imshow(lp[:, :, ::-1])
plt.show()


11output_43_0

使用拉普拉斯平滑进行图像融合

图像金字塔的一个应用是图像融合。例如,在图像缝合中,你需要将两幅图叠在一起,但是由于连接区域图像像素的不连续性,整幅图的效果看起来会很差。这时图像金字塔就可以排上用场了,他可以帮你实现无缝连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import cv2 as cv
import numpy as np
#需要把原图像rsize成2**n分辨率的图像
A = cv2.imread('apple.jpg')
A = cv2.resize(A,(256,256))
B = cv2.imread('orange.jpg')
B = cv2.resize(B,(256,256))
#生成A的高斯金字塔
G = A.copy()
gpA = [G]
for i in range(6):
G = cv2.pyrDown(G)
gpA.append(G)
#生成B的高斯金字塔
G = B.copy()
gpB = [G]
for i in range(6):
G = cv2.pyrDown(G)
gpB.append(G)
#生成A的拉普拉斯金字塔
lpA = [gpA[5]]
for i in range(5, 0, -1):
GE = cv2.pyrUp(gpA[i])
L = cv2.subtract(gpA[i-1], GE) #两个图像相减
lpA.append(L)
#生成B的拉普拉斯金字塔
lpB = [gpB[5]]
for i in range(5, 0, -1):
GE = cv2.pyrUp(gpB[i])
L = cv2.subtract(gpB[i-1], GE)
lpB.append(L)
#现在在每个级别中添加左右两半图像
LS = []
for la, lb in zip(lpA, lpB):
rows, cols, dpt = la.shape
#图像拼接
ls = np.hstack((la[:, 0:int(cols/2)], lb[:, int(cols/2):]))
LS.append(ls)
#现在重建
ls_ = LS[0]
for i in range(1, 6):
ls_ = cv2.pyrUp(ls_)
ls_ = cv2.add(ls_, LS[i])
1
2
plt.imshow(ls_[:, :, ::-1])
plt.show()


11output_47_0

-------------本文结束感谢您的阅读-------------