目标
- 学习图像金字塔相关内容
- 使用图像金字塔创造一种新水果,“Orapple”
- 掌握函数:cv2.pyrUp(),cv2.pyrDown()
理论
通常情况下,我们都会处理尺寸大小不变的图像。但是在某些场合中,我们需要在不同分辨率的条件下处理同一个图像。例如,在一副图像中搜寻某一个对象,比如人脸,我们并不清楚在图像中这个对象的尺寸有多大。因此,我们需要创建一系列不同分辨率的同一图像,在这些图像中搜寻对象。这一系列不同分辨率的图像被称为图像金字塔(因为在排布图像时将分辨率最高的图像放在最底端,分辨率最低的图像放在最上面,这种排布方式看起来像一个金字塔)。
有两种图像金字塔,1)高斯金字塔,2)拉普拉斯金字塔。
在高斯金字塔中,通过删除低一层(高分辨率)图像所有的偶数行和列获得高一层(低分辨率)图像。之后,对高层图像的每个像素进行高斯核卷积。通过这样处理,一个的原始图像将变成的图像,结果图像的面积缩小为原来的4分之一,上述操作被称为Octave。相反,当图像扩张,图像面积变为原来的4倍。使用函数cv2.pyrDown()核cv2.pyrUp()可以获得高斯金字塔。
img = cv.imread('messi5.jpg')
lower_reso = cv.pyrDown(higher_reso)
下面是四层金字塔处理结果
现在,我们可以向上取样,使用函数cv2.pyrUp()
higher_reso2 = cv.pyrUp(lower_reso)
需要注意的是,虽然图像分辨率相同,但是higher_reso2并不等于higher_reso,因为在取样过程中会删除像素,并进行高斯滤波,导致图像大小相同但是分辨率会降低,丢失了信息。下面的图像是从上一个案例的最小的图像进行3次向上取样获得的图像,和原始图像对比可以发现结果图像模糊了很多。
拉普拉斯金字塔来自于高斯金字塔,openCV没有提供直接的函数,拉普拉斯金字塔通过下面的公式获得
Gi是原始图像,Li是拉普拉斯金字塔图像,第i层的拉普拉斯金字塔图像是原始图像减去原始图像进行一次向下取样后又向上取样后的图像 ,也就是高斯金字塔丢失的结果。拉普拉斯金字塔图像就像是边缘图像,大多数像素值为0,主要应用于图像压缩。下面的图像展示了三层拉普拉斯金字塔图像(修改了图像对比度来增强图像内容)
使用金字塔进行图像混合
图像金字塔的一个应用就是图像混合。例如,在图像拼接应用中,你需要将两张图像叠在一起,但是由于图片之间的不连续性会导致图像看起来并不是太好。在这个案例中,使用图像金字塔进行图像混合可以获得无缝的混合结果,并且不会丢失太多数据。一个典型的例子就是混合两个水果,橙子和苹果。下面的图片将展示使用金字塔图像进行图像混合的优势
具体的处理过程如下:
- 加载苹果和橙子的图片;
- 获得两个水果的高斯金字塔图像(在这个案例中,获得6层金字塔);
- 从高斯金字塔中获得拉普拉斯金字塔;
- 在每一层的拉普拉斯金字塔中,将苹果的左边和橙子的右边相加
- 最后,从这些相加的图像金字塔中,重构原始图像。
下面是全部代码;
import cv2 as cv
import numpy as np,sys
# 加载图像,A为苹果图像,B为橙子图像
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)
参考资料