ndimage.generic_filter如何处理多维数组?原理与示例解析
scipy.ndimage.generic_filter处理三维数组的逻辑 我来帮你把generic_filter处理三维(及更高维)数组的运行逻辑讲透,结合你给出的代码例子一步步拆解:
核心逻辑(通用所有维度)
不管数组是2维、3维还是更高维,generic_filter的核心流程都是一致的:
- 遍历数组中的每一个元素,把它当作当前计算的「中心元素」
- 根据你传入的
footprint,确定需要收集的「邻域范围」——footprint里值为1的位置,标记了相对于中心元素的哪些偏移位置需要被纳入计算 - 把这些邻域内的元素(包括超出数组边界时按规则填充的元素)拉平成一个一维buffer,传给你定义的自定义函数(比如你的
fnc是取最小值) - 自定义函数的返回值,就是输出数组中对应中心元素位置的结果
结合你的三维例子详解
先明确你代码里的关键参数:
- 输入数组
a:np.arange(36).reshape(3,3,4),形状是(3,3,4),可以理解为「3层(轴0)、每层3行(轴1)、每行4列(轴2)」的三维结构 - 自定义函数
fnc:返回buffer中的最小值 footprint:形状是(3,2,2),所有位置都是1——意味着邻域覆盖了:- 轴0方向:当前中心元素的前一层、当前层、后一层(共3层)
- 轴1方向:当前中心元素的上一行、当前行(共2行)
- 轴2方向:当前中心元素的前一列、当前列(共2列)
具体计算过程(拿几个典型位置举例)
角落元素
a[0,0,0]
这个位置是数组的最角落,按照footprint的范围,很多偏移位置会超出数组边界(比如轴0的-1、轴1的-1、轴2的-1)。generic_filter默认会用mode='reflect'规则填充边界(简单说就是把边界外的位置反射到数组内,比如x=-1会被当作x=0)。
最终收集到的buffer包含所有填充后的邻域元素,其中最小的就是0,所以输出数组的[0,0,0]位置值为0。中间元素
a[1,1,1]
这个位置完全在数组内部,没有边界问题。footprint覆盖的邻域是:轴0的0、1、2层,轴1的0、1行,轴2的0、1列,也就是a[0:3, 0:2, 0:2]的所有元素。这些元素里的最小值是0,所以输出数组的[1,1,1]位置值也是0。边缘元素
a[0,1,2]
轴0方向的偏移-1会被填充为0(反射规则),轴1和轴2的偏移都在数组范围内。收集到的buffer包含轴0的0、0、1层,轴1的0、1行,轴2的1、2列的元素,其中最小值还是0,所以输出位置的值依旧是0。
关于高维数组的延伸
如果是4维及以上的数组,逻辑完全一致:footprint的维度需要和输入数组的维度匹配,每个维度上的1标记了该维度需要覆盖的偏移范围,最终还是收集所有标记位置的元素到一维buffer,传给自定义函数计算。
内容的提问来源于stack exchange,提问作者tilt

