当前位置: 首页 > news >正文

OpenCV - 图像金字塔

目录

一. 图像金字塔的概念

二. 图像金字塔的类型

三. 高斯金字塔(Gaussian Pyramid)

1. 向下采样(缩小图像)

2. 向上采样(放大图像)

四. 拉普拉斯金子塔(Laplacian Pyramid)

五. 一个完整的示例与应用:图像融合

总结:


一. 图像金字塔的概念

图像金字塔 是一种以多分辨率来解释图像的结构。想象一下古埃及的金字塔,从下到上,一层比一层小。图像金字塔也是如此:

  • 底层:是原始图像的高分辨率表示(尺寸最大,细节最丰富)。

  • 上层:是低分辨率的近似(尺寸逐层减小,细节逐渐减少)。

通过构建金字塔,我们可以同时在不同的空间尺度(分辨率)上分析图像的特征。

为什么需要它?

  1. 多尺度分析:某些特征或物体在不同的尺度下会更容易被识别。例如,一张人脸在低分辨率下可能只是一个肤色块,在高分辨率下才能看清眼睛鼻子。

  2. 加速处理:先在小尺寸的低层金字塔上快速进行粗略计算(如寻找感兴趣区域),然后再到高分辨率层进行精细处理,可以极大节省计算时间。

  3. 图像融合:著名的“苹果和橙子”无缝拼接就是通过拉普拉斯金字塔实现的。

  4. 计算机视觉应用:是许多高级算法(如SIFT特征点检测、图像分割、目标识别)的基础。

二. 图像金字塔的类型

在OpenCV中,我们主要处理两种类型的图像金字塔:

  1. 高斯金字塔 (Gaussian Pyramid)

  2. 拉普拉斯金字塔 (Laplacian Pyramid)

三. 高斯金字塔(Gaussian Pyramid)

高斯金字塔是基础,它通过不断的降采样(缩小)和上采样(放大)来构建。

1. 向下采样(缩小图像)

cv2.pyrDown()

这是构建金字塔上层(更小尺寸)的操作。

原理步骤:

  1. 高斯模糊 (Gaussian Blur):首先对当前层的图像进行高斯模糊。这是一个平滑滤波,可以消除降采样后可能产生的混叠效应(Aliasing)。

  2. 降采样 (Subsample):删除所有的偶数行和偶数列。这样图像的长和宽都变为原来的一半,总像素数变为原来的四分之一。

效果:每调用一次pyrDown(),图像尺寸(宽和高)减半,变得更加模糊。

import cv2
import numpy as np# 读取图像
img = cv2.imread('image.jpg')
layer = img.copy()  # 创建一个副本用于操作# 存储高斯金字塔的列表
gaussian_pyramid = [layer]  # 第0层是原图for i in range(6):  # 构建6层金字塔 layer = cv2.pyrDown(layer)  # 对当前层进行向下采样gaussian_pyramid.append(layer)# 可以打印每层的尺寸看看print(f"Gaussian Layer {i + 1} size: {layer.shape}")# 显示其中一层,列如第3层(索引为3)
cv2.imshow('Gaussian Level 3', gaussian_pyramid[3])if cv.waitKey(0) & 0xFF == ord('q'):cv2.destroyAllWindows()

代码详细讲解:

1. layer = img.copy() 

解释img.copy():创建img的一个完整副本。这是非常重要的,因为在Python中,直接赋值(如layer = img)只是创建了一个引用(别名),而不是真正的副本。如果修改layer,原始图像img也会被修改。

2. gaussian_pyramid = [layer]

解释gaussian_pyramid = [layer]:创建一个名为gaussian_pyramid的列表,并将当前图像(原始图像的副本)作为列表的第一个元素。

3. layer = cv2.pyrDown(layer)

解释

  • cv2.pyrDown(layer):对当前layer图像应用高斯金字塔的下采样操作。这个函数会:

    1. 对图像进行高斯模糊(平滑)

    2. 将图像的宽度和高度都减半(删除所有偶数行和偶数列)

  • layer =:将下采样后的新图像赋值给layer变量,覆盖之前的值。这样在下次循环中,我们将基于这个更小的图像进行进一步下采样。

4. print(f"Gaussian Layer {i+1} size: {layer.shape}")

解释:使用f-string格式化字符串,打印当前金字塔层的索引(从1开始计数)和它的尺寸(高度、宽度、通道数)。

5. cv2.imshow('Gaussian Level 3', gaussian_pyramid[3])

解释:创建一个名为'Gaussian Level 3'的窗口,并在其中显示高斯金字塔中索引为3的图像(即第4个图像,因为索引从0开始)。

2. 向上采样(放大图像)

cv2.pyrUp()

这是从金子塔的上层(小图)重建下层(大图)的操作。

注意:即使放大回来,也会丢失一些细节,无法完全恢复到原始图像。

原理步骤:

  1. 升采样 (Upsample):在每个像素之间插入零值。例如,一个2x2的图像会先变成4x4,但其中很多像素值为0。

  2. 高斯模糊 (Gaussian Blur):然后使用与 pyrDown 类似的高斯核进行卷积,以“填充”那些零值像素,生成一个平滑的、放大后的图像。

效果:每调用一次 pyrUp(),图像尺寸(宽和高)加倍,但会比原始的大图更模糊。

# 从高斯金字塔的最高层(最小的图)开始向上采样
reconstructed_layer = gaussian_pyramid[-1] # 取最顶层的小图for i in range(len(gaussian_pyramid)-1):reconstructed_layer = cv2.pyrUp(reconstructed_layer) # 向上采样# 可以与原始层进行对比# 注意:由于尺寸可能因奇数除法有1像素的差异,需要调整对比的ROI# print(f"Reconstructed size: {reconstructed_layer.shape}, Original size: {gaussian_pyramid[-(i+2)].shape}")# 比较一下原图和“先下采样再上采样”的图,能看到细节的丢失
up_down = cv2.pyrUp(cv2.pyrDown(img))
cv2.imshow('Original', img)
cv2.imshow('PyrDown -> PyrUp', up_down)if cv2.waitKey(0) & 0xFF == ord('q'):cv2.destroyAllWindows()

四. 拉普拉斯金子塔(Laplacian Pyramid)

拉普拉斯金字塔是由高斯金字塔构建而来的。它存储的不是图像本身,而是图像的细节信息,可以理解为“残差”或“边缘”。

构建原理:

  1. 对第 i 层高斯图像进行上采样:G_i_up = pyrUp(Gaussian_{i+1})

    Gaussian_{i+1} 是比 Gaussian_i 更高一层的(更小的)高斯图像。
  2. 将上采样得到的图像与第 i 层的高斯图像相减:

    Laplacian_i = Gaussian_i - G_i_up

拉普拉斯金字塔的每一层,都是高斯金字塔该层与其上一层经上采样后的版本的差。 它包含了为从低分辨率图像(高层)恢复到高分辨率图像(低层)所需的细节信息

主要用途:图像重建、图像压缩、图像融合。

# 构建拉普拉斯金字塔
# 它比高斯金字塔少一层,因为最高层没有更高层用来计算差了
laplacian_pyramid = []for i in range(len(gaussian_pyramid)-1):# 1. 获取当前高斯层gaussian_current = gaussian_pyramid[i]# 2. 获取上一层的高斯层,并对其进行上采样gaussian_next = gaussian_pyramid[i+1]gaussian_next_up = cv2.pyrUp(gaussian_next)# 3. 确保上采样后的图像尺寸与当前层一致(因为奇数尺寸可能导致1像素的差异)# 例如,原图是511x511,pyrDown后是255x255,pyrUp后是510x510rows, cols, _ = gaussian_current.shapegaussian_next_up = gaussian_next_up[:rows, :cols] # 简单的裁剪# 4. 计算拉普拉斯层:当前层 - 上采样后的上一层laplacian = cv2.subtract(gaussian_current, gaussian_next_up)laplacian_pyramid.append(laplacian)# 显示拉普拉斯层(注意:拉普拉斯图像可能有负值,需要转换才能显示)laplacian_display = cv2.convertScaleAbs(laplacian) # 取绝对值并转换为8位cv2.imshow(f'Laplacian Level {i}', laplacian_display)
if cv2.waitKey(0) & 0xFF == ord('q'):cv2.destroyAllWindows()

五. 一个完整的示例与应用:图像融合

图像融合是拉普拉斯金字塔最经典的应用之一。其基本思想是:

  1. 为两张待融合的图像分别构建高斯金字塔和拉普拉斯金字塔。

  2. 将两张图像的拉普拉斯金字塔的每一层拼接起来(例如,左半部分用A图的,右半部分用B图的)。

  3. 用这个拼接后的新拉普拉斯金字塔,从顶到底,与高斯金字塔的顶层一起,逐层重建出融合后的完整图像。

import cv2
import numpy as np# 1. 读取两张需要拼接的图片
A = cv2.imread('apple.jpg')
B = cv2.imread('orange.jpg')# 确保两张图尺寸相同
B = cv2.resize(B, (A.shape[1], A.shape[0]))# 2. 为每张图构建高斯金字塔
gpA = [A.copy()]
gpB = [B.copy()]for i in range(6):A = cv2.pyrDown(A)B = cv2.pyrDown(B)gpA.append(A)gpB.append(B)# 3. 构建拉普拉斯金字塔
lpA = [] 
lpB = []
for i in range(len(gpA)-1):# 计算A的拉普拉斯层GE = cv2.pyrUp(gpA[i+1])rows, cols, _ = gpA[i].shapeGE = GE[:rows, :cols]LA = cv2.subtract(gpA[i], GE)lpA.append(LA)# 计算B的拉普拉斯层GE = cv2.pyrUp(gpB[i+1])rows, cols, _ = gpB[i].shapeGE = GE[:rows, :cols]LB = cv2.subtract(gpB[i], GE)lpB.append(LB)# 4. 现在将每一层的拉普拉斯图像进行拼接(左边来自A,右边来自B)
LS = []
for la, lb in zip(lpA, lpB):rows, cols, dpt = la.shape# 水平拼接ls = np.hstack((la[:, :cols//2], lb[:, cols//2:]))LS.append(ls)# 5. 从拉普拉斯金字塔重建图像
# 从最顶层(最小的高斯图像)开始
ls_ = LS[-1] # 取拼接后的最顶层拉普拉斯图
# 它的基础是高斯金字塔的顶层
reconstructed = cv2.pyrUp(gpA[-1]) # 或者 gpB[-1],它们此时尺寸一样小
rows, cols, _ = ls_.shape
reconstructed = reconstructed[:rows, :cols]
# 开始重建:当前重建层 = 当前拉普拉斯层 + 上一层重建层(经过上采样)
for i in range(len(LS)-2, -1, -1): # 从倒数第二层循环到第0层ls_ = LS[i]reconstructed = cv2.pyrUp(reconstructed)rows, cols, _ = ls_.shapereconstructed = reconstructed[:rows, :cols]# 核心步骤:相加reconstructed = cv2.add(reconstructed, ls_)# 6. 显示结果
cv2.imshow('Apple', gpA[0])
cv2.imshow('Orange', gpB[0])
cv2.imshow('Blended', reconstructed)if cv2.waitKey(0) & 0xFF == ord('q'):cv2.destroyAllWindows()

总结:

  • 高斯金字塔:存储的是图像本身的多尺度表示。用 pyrDown() 和 pyrUp() 操作。

  • 拉普拉斯金字塔:存储的是不同尺度下的细节信息。由高斯金字塔计算得出。

http://www.dtcms.com/a/395280.html

相关文章:

  • 寄存柜频繁维护还卡顿?杰和IB2-281主板:智能化升级高效省心
  • 海外短剧系统开发:多语言适配与跨地区部署的架构实践
  • JVM内存模型详解:看内存公寓如何分配“房间“
  • 【论文阅读】4D-VLA:时空视觉-语言-动作预训练与跨场景校准
  • 【论文阅读】MDM : HUMAN MOTION DIFFUSION MODEL
  • 【论文阅读】RynnVLA-001:利用人类示范改进机器人操作
  • Leecode hot100 - 105.从前序与中序遍历序列构造二叉树
  • 联邦学习论文分享:Federated Learning with GAN-based Data Synthesis for Non-IID Clients
  • 绕过百度网盘无限制下载
  • 【自记】PyCharm 更换阿里云国内源教程
  • 【Axure原型分享】区间K线图
  • javascript之Es6八股文
  • npm和pnpm命令大全
  • kali下安装beef-xss报错-启动失败-简单详细
  • 政策法规下的LLM安全:合规之路
  • 《第21课——C typedef:从Java的“实名制”到C的“马甲生成器”——类型伪装术与代码整容的艺术》
  • 【每天一个知识点】什么是知识库?
  • 豆包·Seedream 4.0深度测评:4K多模态时代的图像创作革命(图文增强版)
  • [新启航]发动机喷管推进剂输送孔光学 3D 轮廓测量 - 激光频率梳 3D 轮廓技术
  • 深入理解 TCP 协议:三次握手与四次挥手的底层原理
  • PyTorch 神经网络工具箱
  • 机器学习-多因子线性回归
  • 国产化Excel开发组件Spire.XLS教程:Python 写入 Excel 文件,数据写入自动化实用指南
  • 08 - spring security基于jdbc的账号密码
  • 解决SSL证书导致源站IP被泄露的问题
  • Worst Western Hotel: 1靶场渗透
  • 电子电气架构 --- 软件开发与产品系统集成流程(上)
  • 运维安全08,日志检测和 tcpdump (抓包) 的介绍以及使用
  • DSC 归档配置相关
  • 彭博社-BloombergGPT金融大模型