官方文档 – https://docs.opencv.org/3.4.0/dc/dff/tutorial_py_pyramids.html
通常,我们使用的是一个恒定大小的图像。但在某些情况下,我们需要处理不同分辨率的图像。例如,当在图像中搜索某样东西时,比如人脸,我们不确定物体在图像中会呈现多大的尺寸。在这种情况下,我们需要创建一组具有不同分辨率的图像,并在所有图像中搜索对象。这些具有不同分辨率的图像被称为图像金字塔(因为当它们被保存在一个有最大图像的堆栈中,最小的图像在顶部看起来像金字塔)。
有两种类型的图像金字塔。1、Gaussian 金字塔;2、Laplacian 金字塔。
Gaussian 金字塔的高水平(低分辨率)是通过在低水平(高分辨率)图像中移除连续的行和列来形成的。然后,高水平的每一个像素都是由5个像素的基础水平和高斯的权重组成的。这样,M x N的图像就变成了 M/2 x N/2 的图像了。所以面积减少到原来面积的四分之一。它被称为八度。越往金字塔的上方(即分辨率下降),同样的模式仍在继续。同样地,在扩张时,每一层的面积都是扩张4倍。我们可以使用cv.pyrDown()
和cv.pyrUp()
函数来找到高斯金字塔。
cv.pyrDown(src[, dst[, dstsize[, borderType]]])
默认情况下,输出图像的大小被计算为Size((src.cols+1)/2, (src.rows+1)/2)
,但是,在任意情况下,以下不等式都成立:|dstsize.width∗2−src.cols|≤2
、|dstsize.height∗2−src.rows|≤2
img = cv.imread('messi5.jpg')
lower_reso = cv.pyrDown(higher_reso)
cv.pyrUp(src[, dst[, dstsize[, borderType]]])
默认情况下,输出图像的大小被计算为Size(src.cols\*2, (src.rows\*2)
,但是,在任意情况下,以下不等式都成立:|dstsize.width−src.cols∗2|≤(dstsize.widthmod2)
、|dstsize.height−src.rows∗2|≤(dstsize.heightmod2)
higher_reso2 = cv.pyrUp(lower_reso)
但是,higher_reso2并不等于higher_reso,因为一旦你降低了分辨率,你就丢失了信息。
下图是在前一种情况下由最小的图像创建的金字塔的第3级,将他与原始图像进行比较。
Laplacian 金字塔是由Gaussian 金字塔形成的。它没有专用函数。Laplacian 金字塔图像仅仅是边缘图像。它的大部分元素都是0。它们用于图像压缩。Laplacian 金字塔的一个层次是由Gaussian 金字塔的水平和Gaussian 金字塔的上层的扩展版本之间的差异所形成的。Laplacian级别的三个级别将如下所示(对比度被调整以增强内容):
金字塔的一个应用就是图像的融合。例如,在图像拼接中,您需要将两个图像叠加在一起,但是由于图像之间的不连续性,可能看起来不太好。在这种情况下,图像与金字塔的混合会让你无缝融合,而不会留下大量的图像。一个经典的例子是两种水果,橘子和苹果的混合。
import cv2 as cv
import numpy as np
A = cv.imread('apple,jpg')
B = cv.imread('orange.jpg')
# 生成A的高斯金字塔
G = A.copy()
gpA = [G]
for i in xrange(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的Laplacian金字塔
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)
# 生成B的Laplacian金字塔
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)
# 在每个层次上添加图像的左和右半部分
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 xrange(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)