目标
在这一章中。
- 我们将学习图像金字塔的知识
- 我们将使用图像金字塔来创建一个新的水果,“Orapple”。
- 我们将看到这些函数:cv.pyrUp(), cv.pyrDown()
理论
通常情况下,我们习惯于使用一个恒定大小的图像。但在某些情况下,我们需要处理不同分辨率的(相同)图像。例如,当我们在图像中搜索某个东西时,比如人脸,我们不确定该物体会以何种尺寸出现在所述图像中。在这种情况下,我们需要创建一组具有不同分辨率的相同图像,并在所有这些图像中搜索物体。这些具有不同分辨率的图像集被称为图像金字塔(因为当它们被保存在一个堆栈中,最高分辨率的图像在底部,最低分辨率的图像在顶部,它看起来像一个金字塔)。
有两种图像金字塔。1)高斯金字塔和2)拉普拉斯金字塔
高斯金字塔中的高层次(低分辨率)是通过去除低层次(高分辨率)图像中的连续行和列而形成的。然后,高一级的每个像素由底层的5个像素的高斯权重贡献形成。通过这样做,M×N的图像变成了M/2×N/2的图像。因此,面积减少到原始面积的四分之一。这就是所谓的八度空间。当我们在金字塔中往上走时,同样的模式会继续下去(即,分辨率降低)。同样地,在扩展时,每一级的面积都会变成4倍。我们可以使用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,因为一旦你降低了分辨率,你就失去了信息。下面的图片是由前面最小的图片创建的3级金字塔。将其与原始图像进行比较:
拉普拉斯金字塔是由高斯金字塔形成的。这方面没有专属函数。拉普拉斯金字塔图像只像边缘图像。它的大部分元素是零。它们被用于图像压缩。拉普拉斯金字塔中的一个层次是由高斯金字塔中该层次与高斯金字塔中其上层的扩展版本之间的差异形成的。一个拉普拉斯金字塔的三个层次看起来如下(对比度被调整以增强内容):
使用金字塔进行图像混合
金字塔的一个应用是图像混合。例如,在图像拼接中,你需要将两幅图像堆叠在一起,但由于图像之间的不连续性,可能看起来不好看。在这种情况下,用Pyramids进行图像混合,可以让你实现无缝混合,而不会在图像中留下很多数据。一个经典的例子是两个水果的混合,橙子和苹果的混合。请看现在的结果本身来理解我所说的:
请查看额外资源中的第一个参考资料,它有关于图像混合、拉普拉斯金字塔等的完整图示细节。简单地说,它是按以下方式进行的:
- 1.加载苹果和橙子的两个图像
- 2.找到苹果和橙子的高斯金字塔(在这个特定的例子中,级别数为6)。
- 3.从高斯金字塔中,找到它们的拉普拉斯金字塔
- 4.现在将苹果的左半边和橙子的右半边分别加入到拉普拉斯金字塔的各个层次中。
- 5.最后从这个联合图像金字塔中,重建原始图像。
下面是完整的代码。(为了简单起见,每个步骤都是单独完成的,这可能会占用更多的内存。如果你想的话,你可以优化它):
import cv2 as cv
import numpy as np,sys
A = cv.imread('apple.jpg')
B = cv.imread('orange.jpg')
# 为A生成高斯金字塔
G = A.copy()
gpA = [G]
for i in range(6):
G = cv.pyrDown(G)
gpA.append(G)
# 为B生成高斯金字塔
G = B.copy()
gpB = [G]
for i in range(6):
G = cv.pyrDown(G)
gpB.append(G)
# 为A生成拉普拉斯金字塔
lpA = [gpA[5]]
for i in range(5,0,-1):
GE = cv.pyrUp(gpA[i])
L = cv.subtract(gpA[i-1],GE)
lpA.append(L)
# 为B生成拉普拉斯金字塔
lpB = [gpB[5]]
for i in range(5,0,-1):
GE = cv.pyrUp(gpB[i])
L = cv.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:cols//2], lb[:,cols//2:]))
LS.append(ls)
# 现在重新构筑
ls_ = LS[0]
for i in range(1,6):
ls_ = cv.pyrUp(ls_)
ls_ = cv.add(ls_, LS[i])
# 图像每一半直接连接
real = np.hstack((A[:,:cols//2],B[:,cols//2:]))
cv.imwrite('Pyramid_blending2.jpg',ls_)
cv.imwrite('Direct_blending.jpg',real)