本章将学习如下内容:
- 学习图像金字塔
- 学习使用图像金字塔来创造一种新的水果“Orapple”
- 介绍如下函数:
cv2.pyrUp()
、cv2.pyrDown()
理论基础
通常,我们使用恒定大小的图像。但在某些情况下,需要处理同一图像的不同分辨率的图像。 例如,在搜索图像中的某些内容(如面部)时,不确定该对象在图像中的大小。 在这种情况下,需要创建一组具有不同分辨率的图像,并在所有图像中搜索对象。 这些具有不同分辨率的图像集被称为图像金字塔(因为当它们被放在一个堆栈中,最大的图像在底部,最小的图像在顶部时看起来像金字塔)。
图像金字塔有如下两种:
- 高斯金字塔(Gaussian Pyramid)
- 拉普拉斯金字塔(Laplacian Pyramids)
高斯金字塔中的高级(低分辨率)是通过删除低级(高分辨率)图像中的连续行和列而形成的。
更高级别的每个像素由具有高斯权重的底层5个像素的贡献形成。
继而一个$M\times N$图像变成$M/2\times N/2$图像。
因此,面积减少到原始面积的四分之一,它被称为Octave。
随着在金字塔中向上移动,同样的模式也在继续(即分辨率降低)。
同样,在扩展时,每个级别的面积都会增加4倍。
我们可以使用cv2.pyrDown()
和cv2.pirUp()
函数找到高斯金字塔。
import cv2
img = cv2.imread('/data/cvdata/messi5.jpg')
higher_reso = 4
lower_reso = cv2.pyrDown(higher_reso)
%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(lower_reso)
<matplotlib.image.AxesImage at 0x7f8c49784560>
下面是图像金字塔中的4个级别。
可以使用cv2.pyrUp()
函数访问图像金字塔。
higher_reso2 = cv2.pyrUp(lower_reso)
请记住,$higher_reso 2 $不等于$higher_reso$, 因为一旦降低分辨率,就会丢失信息。 下图是由前一种情况下最小图像创建金字塔的3层。 将其与原始图像进行比较:
拉普拉斯金字塔是由高斯金字塔形成的,没有专属功能。 拉普拉斯金字塔图像仅类似于边缘图像,大部分元素都是零,用于图像压缩。 拉普拉斯金字塔中的一个级别是由高斯金字塔中的该级别与其高斯金字塔中上层扩展版本之间的差异形成的。 拉普拉斯水平的三个级别如下(调整对比度以增强内容):
使用金字塔进行图像融合
金字塔的一个应用是图像融合。 例如,在图像拼接中,需要将两个图像堆叠在一起,但由于图像之间的不连续性,这可能看起来不太好。 在这种情况下,图像与金字塔的混合可以实现无缝混合,而不会在图像中留下太多数据。 一个经典的例子是混合两种水果,橙子和苹果。现在看看结果本身:
请查看附加资源中的第一个参考,它有完整的图像融合、拉普拉斯金字塔等的图解细节。 如下所示:
- 加载苹果和橙子的两张图片
- 找到苹果色和橙色的高斯金字塔(在这个特定的例子中,级别数为6)
- 从高斯金字塔中,找到拉普拉斯金字塔
- 在拉普拉斯金字塔的每一层中,将苹果的左半部分和橙色的右半部分连接起来
- 最后从该联合图像金字塔中,重建原始图像
下面是完整的代码。(为了简单起见,每个步骤都是单独完成的,这可能会占用更多的内存。如果愿意,可以对其进行优化)。
import cv2 as cv
import numpy as np,sys
A = cv2.imread('/data/cvdata/apple.jpg')
B = cv2.imread('/data/cvdata/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:int(cols/2)], lb[:,int(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[:,:int(cols/2)],B[:,int(cols/2):]))
cv.imwrite('xx_Pyramid_blending2.jpg',ls_)
cv.imwrite('xx_Direct_blending.jpg',real)
True