图像金字塔
目标
在这一章当中,
- 我们将了解图像金字塔。
- 我们将使用图像金字塔创建一个新的水果,“Orapple”
- 我们将看到这些功能: cv.pyrUp() , cv.pyrDown()
理论
在通常情况下我们使用大小恒定的图像。但在某些情况下,我们需要使用不同分辨率的同幅图像。例如,在搜索图像中的某些内容如脸部信息时,并不确定该内容在图像中占据的大小。在这种情况下,我们需要创建一组不同分辨率的相同图像,并在所有图像中搜索该内容。这些不同分辨率的图像被称为图像金字塔(因为当它们堆叠排列时,底部为最高分辨率图像而顶部为最低分辨率图像,看起来像金字塔)。
图像金字塔有两种: 1)高斯金字塔和 2)拉普拉斯金字塔
通过去除较低级别图像(较高分辨率)中的连续行和列来形成高斯金字塔中的较高级别图像(较低分辨率)。较高级别图像的每个像素值由低一级别图像的 5 个像素值高斯加权得到。由此,图像变为图像,面积减少到原来的四分之一。这些图像被称为 Octave(组)。当我们在金字塔中上升时(即分辨率降低),重复相似的操作。同理,在金字塔中下降时,每个级别的图像面积大小为上一级的四倍。我们可以使用 cv.pyrDown() 和 cv.pyrUp() 函数获取高斯金字塔。
img = cv.imread('messi5.jpg')lower_reso = cv.pyrDown(higher_reso)
以下是图像金字塔中的 4 个级别。
现在你可以用 cv.pyrUp() 函数处理图像金字塔。
higher_reso2 = cv.pyrUp(lower_reso)
请记住,higher_reso2
不等于higher_reso
,因为一旦降低了分辨率,就会丢失信息。下图为将上述金字塔中最高级别图像下降三个级别后的结果(即重构三次)。将其与原始图像进行比较,可以发现分辨率相同,但丢失了许多信息:
拉普拉斯金字塔由高斯金字塔转化而来,没有专属功能。拉普拉斯金字塔图像与边缘图像相似,它的大部分元素都是零,可以用于图像压缩。拉普拉斯金字塔中的某一层次即高斯金字塔中的该层次与高斯金字塔中的上层的扩展版本之间的差异。拉普拉斯级别的三个级别如下所示(效果为调整对比度以凸显内容):
使用金字塔的图像混合
金字塔的一个应用是图像混合。例如,在图像拼接中,您需要将两个图像堆叠在一起,但由于图像之间的不连续性,它可能看起来不太好。在这种情况下,使用金字塔进行图像混合可以实现无缝混合,而不会在图像中留下多余数据。典型的例子是混合橙子和苹果图像。现在查看结果以了解我在说什么:
请在其他资源中查看第一个参考资料,它有关于图像混合,拉普拉斯金字塔等的完整图表细节。简单的表述如下:
- 加载苹果和橙色的两个图像
- 找到苹果和橙色的高斯金字塔(在这个例子中,级别数是 6)
- 从高斯金字塔,找到他们的拉普拉斯金字塔
- 现在加入左半部分的苹果和右半部分的拉普拉斯金字塔
- 最后,从这个联合图像金字塔,重建原始图像。
以下是完整的代码。 (为简单起见,每个步骤都单独完成,由此可能需要更多内存。读者也可以对其进行优化)。
import cv2 as cv
import numpy as np,sys
A = cv.imread('apple.jpg')
B = cv.imread('orange.jpg')
# generate Gaussian pyramid for A
G = A.copy()
gpA = [G]
for i in xrange(6):
G = cv.pyrDown(G)
gpA.append(G)
# generate Gaussian pyramid for B
G = B.copy()
gpB = [G]
for i in xrange(6):
G = cv.pyrDown(G)
gpB.append(G)
# generate Laplacian Pyramid for A
lpA = [gpA[5]]
for i in xrange(5,0,-1):
GE = cv.pyrUp(gpA[i])
L = cv.subtract(gpA[i-1],GE)
lpA.append(L)
# generate Laplacian Pyramid for B
lpB = [gpB[5]]
for i in xrange(5,0,-1):
GE = cv.pyrUp(gpB[i])
L = cv.subtract(gpB[i-1],GE)
lpB.append(L)
# Now add left and right halves of images in each level
LS = []
for la,lb in zip(lpA,lpB):
rows,cols,dpt = la.shape
ls = np.hstack((la[:,0:cols/2], lb[:,cols/2:]))
LS.append(ls)
# now reconstruct
ls_ = LS[0]
for i in xrange(1,6):
ls_ = cv.pyrUp(ls_)
ls_ = cv.add(ls_, LS[i])
# image with direct connecting each half
real = np.hstack((A[:,:cols/2],B[:,cols/2:]))
cv.imwrite('Pyramid_blending2.jpg',ls_)
cv.imwrite('Direct_blending.jpg',real)