第11章:图像金字塔

article/2025/10/23 2:03:05

第11章:图像金字塔

    • 一、理论基础:
      • 1. 向下采样:
      • 2. 向上采样:
    • 二、pyrDown函数使用:
    • 三、pyrUp函数及使用:
    • 四、采样可逆性研究
    • 五、拉普拉斯金字塔
      • 1. 定义:
      • 2. 应用:

什么是图像金子塔?

​ 图像金字塔是由一幅图像的多个不同分辨率的子图构成的图像集合。是通过一个图像不断的降低采样率产生的,最小的图像可能仅仅有一个像素点。下图是一个图像金子塔的示例。从图中可以看到,图像金字塔是一系列以金字塔形状排列的、自底向上分辨率逐渐降低的图像集合。

image-20211103135027005

​ 通常情况下,图像金字塔的底部是待处理的高分辨率图像(原始图像),而顶部则为其低分辨率的近似图像。向金字塔顶部移动时,图像的尺寸和分辨率都不断地降低。通常情况下,每向上移动一级,图像的宽和高都降低为原来的二分之一。

一、理论基础:

图像金字塔是同一图像不同分辨率的子图集合,是通过原图像不断地向下降低采样而产生的,即由高分辨率的图像(大尺寸)产生低分辨率的近似图像(小尺寸)。

1. 向下采样:

​ 最简单的图像金字塔可以通过不断的删除图像的偶数行和偶数列得到的。例如,有一幅图像,其大小是N*N,删除其偶数行和偶数列后得到一幅(N/2)*(N/2)大小的图像。经过上述处理后,图像的大小变为原来的四分之一,不断重复该过程,就可以得到该图像的图像金字塔。

​ 也可以通过先对原始图像滤波,得到原始图像的近似图像,然后将近似图像的偶数行和偶数列删除以获取向下采样的结果。有多种滤波器可以选择。

  • 领域滤波器:采用邻域平均值计算求原始图像的近似图像。该滤波器能够产生平均金字塔。

  • 高斯滤波器:采用高斯滤波器对原始图像进行滤波,得到高斯金字塔。这是OpenCV函数cv2.pyrDown()所采用的的方式。

    高斯金字塔是通过不断地使用高斯金字塔滤波、采样所产生的,其过程如下:

    image-20211103141432789

​ 经过上述处理后,原始图像与各次向下采样所得到的结果图像共同构成了高斯金字塔。例如,可以将原始图像称为第0层,第1次向下采样的结果图像称为第一层、第2次向下采样的结果图像称为第2层,以此类推。上述图像所构成的高斯金字塔如图所示。

image-20211103141930222

​ 下面为了表述统一,我们一律将图像金字塔中底层称为第0层,底层上面一层称为第1层,并以此类推。

2. 向上采样:

​ 在向上采样的过程中,通常将图像的宽度和高度都变为原来的2倍。这意味着,向上采样的结果图像的大小是原始图像的4倍。因此,要在结果图像中补充大量的像素点。对新生成的像素点进行赋值的行为,称为 插值。该过程可以通过多种方式实现,例如最邻近插值就是使用最邻近的像素点给当前还没有值的像素点赋值。

​ 还有一种常见的向上采样,对像素点以补零的方式完成插值。通常是在每列像素点的右侧插入值为零的列,在每行像素点的下方插入值为零的行。如图,左侧是要进行向上采样的4个像素点,右侧是向上采样时进行补零后处理结果。

image-20211103142850912

​ 接下来,使用向下采样时所使用的的高斯滤波器对补零后的图像进行滤波处理,以获取向上采样的结果图像。 但是需要注意,此时图像中有四分之三的像素点的值都是零。所以,要将高斯滤波器系数乘以4,以保证得到的像素值在其原有像素值的范围内。

​ 例如,针对上图右侧的像素点,其对应的是8位图像,像素值的范围是[0, 255]。由于其中四分之三的像素点的值都是为零,如果直接使用高斯滤波器对其进行卷积计算,会导致像素值的范围变为[0, 255*1/4]。所以,要将所使用的高斯滤波器系数乘以4,以保证得到像素值的范围仍旧在[0, 255]内。

​ 或者,从另一个角度理解,在原始图像内每个像素点的右侧列插入零值列,在每个像素点的下一行插入零值行,将图像变为原来的两倍宽、两倍高。接下来,将补零后的图像用高斯滤波器进行卷积运算。最后,将图像内每个像素点的值乘以4,以保证像素值的范围与原始图像一致。

​ 通过以上分析可知,向上采样和向下采样是相反的两种操作。但是,由于上下采样会丢失像素值,所以两种操作并不是可逆的。 也就是说,对一幅图像先向上采样、再向下采样,是无法恢复期原始状态的;同样,对一幅图像先向下采样、再向上采样也是无法恢复到原始状态的。

二、pyrDown函数使用:

在OpenCV中使用函数cv2.pyrDown(),实现图像高斯金字塔操作中的向下采样,语法形式为:

dst = cv2.pyrDown(src [, dstsize [, borderType] ])

  • dst:目标图像
  • src:原始图像
  • dstsize:目标图像的大小
  • borderType:边界类型,默认值为BORDER_DEFAULT,且这里仅支持BORDER_DEFAULT。

默认情况下,输出图像的大小为Size((src.cols+1)/2, (src.rows+1)/2)。在任何情况下,图像的尺寸必须满足如下条件:

  • |dst.width * 2 - src.cols| ≤ 2

    |dst.height * 2 - src.rows| ≤ 2

cv2.pyrDown()函数首先对原始图像进行高斯滤波变换,以获取原始图像的近似图像。在获取近似图像后,该函数通过抛弃偶数行和偶数列来实现向下采样。

示例:

import cv2img = cv2.imread('../lena.bmp')
rst1 = cv2.pyrDown(img)
rst2 = cv2.pyrDown(rst1)
rst3 = cv2.pyrDown(rst2)print('img.shape=', img.shape)
print('rst1.shape=', rst1.shape)
print('rst2.shape=', rst2.shape)
print('rst3.shape=', rst3.shape)cv2.imshow('img', img)
cv2.imshow('rst1', rst1)
cv2.imshow('rst2', rst2)
cv2.imshow('rst3', rst3)cv2.waitKey()
cv2.destroyAllWindows()# 输出结果
img.shape= (512, 512, 3)
rst1.shape= (256, 256, 3)
rst2.shape= (128, 128, 3)
rst3.shape= (64, 64, 3)

image-20211103153007877

三、pyrUp函数及使用:

在OpenCV中,使用函数cv2.pyrUp()实现图像金字塔操作中的向上采样,其语法格式为:

dst = cv2.pyrUp(src, [, dstsize [, borderType ] ] )

  • dst:目标图像
  • src:原始图像
  • dstsize:目标图像的大小
  • borderType:边界类型,默认值为BORDER_DEFAULT,且这里仅支持BORDER_DEFAULT。

默认情况下,输出图像的大小为Size(src.cols*2, src.rows*2)。在任何情况下,图像的尺寸必须满足如下条件:

  • |dst.width - src.cols * 2| ≤ mod(dst.widh, 2)

    |dst.height - src.rows * 2| ≤ mod(dst.height, 2)

​ 在使用cv2.pyrUp()函数对图像向上采样时,在每个像素的右侧、下方分别插入零值列和零值行,得到一个偶数行、偶数列(即新增的行、列)都是零值的新图像New。接下来,用向下采样时所使用的高斯滤波器对新图像New进行滤波,得到向上采样的结果图像。需要注意的是,为了确保像素值的区间在向上采样后与原始图像保持一致,需要将高斯滤波器的系数乘以4。

示例:

import cv2img = cv2.imread('../boat.512.tiff')
rst1 = cv2.pyrUp(img)
rst2 = cv2.pyrUp(rst1)
rst3 = cv2.pyrUp(rst2)print('img.shape=', img.shape)
print('rst1.shape=', rst1.shape)
print('rst2.shape=', rst2.shape)
print('rst3.shape=', rst3.shape)cv2.imshow('img', img)
cv2.imshow('rst1', rst1)
cv2.imshow('rst2', rst2)
cv2.imshow('rst3', rst3)cv2.waitKey()
cv2.destroyAllWindows()# 输出结果
img.shape= (64, 64, 3)
rst1.shape= (128, 128, 3)
rst2.shape= (256, 256, 3)
rst3.shape= (512, 512, 3)

image-20211103162317850

四、采样可逆性研究

​ 图像在向上采样后,整体尺寸变为原来的4倍;在向下采样后,整体尺寸变为原来的四分之一。下图展示了图像在采样前后的大小变化关系。一幅M*N大小的图像经过向下采样后大小会变为(M/2)*(N/2);一幅M*N大小的图像经过向上采样后大小会变为(2M)*(2N)

​ 虽然一幅图像在先后经过向下采样、向上采样后,会恢复原始大小,但是向上采样和向下采样不是互逆的。也就是说,虽然在经历两次采样操作后,得到的结果图像与原始图像的大小一致,肉眼看起来也相似,但是二者的像素并不是一致的。

示例:

import cv2img = cv2.imread('../boat.512.tiff')down = cv2.pyrDown(img)
up = cv2.pyrUp(down)
diff = up - img
print('img.shape=', img.shape)
print('down.shape=', up.shape)
cv2.imshow('img', img)
cv2.imshow('up', up)
cv2.imshow('diff', diff)
cv2.waitKey()
cv2.destroyAllWindows()# 输出结果
img.shape= (512, 512, 3)
down.shape= (512, 512, 3)

image-20211103164347143

五、拉普拉斯金字塔

​ 前面所介绍的高斯金字塔,是通过对一幅图像一系列的向下采样所产生的。有时,我们希望通过对金字塔中的小图像进行向上采样以获取完整的大尺寸高分辨率图像,这时就需要用到拉普拉斯金字塔。

1. 定义:

​ 一幅图像在经过向下采样后,在对其进行向上采样,是无法恢复为原始状态的。对此,我们也用程序进行了验证。向上采样并不是向下采样的逆运算。这很明显,因为向下采样时在使用高斯滤波器处理后还要抛弃偶数行,偶数列,不可避免的要丢失一些信息。

为了在向上采样是能够恢复具有较高分辨率的原始图像,就要获取在采样过程中所丢失的信息,这些丢失的信息就构成了拉普拉斯金字塔。 也是拉普拉斯金字塔是有向下采样时丢失的信息构成。

拉普拉斯金字塔的定义形式为:

  • Li = Gi - pyrUp( Gi + 1 )

式中:

  • Li:表示拉普拉斯金字塔中的第i层
  • Gi:表示高斯金字塔中的第i层

​ 拉普拉斯金字塔中的第i层,等于"高斯金字塔中的第i层"与"高斯金字塔中的第 i + 1层的向上采样结果"之差。下图展示了高斯金字塔和拉普拉斯金字塔的对应关系。

image-20211104141957761

示例:使用cv2.pyrDown()和cv2.pyrUp()构造拉普拉斯金子塔

import cv2img = cv2.imread('../boat.512.tiff')
G1 = cv2.pyrDown(img)
G2 = cv2.pyrDown(G1)
G3 = cv2.pyrDown(G2)L0 = img - cv2.pyrUp(G1)
L1 = G1 - cv2.pyrUp(G2)
L2 = G2 - cv2.pyrUp(G3)print('L0.shape=', L0.shape)
print('L1.shape=', L1.shape)
print('L2.shape=', L2.shape)cv2.imshow('L0', L0)
cv2.imshow('L1', L1)
cv2.imshow('L2', L2)
cv2.waitKey()
cv2.destroyAllWindows()# 输出结果
L0.shape= (512, 512, 3)
L1.shape= (256, 256, 3)
L2.shape= (128, 128, 3)

image-20211104142942584

2. 应用:

拉普拉斯金字塔的作用在于,能够恢复高分辨率的图像。下图演示了如何通过拉普拉斯金字塔恢复高分辨率图像。

image-20211104143448105

图中各标记含义如下:

  • G0、G1、G2、G3分别是高斯金字塔的第0层、第1层、第2层、第3层。
  • L0、L1、L2、分别是拉普拉斯金字塔的第0层、第1层、第2层。
  • 向下的箭头表示向下采样操作(对应cv2.pyrDown()函数)
  • 向右的箭头表示向上采样操作(对应cv2.pyrUp() 函数)
  • "+"表示加法操作
  • "-"表示减法操作

上图中的操作关系有:

向下采样:

  • G1 = cv2.pyrDown(G0)
  • G2 = cv2.pyrDown(G1)
  • G3 = cv2.pyrDown(G2)

拉普拉斯金字塔:

  • L0 = G0 - cv2.pyrUp(G1)
  • L1 = G1 - cv2.pyrUp(G2)
  • L2 = G2 - cv2.pyrUp(G3)

向上采样恢复高分辨率图像:

  • G0 = L0 + cv2.pyrUp(G1)
  • G1 = L1 + cv2.pyrUp(G2)
  • G2 = L2 + cv2.pyrUp(G3)

上述关系是通过数学运算推导得到的。例如,已知L0=G0-cv2.pyrUp(G1),将表达式右侧的cv2.pyrUp(G1)移到左侧,就得到了表达式G0 = L0 + cv2.pyrUp(G1)。除此之外,G1和G2都可以通过拉普拉斯金字塔的构造表达式得到。如之前介绍的,拉普拉斯金字塔的目的就是为了恢复高分辨率的图像。

示例:使用拉普拉斯金字塔恢复高分辨率的图像

import cv2
import numpy as npimg = cv2.imread('../boat.512.tiff')G0 = img
G1 = cv2.pyrDown(G0)
G2 = cv2.pyrDown(G1)
G3 = cv2.pyrDown(G2)L0 = G0 - cv2.pyrUp(G1)
L1 = G1 - cv2.pyrUp(G2)
L2 = G2 - cv2.pyrUp(G3)rst_G0 = L0 + cv2.pyrUp(G1)
rst_G1 = L1 + cv2.pyrUp(G2)
rst_G2 = L2 + cv2.pyrUp(G3)print('rst_G0', np.sum(abs(G0 - rst_G0)))
print('rst_G1', np.sum(abs(G1 - rst_G1)))
print('rst_G2', np.sum(abs(G2 - rst_G2)))cv2.imshow('G0', G0)
cv2.imshow('G1', G1)
cv2.imshow('G2', G2)cv2.imshow('rst_G0', rst_G0)
cv2.imshow('rst_G1', rst_G1)
cv2.imshow('rst_G2', rst_G2)cv2.waitKey()
cv2.destroyAllWindows()

image-20211104145537252


http://chatgpt.dhexx.cn/article/NeUjng6Z.shtml

相关文章

C语言for语句简单打印心形。

C语言简单for语句打印心形 #include<stdio.h> int main() {int i;int j;int k;int n;int m;printf("\n\n\n\n\n\n\n\n表白朋友圈:\n\n\n\n");for (i 1; i < 3; i){if (i 1){printf(" ");printf(&quo…

C语言暴力解法:围圈报数(解析与思考)

围圈报数 题目 解题步骤 一.整体逻辑 1.从第&#xff11;个人开始报数&#xff0c; 2.数到第&#xff4d;个人出列&#xff0c; 3.然后从出列的下一个人开始报数&#xff0c; 4.数到第&#xff4d;个人又出列&#xff0c;…&#xff0c;如此反复到所有的人全部出列为止。 二…

html 一个圆圈一个c,如何用c语言程序画一个圆?

以一个空心圆来举例。 /* 判断是是否在圆上 */ int isAtCircle(int x, int y, int r) { /* 将(x, y)转换为相当圆心(r, r)的坐标 */ int rx x - r; int ry y - r; double d sqrt(rx*rx ry*ry) - r; /*计算到圆心的距离*/ if(fabs(d) < 0.5)""> return 1; e…

在HTML 页面中如何显示带圈圈的数字

数字外面有个圈圈&#xff0c; 或者圈圈里有反底色显示&#xff0c;效果类似&#xff1a; 带圈圈的数字示例&#xff1a; ① 反色圈圈数字示例&#xff1a; ❶ 要实现上面的效果&#xff0c;使用以下技术都可以达成&#xff1a; 方式1&#xff0c;. 使用图片 <image&…

C语言打印出心形表白,初学C语言也能看懂~(3)

例2&#xff1a;C语言实现打印出心形&#xff0c;初学者的表白神器。 解题思路&#xff1a;这道例题可以分成4部分&#xff0c;前3行一部分&#xff0c;4-6行一部分&#xff0c;7-13行一部分&#xff0c;最后一行一部分&#xff0c;读者请仔细阅读注释&#xff0c;小林写的很详…

C语言-报数出圈问题(链表实现)

问题描述&#xff1a;n个人围成一圈&#xff0c;顺序编号。从第一个人开始从1到m报数&#xff0c;凡报到m的人退出圈子&#xff0c;编程求解最后留下的人的初始编号。 程序运行示例&#xff1a; 6 3&#xff08;两个输入数据之间有空格&#xff09; 1输入格式&#xff1a;scanf…

蓝桥杯 小朋友崇拜圈 C语言

标题&#xff1a;小朋友崇拜圈 班里N个小朋友&#xff0c;每个人都有自己最崇拜的一个小朋友&#xff08;也可以是自己&#xff09;。 在一个游戏中&#xff0c;需要小朋友坐一个圈&#xff0c; 每个小朋友都有自己最崇拜的小朋友在他的右手边。 求满足条件的圈最大多少人&…

java 圈复杂度_详解圈复杂度

详解圈复杂度 圈复杂度概念 圈复杂度(Cyclomatic complexity,简写CC)也称为条件复杂度,是一种代码复杂度的衡量标准。由托马斯J麦凯布(Thomas J. McCabe, Sr.)于1976年提出,用来表示程序的复杂度,其符号为VG或是M。它可以用来衡量一个模块判定结构的复杂程度,数量上表现为…

控制台图形化打印二叉树(c/c++)

二叉树作为一种常见的数据结构,我们在学习的过程中会经常用到. 当我们做课设的时候,能把二叉树图形化的打印出来无疑是一个加分项,所以今天我们就来探讨一下如何图形化的打印出二叉树来. 目录 分析阶段 如何打印 如何将数据存入打印数组 代码实现 存储结构定义 二叉树的…

C语言:围圈报数游戏

游戏规则&#xff1a;有N个人围成一圈&#xff0c;顺序排号&#xff0c;从第一个人开始1到D报数&#xff0c;&#xff0c;凡报到D的人退出圈子&#xff08;下场&#xff09;&#xff0c;问最后留下来的是原来的第几号&#xff1f; 逻辑思想&#xff1a;用布尔数组记下每个人的…

c语言 打印共九行的菱形,用C语言打印图案的几种实现方法

循环的使用 维普资讯 http://doc.xuehai.net 科技伯. 1 1 0计算机与信息技术 0 S IN E I F R TO CE C N O MA I N 20 06年第 4期 用 C语言打印图案的几种实现方法 陈莹张青锋 (口师范学院计科系河南周口周 46 0 ) 60 0 摘要&#xff1a;经过几年来在 c语言教学中的实践&#xf…

C语言实现打印简易圣诞树

C语言实现打印简易圣诞树 引言想法的诞生一棵简易的圣诞树怎么构成梯形的代码梯形的叠加做一个长方形树干 总代码及其输出的简易圣诞树 引言 各位大佬好&#xff0c;我是一名大一的学生&#xff0c;目前只学习了C语言的语法基础&#xff0c;在CSDN这个平台上将自己所学的东西记…

HTML圈c怎么打出来,一种方便固定手表的展示C圈的制作方法

本实用新型属于展示C圈技术领域&#xff0c;具体涉及一种方便固定手表的展示C圈。 背景技术&#xff1a; 展示C圈是用来展示手表的必备器材&#xff0c;展示C圈采用耐用透明展示底座&#xff0c;方便工作人员为顾客展示手表的折光度。 原有展示C圈&#xff0c;手表固定在C圈上时…

c语言圈复杂度switch,干货|C语言switch\/case圈复杂度优化重构

点击上方“中兴开发者社区”&#xff0c;关注我们 每天读一篇一线开发者原创好文 ▍作者简介 作者陈彬是一名Linux驱动开发工程师&#xff0c;对Linux内核、软件设计和敏捷有较浓厚的兴趣和长期实践经验。自从项目建立起代码质量规范和监控工具后&#xff0c;如何重构高圈复杂度…

c语言圈复杂度switch,C语言switch/case圈复杂度优化重构

软件重构是改善代码可读性、可扩展性、可维护性等目的的常见技术手段。圈复杂度作为一项软件质量度量指标,能从一定程度上反映这些内部质量需求(当然并不是全部),所以圈复杂度往往被很多项目采用作为软件质量的度量指标之一。 C语言开发的项目中,switch/case代码块是一个很容…

Excel2016打开文件后显示空白

打开文件时显示 打开后空白 解决办法:

Excel双击文件打开后是空白,再次双击才能打开

Excel双击打开文件只弹出空白页面&#xff0c;再双击才打开所需页面。 解决方案&#xff08;仅供参考&#xff09;&#xff1a;WINR -->regedit-->修改HKEY_CLASSES_ROOT\Excel.Sheet.12\shell\Open\command项->默认值 数值数据原值后面加上 “%1” 点击确定即可 如&…

【Windows】Excel2019打开文档显示空白且工具栏灰色无法点击

如标题&#xff0c;要想打开Excel文档&#xff0c;只能通过菜单栏操作&#xff1a;文件->打开&#xff0c;然后选择要打开的文档才能正常显示。遇到这个问题很久了&#xff0c;今天着实忍不住了&#xff0c;特记录一下解决方法。 1、查看是否隐藏 点击“视图”菜单&#x…

Excel 2016打开后显示灰色空白页解决方法

重新装了系统&#xff0c;安装上Excel2016&#xff0c;发现打开xls文件只显示一个灰色的开始页面 再次打开excel文件才显示内容&#xff0c;一直这样岂不是太繁琐&#xff1f; 找到了一个教程&#xff0c;在Excel启动选项设置一下。文件-选项-常规-启动选项&#xff0c;将应用…

解决Excel打开后灰色没有内容的问题

问题现象 双击打开的Excel文件&#xff0c;扩展名包括xls、xlsx、csv&#xff0c;如下图&#xff1a; 解决方案 1、打开注册表 快捷键Win R&#xff0c;输入regedit&#xff1a; 2、修改注册表 计算机\HKEY_CLASSES_ROOT\Excel.csv\shell\Open\command计算机\HKEY_CLA…