⚠️由于自己的拖延症,3.4.3翻到一半,OpenCV发布了4.0.0了正式版,所以接下来是按照4.0.0翻译的。
⚠️除了版本之外,其他还是照旧,Image Pyramids,附原文。
在这个章节,
通常情况下,我们处理的是大小不变的图像。但在某些情况下,我们需要处理同一张图像只是它的分辨率不同。例如,在检索图像中的某些对象时,比如脸,我们不确定该对象在我们提到的这张图像中的大小。在这种情况下,我们需要创建一组具有不同分辨率的相同图像,并在所有图像中搜索对象。这组具有不同分辨率的图像集合,我们称之为图像金字塔(因为当它们被保存在一个栈中时,分辨率最高的图像位于底部,分辨率最低的图像位于顶部(译者注:因为栈顶的数据先出,我们总是用较小分辨率的图像先拿出来对比),看起来就像金字塔一样)。
有两种图像金字塔。1) 高斯金字塔 和 2) 拉普拉斯金字塔
高斯金字塔高层(低分辨率)是通过除去低层中连续的行和列来构建起来的。每个处于高层的像素点是由这层下面的一层通过5像素内核用高斯权重算出来的。这么做了之后,一个 M×N 的图像就会变成 M/2×N/2 的图像。因此面积也降到了原图的 1/4。这就被称为一阶。同样的(变化)模式在不断的往金字塔顶端前进的同时重复着(例如,分辨率降低)。同样,图像扩展时,面积会变成每一级增加至 4 倍。我们可以获取到高斯金字塔(的某一阶),通过函数 cv.pyrDown() 和 cv.pyrUp()。
img = cv.imread('messi5.jpg')
lower_reso = cv.pyrDown(higher_reso)
以下是一个图像金字塔往上爬的4阶:
现在你可以往下爬金字塔,通过 cv.pyrUp() 函数。
(译者注:OpenCV这个俩方法的命名Up和Down明显不是针对这个金字塔的上下,而是针对图像大小的上下。)
higher_reso2 = cv.pyrUp(lower_reso)
要记住的是,higher_reso2 和 higher_reso, 并不相等。因为一旦你(往上爬一层)降低了分辨率之后,你就丢弃了部分图像信息。以下图像是用之前的示例中最小的图像再往下爬三阶之后的结果,用它和原图比较:
拉普拉斯金字塔其实就是基于高斯金字塔构建起来的。它并没有一个专门对应的函数。拉普拉斯金字塔就好像只有边缘的图像。它其中大部分的元素都是 0(译者注:意思就是每一阶看起来都是一片黑)。它被用于图像压缩,拉普拉斯金字塔中的某一阶,等于这一阶的高斯金字塔与这一阶高斯金字塔的上一阶的扩展版本之差(译者注:意思就是拉普拉斯=高斯-高斯.down.up)。三阶拉普拉斯金字塔看起来就如下图所示(调整了对比度来增强图像内容):
图像金字塔的其中一个应用就是用来混合图像。例如,在缝合图像的过程中,需要将两幅图像堆叠在一起,但由于图像之间的不连续,可能一看就觉得不妥。在这种情况下,图像与金字塔能让图像无缝的混合,而不会在图像中留下太多数据。一个经典的例子是把两种水果,橘子和苹果混合在一起。看一下结果,理解我在说什么:
请先查看附加资源中的参考资料,它提供了关于图像混合、拉普拉斯金字塔等的完整的图表细节。
简单的说它是这么做的:
以下是完整代码。(为了易懂,每一个步骤被分开做了,这可能需要花更多的内存,如果想要的话,你可以自己优化一下。)
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)
上篇:【翻译:OpenCV-Python教程】坎尼边缘检测
下篇:【翻译:OpenCV-Python教程】图像轮廓