0

0

从整体积分图中高效获取局部区域积分图的方法

碧海醫心

碧海醫心

发布时间:2025-11-16 11:07:16

|

186人浏览过

|

来源于php中文网

原创

从整体积分图中高效获取局部区域积分图的方法

本文详细介绍了如何从一个大型图像(如精灵图集)的积分图中,高效地提取出其中任意指定局部区域(如单个精灵)的积分图。核心方法包括精确切片和基于 numpy 广播机制的行/列减法调整,确保生成的局部积分图具有正确的零起始点,从而实现对子区域求和的快速计算,避免重新计算整个子区域的积分图。

引言:积分图及其应用

积分图(Integral Image),又称求和面积表(Summed-Area Table),是一种用于快速计算图像任意矩形区域内像素值之和的数据结构。其核心思想是,图像中任意一点 (x, y) 的积分图值 I(x, y) 等于原始图像中以 (0, 0) 为左上角、以 (x, y) 为右下角的矩形区域内所有像素值的总和。利用积分图,计算任意矩形区域 (x1, y1) 到 (x2, y2) 内的像素和,仅需四次查找和三次加减运算:I(x2, y2) - I(x1-1, y2) - I(x2, y1-1) + I(x1-1, y1-1)。这极大地提高了区域求和的效率,广泛应用于图像处理、计算机视觉(如Haar特征检测)等领域。

问题:从整体积分图中提取局部积分图

在实际应用中,我们可能拥有一个大型图像(例如,包含多个精灵的精灵图集)的完整积分图。现在,我们需要获取其中某个特定子区域(例如,图集中的一个独立精灵)的积分图。直接对子区域重新计算积分图虽然可行,但如果需要频繁提取,效率会较低。更优的方法是,能否利用已有的整体积分图,通过简单的数学运算和切片操作来“导出”子区域的积分图?

核心原理与实现步骤

答案是肯定的。从整体积分图中提取局部区域的积分图,可以通过以下步骤实现:

  1. 确定子区域的坐标范围: 首先,明确目标子区域在原始大图中的左上角 (y0, x0) 和右下角 (y1-1, x1-1) 像素坐标。这里我们使用半开区间表示法,即 [y0:y1, x0:x1] 代表从 y0 行到 y1-1 行,从 x0 列到 x1-1 列的区域。

  2. 从整体积分图中进行切片: 由于积分图通常会在第一行和第一列进行零填充,以简化边界条件的处理。因此,原始图像中 (y, x) 位置的像素值累加到积分图中的 (y+1, x+1) 位置。 如果我们目标子区域在原始大图中的范围是 [y0:y1, x0:x1],那么在整体积分图中对应的区域将是 [y0:y1+1, x0:x1+1]。 我们需要从整体积分图中切取出这个范围的子矩阵。关键在于,切片时必须包含目标区域的“前导”行和“前导”列(即在整体积分图中,子区域左侧和上方的行/列)。这些前导行和列在后续的调整步骤中至关重要。

  3. 调整切片值以重置原点: 切片得到的子矩阵,其值是基于整体积分图的 (0, 0) 原点累加的。为了使其成为一个独立的、以自身左上角为 (0, 0) 原点的积分图,我们需要进行调整。 调整方法是:将切片子矩阵的第一行和第一列的值从整个子矩阵中减去。具体来说:

    • 将子矩阵的第一行(除了第一个元素)减去其第一个元素。
    • 将子矩阵的第一列(除了第一个元素)减去其第一个元素。
    • 更高效的做法是,将子矩阵的第一行(作为一维数组)从整个子矩阵中减去。
    • 然后,将子矩阵的第一列(作为一维数组)从整个子矩阵中减去。 经过这两步减法操作后,切片子矩阵的第一行和第一列将变为零,从而有效地将子积分图的原点“重置”到其自身的左上角,使其符合标准积分图的定义。

Python 示例

下面通过一个具体的 Python 例子来演示上述步骤,使用 numpy 进行数组操作,并利用 opencv 的 cv.integral 函数来生成和验证积分图。

ClipDrop Relight
ClipDrop Relight

ClipDrop推出的AI图片图像打光工具

下载
import numpy as np
import cv2 as cv

# 1. 定义原始精灵图集和目标子区域
sprite_sheet = np.uint8([
    [1, 2, 1, 2],
    [3, 4, 3, 4],
    [1, 2, 1, 2],
    [3, 4, 3, 4],
])

# 定义子区域在sprite_sheet中的坐标 (y0, y1, x0, x1)
# 对应原始图像的 [y0:y1, x0:x1] 区域
# 例如,我们想提取 [[1, 2], [3, 4]] 这个子图
# 它在 sprite_sheet 中是 sprite_sheet[2:4, 2:4]
y0, y1, x0, x1 = 2, 4, 2, 4
sprite = sprite_sheet[y0:y1, x0:x1]

print("原始精灵图集:\n", sprite_sheet)
print("\n目标子区域 (sprite):\n", sprite)

# 2. 计算整个精灵图集的积分图
# cv.integral 会自动在第一行和第一列添加0填充
sheet_integral = cv.integral(sprite_sheet)
print("\n精灵图集积分图 (sheet_integral):\n", sheet_integral)

# 3. 验证:直接计算目标子区域的积分图 (作为我们期望的输出)
expected_sprite_integral = cv.integral(sprite)
print("\n期望的子区域积分图 (cv.integral(sprite)):\n", expected_sprite_integral)

# 4. 从整体积分图中切片
# 注意:切片范围是 [y0:y1+1, x0:x1+1],以包含子区域的“前导”行和列
# 这里的 y0, x0 是原始图像的起始索引,y1, x1 是结束索引+1
# sheet_integral 的索引比原始图像大1
# 所以,如果原始图像的子区域是 [y0:y1, x0:x1]
# 那么在 sheet_integral 中,对应的切片是 [y0:y1+1, x0:x1+1]
# 例如,y0=2, y1=4, x0=2, x1=4
# 切片范围是 sheet_integral[2:5, 2:5]
sliced_integral = sheet_integral[y0:y1+1, x0:x1+1].copy() # 使用 .copy() 避免视图修改原数据
print("\n从整体积分图切片得到的原始子矩阵 (sliced_integral):\n", sliced_integral)

# 5. 调整切片值以重置原点
# 使用 NumPy 的广播机制:
# 第一次减法:将第一行 (sliced_integral[0:1, :]) 从整个矩阵中减去
sliced_integral -= sliced_integral[0:1, :]
print("\n第一次调整后 (减去第一行): \n", sliced_integral)

# 第二次减法:将第一列 (sliced_integral[:, 0:1]) 从整个矩阵中减去
sliced_integral -= sliced_integral[:, 0:1]
print("\n第二次调整后 (减去第一列,最终结果):\n", sliced_integral)

# 6. 验证结果
print("\n最终提取的子区域积分图是否与期望值一致:", np.array_equal(sliced_integral, expected_sprite_integral))

运行结果示例:

原始精灵图集:
 [[1 2 1 2]
 [3 4 3 4]
 [1 2 1 2]
 [3 4 3 4]]

目标子区域 (sprite):
 [[1 2]
 [3 4]]

精灵图集积分图 (sheet_integral):
 [[ 0  0  0  0  0]
 [ 0  1  3  4  6]
 [ 0  4 10 14 20]
 [ 0  5 13 18 26]
 [ 0  8 20 28 40]]

期望的子区域积分图 (cv.integral(sprite)):
 [[ 0  0  0]
 [ 0  1  3]
 [ 0  4 10]]

从整体积分图切片得到的原始子矩阵 (sliced_integral):
 [[10 14 20]
 [13 18 26]
 [20 28 40]]

第一次调整后 (减去第一行): 
 [[ 0  0  0]
 [ 3  4  6]
 [10 14 20]]

第二次调整后 (减去第一列,最终结果):
 [[ 0  0  0]
 [ 0  1  3]
 [ 0  4 10]]

最终提取的子区域积分图是否与期望值一致: True

注意事项

  • 坐标系统: 务必理解原始图像坐标、积分图坐标以及切片范围之间的对应关系。cv.integral 函数生成的积分图通常比原始图像多一行一列(用于零填充),因此原始图像中的 (y, x) 对应积分图中的 (y+1, x+1)。
  • 切片范围: 切片 sheet_integral[y0:y1+1, x0:x1+1] 的关键在于 +1,它确保我们包含了子区域在积分图中的“前导”行和列,这对于后续的减法调整至关重要。
  • NumPy 广播: 在调整步骤中,sliced_integral -= sliced_integral[0:1, :] 和 sliced_integral -= sliced_integral[:, 0:1] 利用了 NumPy 的广播机制。[0:1, :] 选取的是第一行(保持二维结构),[:, 0:1] 选取的是第一列(保持二维结构),这样 NumPy 就能正确地将其广播到整个矩阵进行减法运算。
  • 数据类型: 积分图的值可能会比原始像素值大很多,因此需要使用足够大的数据类型(如 int32 或 int64)来存储,以避免溢出。cv.integral 默认会使用 int32。

总结

通过上述方法,我们可以高效地从一个大型图像的积分图中提取出任意指定局部区域的积分图,而无需重新计算。这种方法利用了积分图的性质和 NumPy 的高效数组操作,对于需要频繁处理图像子区域积分图的场景(如实时目标检测、特征提取等)具有重要的实用价值。理解并掌握这一技巧,能够显著优化图像处理算法的性能。

相关专题

更多
python开发工具
python开发工具

php中文网为大家提供各种python开发工具,好的开发工具,可帮助开发者攻克编程学习中的基础障碍,理解每一行源代码在程序执行时在计算机中的过程。php中文网还为大家带来python相关课程以及相关文章等内容,供大家免费下载使用。

746

2023.06.15

python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

634

2023.07.20

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

758

2023.07.25

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

617

2023.07.31

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

1261

2023.08.03

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

547

2023.08.04

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

577

2023.08.04

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

705

2023.08.11

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

9

2026.01.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 0.6万人学习

Django 教程
Django 教程

共28课时 | 3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号