如何用卷积高效生成非零元素的8邻域缓冲区

浅磊同学_8233

浅磊同学_8233

2026-07-27

564人浏览

原创

如何用卷积高效生成非零元素的8邻域缓冲区

本文介绍如何利用 SciPy 的 convolve 函数替代手动位移拼接,将非零值的8方向邻域扩展(即“缓冲区”)计算速度提升数倍至数十倍,适用于大规模二维 NumPy 数组。

本文介绍如何利用 scipy 的 `convolve` 函数替代手动位移拼接,将非零值的8方向邻域扩展(即“缓冲区”)计算速度提升数倍至数十倍,适用于大规模二维 numpy 数组。

在图像处理、地理空间分析和稀疏矩阵邻域建模等场景中,常需快速标记“与任意非零元素相邻(含对角线)”的位置——即为每个非零值生成一个 3×3 的全1缓冲区。原始方法通过 Python 列表推导 + 多次 shift_array 模拟位移并取最大值,不仅代码冗长、内存开销大(需保存8个临时数组),且时间复杂度高(O(9×N²) 显式循环),难以扩展到百万级像素阵列。

更优解是使用二维卷积(2D convolution):将输入二值化后,与一个 3×3 全1卷积核进行相关运算,再对结果做阈值判断。该操作本质是统计每个位置周围 3×3 区域内非零元素个数,只要 ≥1 即标记为1——这正是所需逻辑。

以下是优化后的高性能实现:

import numpy as np
from scipy.ndimage import convolve

def create_neighborhood_buffer(arr):
    """
    为输入二维数组生成8邻域缓冲区(Moore邻域)。

    Parameters
    ----------
    arr : np.ndarray, shape (M, N)
        输入二维数组(支持任意数值类型)

    Returns
    -------
    np.ndarray, shape (M, N), dtype=bool or int
        输出布尔数组:True 表示该位置与至少一个非零值相邻(含自身)
        (可选:`.astype(int)` 转为0/1整数)
    """
    # 步骤1:二值化——仅保留非零位置信息
    binary = arr != 0

    # 步骤2:定义3×3全1卷积核(覆盖中心+8个邻居)
    kernel = np.ones((3, 3), dtype=int)

    # 步骤3:执行卷积(默认 mode='reflect',但此处推荐 'constant' 避免边界伪影)
    # 使用 mode='constant' 并设 cval=0,确保边界外补零
    convolved = convolve(binary, kernel, mode='constant', cval=0)

    # 步骤4:阈值化——只要邻域内存在至少一个非零,结果即为True
    return convolved > 0

# 示例验证
arr = np.array([[10,  0,  0,  0,  0],
                [ 0,  0,  2,  0,  0],
                [ 0,  0,  0,  0,  0]])

result = create_neighborhood_buffer(arr)
print(result.astype(int))

输出:

NumPy Linux版 2.4.2
NumPy Linux版 2.4.2

NumPy 2.4.2 历史版本下载,来自 PyPI 官方发布,适合旧项目兼容、科学计算脚本复现和指定环境安装。

下载
[[1 1 1 1 0]
 [1 1 1 1 0]
 [0 1 1 1 0]]

✅ 性能优势显著:

  • 时间复杂度降至 O(M×N),底层由 C/Fortran 优化实现;
  • 内存友好:仅需 2 个额外数组(binary 和 convolved),无需存储8个位移副本;
  • 自动处理边界:mode='constant' 确保边缘位置正确补零,避免越界错误;
  • 可无缝扩展:支持 float32/int64 等任意 dtype,且对超大数组(如 4096×4096)仍保持毫秒级响应。

⚠️ 注意事项:

  • 若需严格排除“自身为非零”的情况(即仅标记“邻居”,不含中心点),应先将 binary 中的中心位清零(例如 binary_no_center = binary.copy(); binary_no_center[arr != 0] = False),再卷积;
  • 对于极高分辨率数据,可考虑 scipy.ndimage.maximum_filter(等价于卷积+max),其针对此类布尔膨胀任务做了进一步优化;
  • 避免使用 np.where(arr>0, 1, 0) —— 直接 arr != 0 更简洁、更安全(兼容负数、浮点零等)。

综上,用 scipy.ndimage.convolve 替代手工位移,是解决此类邻域膨胀问题的标准、高效且可维护的方案。

相关专题

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

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

2023.07.20

1831

4

python能做什么
python能做什么

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

2023.07.25

4924

7

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

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

2023.07.31

1789

3

python教程
python教程

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

2023.08.03

29417

23

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

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

2023.08.04

3507

5

python eval
python eval

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

2023.08.04

3527

5

scratch和python区别
scratch和python区别

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

2023.08.11

1223

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

616

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2743

5

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SciPy 教程
SciPy 教程

共10课时 | 4.1万人学习

NumPy 官方文档与用户指南
NumPy 官方文档与用户指南

共0课时 | 0人学习