You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效统计Numpy滑动窗口视图中像素的使用次数?

高效统计滑动窗口补丁的像素覆盖次数

问题背景

使用numpy.lib.stride_tricks.sliding_window_view从100×100图像生成19×19个10×10间隔采样补丁(步长5)时,需要统计每个像素被多少个补丁覆盖。直接对滑动窗口视图执行+=1会导致所有像素仅被加1(视图重叠区域的内存共享导致赋值覆盖),而Python嵌套循环虽然能实现正确计数,但性能极差。


最优解决方案

以下两种方案均基于Numpy向量化操作,完全规避Python循环的性能损耗:

方案1:分段求和(最简洁高效)

通过创建全1补丁数组,利用np.add.reduceat按步长分段累加,直接得到像素覆盖次数:

import numpy as np
from numpy.lib.stride_tricks import sliding_window_view

# 初始化100×100图像
img = np.random.random((100, 100))
patch_shape = (10, 10)
stride = 5

# 生成间隔采样的补丁视图
patches = sliding_window_view(img, patch_shape)[::stride, ::stride]
patch_grid_shape = patches.shape[:2]  # (19,19)

# 构建全1的补丁数组,按步长分段求和得到计数
counts = np.add.reduceat(
    np.add.reduceat(
        np.ones(patch_grid_shape + patch_shape, dtype=int),
        np.arange(0, patch_grid_shape[0] * stride, stride),
        axis=0
    ),
    np.arange(0, patch_grid_shape[1] * stride, stride),
    axis=1
)

方案2:卷积法(逻辑直观)

将补丁采样位置标记为掩码,用全1补丁核做卷积,结果即为像素覆盖次数:

import numpy as np
from numpy.lib.stride_tricks import sliding_window_view

img = np.random.random((100, 100))
patch_shape = (10, 10)
stride = 5

patches = sliding_window_view(img, patch_shape)[::stride, ::stride]
patch_h, patch_w = patches.shape[:2]

# 创建补丁起始位置掩码
kernel = np.zeros(img.shape, dtype=int)
kernel[::stride, ::stride] = 1

# 用10×10全1核卷积得到计数
counts = np.convolve(
    np.convolve(kernel.ravel(), np.ones(patch_shape[0]*patch_shape[1], dtype=int), mode='same'),
    mode='same'
).reshape(img.shape)

为什么直接修改视图无效?

sliding_window_view返回的是原始数组的内存视图,而非独立副本。执行zpatches +=1时,Numpy会通过广播将视图内所有位置赋值为1,但重叠区域的内存是共享的,最终每个像素仅保留最后一次赋值结果,导致所有像素仅被加1。


内容的提问来源于stack exchange,提问作者CrashandCern

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 08:28:21