opencv15:图像金字塔

目标

在本章中,将学习图像金字塔( Image Pyramids)

  • 使用图像金字塔创建一个新的水果Orapple
  • 函数:cv2.pyrUp()cv2.pyrDown()

理论

通常,过去使用的是恒定大小的图像。但是在某些情况下,需要使用不同分辨率的(相同)图像。例如,当在图像中搜索某些东西(例如人脸)时,不确定对象将以多大的尺寸显示在图像中。在这种情况下,将需要创建一组具有不同分辨率的相同图像,并在所有图像中搜索对象。这些具有不同分辨率的图像集称为“图像金字塔”(因为当它们堆叠在底部时,最高分辨率的图像位于顶部,最低分辨率的图像位于顶部时,看起来像金字塔)

有两种图像金字塔。

  • 高斯金字塔(Gaussian Pyramid)
  • 拉普拉斯金字塔( Laplacian Pyramids)

高斯金字塔中的较高级别(低分辨率)是通过删除较低级别(较高分辨率)图像中的连续行和列而形成的。然后,较高级别的每个像素由基础级别的5个像素的贡献与高斯权重形成。通过这样做,M × N图像变成M / 2 × N / 2图像。因此面积减少到原始面积的四分之一。它称为Octave。当在金字塔中越靠上时(即分辨率下降),这种模式就会继续。同样,在扩展时,每个级别的面积变为4倍。可以使用cv2.pyrDown()cv2.pyrUp()函数找到高斯金字塔。

高分辨率能看到图像的一些细节信息,通过低分辨率能看到图像的一些轮廓的信息

  • cv2.pyrDown(): 先要用高斯核对图像进行卷积,然后删除所有偶数行和偶数列,新的到的图像面积就会变成源图像的四分之一
  • cv2.pyrUp(): 图像首先在每个维度上扩大为原来的两倍,新增的行和列(偶数行和列)以 0 填充。然后用指定的滤波器进行卷积(实际上是一个在每个维度上都扩大为原来两倍的过滤器)去估计”丢失“像素的近似值
import cv2
import numpy as np

img = cv2.imread('messi.png')
lower_reso = cv2.pyrDown(img)
high_reso = cv2.pyrUp(lower_reso)
print(img.shape)         # (259, 419, 3)
print(lower_reso.shape)  # (130, 210, 3)
print(high_reso.shape)   # (260, 420, 3)

以下是图像金字塔中的4个级别。
在这里插入图片描述
现在,可以使用cv2.pyrUp()函数向上扩展图像金字塔

higher_reso2 = cv.pyrUp(lower_reso) 

记住,higher_reso2不等于higher_reso,因为一旦降低了分辨率,就会丢失信息。下面的图像是3层的金字塔从最小的图像在前面的情况下创建。与原图对比:

在这里插入图片描述

拉普拉斯金字塔由高斯金字塔形成。没有专门的函数实现。拉普拉斯金字塔图像仅像边缘图像。它的大多数元素为零, 被用于图像压缩。拉普拉斯金字塔的层由高斯金字塔的层与高斯金字塔的高层的扩展版本之间的差形成, 用来存储下采样后的图像于原始图像的差异。
假如原始图像为 G0,金字塔中任意一层图像为 Gi,下采样后得到 Gi+1 = Down(Gi), 由于图像下采样之后尺寸发生了变化,若将下采样后的图进行上采用得到 Up(Down(Gi)), 但是下采样后的变化是不可逆的即不可能恢复成原始图像。因此,有部分信息丢失不能完全恢复成原始图像。拉普拉斯金字塔就是记录金字塔每一层下采样后再上采用回来与该层之间的差异的。

拉普拉斯等级的三个等级如下所示(调整对比度以增强内容):

在这里插入图片描述

def laplacian(gaussian_pyramid, up_times=5):
    laplacian_pyramid = [gaussian_pyramid[-1]]
 
    for i in range(up_times, 0, -1):
        # i的取值为5,4,3,2,1,0也就是拉普拉斯金字塔有6层
        temp_pyrUp = cv2.pyrUp(gaussian_pyramid[i])
        temp_lap = cv2.subtract(gaussian_pyramid[i-1], temp_pyrUp)
        laplacian_pyramid.append(temp_lap)
    return laplacian_pyramid

使用金字塔进行图像融合

金字塔的一种应用是图像融合(image blending)。例如,在图像拼接中,需要将两个图像堆叠在一起,但是由于图像之间的不连续性,可能看起来不太好。在这种情况下,使用金字塔混合图像可以无缝混合,而不会在图像中保留大量数据。一个经典的例子是将两种水果——橙和苹果混合在一起。
在这里插入图片描述

融合上述图片只需完成以下步骤即可:

  • 加载苹果和橙子的两个图像
  • 查找苹果和橙子的高斯金字塔(在此示例中, 级别数为6)
  • 在高斯金字塔中,找到其拉普拉斯金字塔
  • 然后在每个拉普拉斯金字塔级别中加入苹果的左半部分和橙子的右半部分
  • 最后从此联合图像金字塔中重建原始图像。

下面是完整的代码。(为简单起见,每个步骤都是单独进行的,这可能会占用更多的内存。如果需要,可以对其进行优化)。

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 range(6):
    G = cv.pyrDown(G)
    gpA.append(G)

# generate Gaussian pyramid for B
G = B.copy()
gpB = [G]
for i in range(6):
    G = cv.pyrDown(G)
    gpB.append(G)
# generate Laplacian Pyramid for A
lpA = [gpA[5]]
for i in range(5, 0,-1):
    GE = cv.pyrUp(gpA[i])
    w, h, _ = gpA[i-1].shape
    GE = cv.resize(GE, (w, h))  # size keep same
    L = cv.subtract(gpA[i-1],GE)
    lpA.append(L)

# generate Laplacian Pyramid for B
lpB = [gpB[5]]
for i in range(5,0,-1):
    GE = cv.pyrUp(gpB[i])
    w, h, _ = gpB[i-1].shape
    GE = cv.resize(GE, (w, h))  # size keep same
    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:int(cols/2)], lb[:,int(cols/2):]))
    LS.append(ls)
# now reconstruct
ls_ = LS[0]
for i in range(1,6):
    ls_ = cv.pyrUp(ls_)
    w, h, _ = LS[i].shape
    ls_ = cv.resize(ls_, (w, h))  # size keep same
    ls_ = cv.add(ls_, LS[i])
# image with direct connecting each half

real = np.hstack((A[:,:int(cols/2)],B[:,int(cols/2):]))
cv.imwrite('Pyramid_blending2.jpg',ls_)
cv.imwrite('Direct_blending.jpg',real)


# bgr与rgb转化

real_rgb = cv.cvtColor(real, cv2.COLOR_BGR2RGB) 
ls_rgb = cv.cvtColor(ls_, cv2.COLOR_BGR2RGB) 

plt.subplot(1, 2, 1)
plt.imshow(real_rgb)
plt.title('Direct blending')
plt.xticks([])
plt.yticks([])


plt.subplot(1,2,2)
plt.imshow(ls_rgb)
plt.title('Pyramid blending')
plt.xticks([])
plt.yticks([])

plt.show()

在这里插入图片描述

附加资源

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uncle_ll

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值