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 函数来生成和验证积分图。

一点PPT
一点PPT

一句话生成专业PPT,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 的高效数组操作,对于需要频繁处理图像子区域积分图的场景(如实时目标检测、特征提取等)具有重要的实用价值。理解并掌握这一技巧,能够显著优化图像处理算法的性能。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

338

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

225

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

138

2026.02.12

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

550

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

30

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

45

2026.01.06

go语言 数组和切片
go语言 数组和切片

本专题整合了go语言数组和切片的区别与含义,阅读专题下面的文章了解更多详细内容。

56

2025.09.03

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

499

2023.08.14

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

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

精品课程

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

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

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

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