OpenCV-Python——第16章:图像金字塔

目录

原理     高斯金字塔     拉普拉斯金字塔     使用金字塔进行图像融合


0 原理

一般情况下,我们要处理是一副具有固定分辨率的图像。但是有些情况下,我们需要对同一图像的不同分辨率的子图像进行处理。比如,我们要在一幅图像中查找某个目标,比如脸,我们不知道目标在图像中的尺寸大小。这种情况下,我们需要创建创建一组图像,这些图像是具有不同分辨率的原始图像。我 们把这组图像叫做图像金字塔(简单来说就是同一图像的不同分辨率的子图集 合)。如果我们把最大的图像放在底部,最小的放在顶部,看起来像一座金字塔,故而得名图像金字塔。

图像金字塔是图像尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单地结构。图像金字塔最初用于 机器视觉 和 图像压缩 ,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源同一张原始图的图像集合。其次通过梯次向下采样获得,直到达到某个终止条件才停止采样。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。

有两类图像金字塔:高斯金字塔和拉普拉斯金字塔。

高斯金字塔的顶部是通过将底部图像中的连续的行和列去除得到的。顶部图像中的每个像素值等于下一层图像中 5 个像素的高斯加权平均值。这样 操作一次一个 MxN 的图像就变成了一个 M/2xN/2 的图像。所以这幅图像 的面积就变为原来图像面积的四分之一。这被称为 Octave。连续进行这样 的操作我们就会得到一个分辨率不断下降的图像金字塔。我们可以使用函数 cv2.pyrDown() 和 cv2.pyrUp() 构建图像金字塔。 但需要注意的是,PryUp和PryDown不是互逆的,即PryUp不是降采样的逆操作。

函数 cv2.pyrDown() 从一个高分辨率大尺寸的图像向上构建一个金子塔 (尺寸变小,分辨率降低)。

1 高斯金字塔

高斯金字塔是通过高斯平滑和亚采样获得一系列采样图像,也就是说第K层高斯金字塔通过平滑,亚采样就可以获得K+1层高斯图像,高斯金字塔包含了一系列低通滤波器,其截止频率从上一层到下一层是以因子2逐渐增加,所以高斯金字塔就可以跨越很大的频率范围。

另外,每一层都按从下到上的次序编号, 层级 G_i+1 (表示为 G_i+1尺寸小于第i层G_i)。

1.1 对图像向下取样

为了获取层级为 G_i+1 的金字塔图像,我们采用如下方法:

   (1)对图像G_i进行高斯内核卷积

   (2)将所有偶数行和列去除

得到的图像即为G_i+1的图像,显而易见,结果图像只有原图的四分之一。通过对输入图像G_i(原始图像)不停迭代以上步骤就会得到整个金字塔。同时我们也可以看到,向下取样会逐渐丢失图像的信息。以上就是对图像的向下取样操作,即缩小图像。

cv2.pyrDown(src, dst, dstsize, borderType)

1.2 对图像向上取样

如果想放大图像,则需要通过向上取样操作得到,具体做法如下:

 (1)将图像在每个方向扩大为原来的俩倍,新增的行和列以0填充

 (2)使用先前同样的内核(乘以4)与放大后的图像卷积,获得新增像素的近似值

得到的图像即为放大后的图像,但是与原来的图像相比会发觉比较模糊,因为在缩放的过程中已经丢失了一些信息,如果想在缩小和放大整个过程中减少信息的丢失,这些数据形成了拉普拉斯金字塔。

cv2.pyrUp(src, dst, dstsize, borderType)

  • 参数同上

1.3 举例

程序:

import cv2
import numpy as np

img = cv2.imread('test6.jpg')
lower = cv2.pyrDown(img)
lower1 = cv2.pyrDown(lower)
higher = cv2.pyrUp(lower1)
higher1 = cv2.pyrUp(higher)

while(1):
    cv2.imshow('src', img)
    cv2.imshow('lower', lower)
    cv2.imshow('lower1', lower1)
    cv2.imshow('higher', higher)
    cv2.imshow('higher1', higher1)
    if cv2.waitKey(1) & 0xFF == 27:
        break
cv2.destroyAllWindows()

 结果如下:

从左到右分别是原图,向下,再向下,向上,再向上,可以看出图像失去了某些细节变得模糊。

2 拉普拉斯金字塔

拉普拉斯金字塔可以有高斯金字塔计算得来,公式如下:

 也就是说,拉普拉斯金字塔是通过源图像减去先缩小后再放大的图像的一系列图像构成的。整个拉普拉斯金字塔运算过程可以通过下图来概括:

例如:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 图像尺寸最好是2的整次幂,如256,512等
# 否则在金字塔向上的过程中图像的尺寸会不等
# 这会导致在拉普拉斯金字塔处理时由于不同尺寸矩阵相减而出错
img = cv2.imread('test6.jpg')
lower = cv2.pyrDown(img)
lower1 = cv2.pyrDown(lower)
higher = cv2.pyrUp(lower1)
higher1 = cv2.pyrUp(higher)
laplace = cv2.subtract(img, higher1)

plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('Src')
plt.subplot(122), plt.imshow(cv2.cvtColor(laplace, cv2.COLOR_BGR2RGB)), plt.title('Laplace')
plt.show()

注:图像尺寸最好是2的整次幂,如256,512等,否则在金字塔向上的过程中图像的尺寸会不等,这会导致在拉普拉斯金字塔处理时由于不同尺寸矩阵相减而出错

结果如下:

3 使用金字塔进行图像融合

图像金字塔的一个应用是图像融合。例如,在图像缝合中,你需要将两幅图叠在一起,但是由于连接区域图像像素的不连续性,整幅图的效果看起来会很差。这时图像金字塔就可以排上用场了,他可以帮你实现无缝连接。这里的 一个经典案例就是将两个水果融合成一个。

实现上述效果的步骤如下:

  1. 读入两幅图像,苹果和句子
  2. 构建苹果和橘子的高斯金字塔(6 层)
  3. 根据高斯金字塔计算拉普拉斯金字塔
  4. 在拉普拉斯的每一层进行图像融合(苹果的左边与橘子的右边融合)
  5. 根据融合后的图像金字塔重建原始图像。

 程序如下:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 图像尺寸最好是2的整次幂,如256,512等
# 否则在金字塔向上的过程中图像的尺寸会不等
# 这会导致在拉普拉斯金字塔处理时由于不同尺寸矩阵相减而出错
A = cv2.imread('apple.jpg')
B = cv2.imread('orange.jpg')

# 将苹果进行高斯金字塔处理,总共六级处理
G = A.copy()
gpA = [G]
for i in range(6):
    G = cv2.pyrDown(G)
    gpA.append(G)

# 将橘子进行高斯金字塔处理,总共六级处理
G = B.copy()
gpB = [G]
for i in range(6):
    G = cv2.pyrDown(G)
    gpB.append(G)

# 将苹果进行拉普拉斯金字塔处理,总共5级处理
lpA = [gpA[5]]
for i in range(5, 0, -1):
    GE = cv2.pyrUp(gpA[i])
    L = cv2.subtract(gpA[i-1], GE)
    lpA.append(L)

# 将橘子进行拉普拉斯金字塔处理,总共5级处理
lpB = [gpB[5]]
for i in range(5, 0, -1):
    GE = cv2.pyrUp(gpB[i])
    L = cv2.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]  # 这里LS[0]为高斯金字塔的最小图片
for i in range(1, 6):  # 第一次循环的图像为高斯金字塔的最小图片,依次通过拉普拉斯金字塔恢复到大图像
    ls_ = cv2.pyrUp(ls_)
    ls_ = cv2.add(ls_, LS[i])

# 直接拼接
real = np.hstack((A[:, :cols//2], B[:, cols//2:]))

plt.subplot(221), plt.imshow(cv2.cvtColor(A, cv2.COLOR_BGR2RGB)), plt.title('Apple')
plt.subplot(222), plt.imshow(cv2.cvtColor(B, cv2.COLOR_BGR2RGB)), plt.title('Orange')
plt.subplot(223), plt.imshow(cv2.cvtColor(real, cv2.COLOR_BGR2RGB)), plt.title('Direct')
plt.subplot(224), plt.imshow(cv2.cvtColor(ls_, cv2.COLOR_BGR2RGB)), plt.title('Pyramid')
plt.show()

结果如下:

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值