如何用Numpy实现无重叠2D滑动窗口(分块、均值池化)
无重叠(k,k)滑动窗口的像素均值计算(高效Numpy实现)
核心思路
无重叠滑动窗口本质是将图像按k×k大小分块,直接对每个块计算均值。利用Numpy的矢量化操作或专用分块工具,完全避免Python循环带来的性能损耗。
方法1:纯Numpy实现(无需额外库)
通过重塑数组形状,将原帧的前两个维度拆分为「块数×块大小」的结构,再对块内维度求均值。
代码示例
import numpy as np # 构造测试帧:4×4×3(对应示例单通道矩阵扩展为3通道) frame = np.array([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16] ])[:, :, np.newaxis].repeat(3, axis=2) k = 2 # 处理尺寸:若帧的宽高不能被k整除,自动截断到最近可整除的尺寸 n, m, c = frame.shape n_trunc = (n // k) * k m_trunc = (m // k) * k frame_trunc = frame[:n_trunc, :m_trunc, :] # 分块并计算均值 h_blocks = n_trunc // k # 垂直方向的块数 w_blocks = m_trunc // k # 水平方向的块数 # 重塑为 (垂直块数, 块高度k, 水平块数, 块宽度k, 通道数) blocked_frame = frame_trunc.reshape(h_blocks, k, w_blocks, k, c) # 在块的高度、宽度维度上求均值 mean_blocks = blocked_frame.mean(axis=(1, 3)) print("纯Numpy方法输出:") print(mean_blocks)
方法2:用skimage的view_as_blocks(更直观)
view_as_blocks是专门用于生成无重叠分块的工具,内部封装了stride_tricks的复杂步长计算,更易上手且不易出错。
代码示例
import numpy as np from skimage.util import view_as_blocks # 构造测试帧 frame = np.array([ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16] ])[:, :, np.newaxis].repeat(3, axis=2) k = 2 # 生成无重叠块,块形状为(k, k, 3) blocks = view_as_blocks(frame, block_shape=(k, k, 3)) # 对每个块的内部维度求均值 mean_blocks = blocks.mean(axis=(2, 3)) print("\nskview_as_blocks方法输出:") print(mean_blocks)
输出说明
对于上述测试帧(k=2),输出结果为(2,2,3)的数组,每个元素对应一个2×2窗口的三通道均值:
[[[3.5 3.5 3.5] [5.5 5.5 5.5]] [[11.5 11.5 11.5] [13.5 13.5 13.5]]]
为什么as_strided容易出错?
手动使用as_strided需要精确计算数组的步长(stride),对于(n,m,3)的帧,元素步长、行步长、列步长的计算需考虑通道数,无重叠块的跨块步长还要乘以k。view_as_blocks已封装这一过程,避免手动计算出错。
内容的提问来源于stack exchange,提问作者gaviezri
相关产品推荐
相关产品推荐

