Python 'order=0的'scipy.ndimage.zoom()'的意外行为`

Python 'order=0的'scipy.ndimage.zoom()'的意外行为`,python,numpy,scipy,zooming,ndimage,Python,Numpy,Scipy,Zooming,Ndimage,我很难理解order=0时的行为 考虑以下代码: import numpy as np import scipy as sp import scipy.ndimage arr = np.arange(3) + 1 print(arr) for order in range(5): zoomed = sp.ndimage.zoom(arr.astype(float), 4, order=order) print(order, np.round(zoomed, 3)) 其输出为:

我很难理解order=0时的行为

考虑以下代码:

import numpy as np
import scipy as sp
import scipy.ndimage

arr = np.arange(3) + 1
print(arr)
for order in range(5):
    zoomed = sp.ndimage.zoom(arr.astype(float), 4, order=order)
    print(order, np.round(zoomed, 3))
其输出为:

0 [1. 1. 1. 2. 2. 2. 2. 2. 2. 3. 3. 3.]
1 [1.    1.182 1.364 1.545 1.727 1.909 2.091 2.273 2.455 2.636 2.818 3.   ]
2 [1.    1.044 1.176 1.394 1.636 1.879 2.121 2.364 2.606 2.824 2.956 3.   ]
3 [1.    1.047 1.174 1.365 1.601 1.864 2.136 2.399 2.635 2.826 2.953 3.   ]
4 [1.    1.041 1.162 1.351 1.59  1.86  2.14  2.41  2.649 2.838 2.959 3.   ]
因此,当
order=0
时,值(预期)不会插值。 但是,我希望:

[1. 1. 1. 1. 2. 2. 2. 2. 3. 3. 3. 3.]
i、 e.每个值的元素数完全相同,因为缩放是一个整数。 因此,我期望得到与以下相同的结果:

为什么每个元素重复的次数会有变化


请注意,
np.repeat()
不能直接处理多维数组,这就是我希望从
scipy.ndimage.zoom()中获得“正确”行为的原因


我的NumPy和SciPy版本是:

print(np.__version__)
# 1.17.4
print(sp.__version__)
# 1.3.3

我发现:
这指向了scipy.ndimage.zoom()的一些意外行为,但我不太确定观察到的效果是否相同。

我认为这是预期的行为

考虑一下您的初始列表,
[1,2,3]
。您要求scipy将其放大4倍,从而创建一个4x3=12个元素的列表。列表的第一个元素必须是1,最后一个元素必须是3。然后,对于2,我们有偶数个元素,所以将2作为第6和第7元素是有意义的。这就给出了
[1,2,2,3]
。从这里开始,您提供了顺序为0的zoom,这意味着zoom将使用顺序为0的样条线来填充缺少的值。第一种情况下,zoom需要填充4个介于1和2之间的缺失值。这必须是
[1,1,2,2]
。第二种情况下,2和3之间缺少4个值。同样的逻辑,
[2,2,3,3]
。最终结果
[1,1,1,2,2,2,2,2,3,3]

现在考虑一个5X变焦,它生成一个15元素数组。同样的故事,只是有一个“中间”元素,所以最初只有一个2被放在新列表的第8位。每对之间有六个元素要填充,我们得到的逻辑是相同的

[1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3]


因此,您得到的2s比1s或3s多,因为2涉及两个插值操作,而不是1和3的一个插值操作

我认为这是预期的行为

考虑一下您的初始列表,
[1,2,3]
。您要求scipy将其放大4倍,从而创建一个4x3=12个元素的列表。列表的第一个元素必须是1,最后一个元素必须是3。然后,对于2,我们有偶数个元素,所以将2作为第6和第7元素是有意义的。这就给出了
[1,2,2,3]
。从这里开始,您提供了顺序为0的zoom,这意味着zoom将使用顺序为0的样条线来填充缺少的值。第一种情况下,zoom需要填充4个介于1和2之间的缺失值。这必须是
[1,1,2,2]
。第二种情况下,2和3之间缺少4个值。同样的逻辑,
[2,2,3,3]
。最终结果
[1,1,1,2,2,2,2,2,3,3]

现在考虑一个5X变焦,它生成一个15元素数组。同样的故事,只是有一个“中间”元素,所以最初只有一个2被放在新列表的第8位。每对之间有六个元素要填充,我们得到的逻辑是相同的

[1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3]


因此,您得到的2s比1s或3s多,因为2涉及两个插值操作,而不是1和3的一个插值操作

这是一个bin/edge数组解释问题。
scipy.ndimage.zoom()
的行为基于数组值的边缘解释,而为整数缩放因子(模仿
np.repeat()
)生成大小相同的块的行为基于bin解释

让我们用一些“图片”来说明

Bin解释 考虑数组
[1 2 3]
,让我们将每个值分配给一个bin。 每个箱子的边缘将是:
0
1
用于
1
1
2
用于
2
,等等

0 1 2 3
|1|2|3|
现在,让我们将此数组缩放4倍:

                    1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2
|   1   |   2   |   3   |
                    1 1
0 1 2 3 4 5 6 7 8 9 0 1
| | | | | | | | | | | |
1          2          3

因此,使用“隔壁邻居”方法分配给料仓的值为:

                    1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2
|1 1 1 1|2 2 2 2|3 3 3 3|
                    1 1
0 1 2 3 4 5 6 7 8 9 0 1
| | | | | | | | | | | |
1 1 1 2 2 2 2 2 2 3 3 3
边缘解释 考虑与前面相同的数组
[1 2 3]
,但现在让我们将每个值分配给一条边:

0 1 2
| | |
1 2 3
现在,让我们将此数组缩放4倍:

                    1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2
|   1   |   2   |   3   |
                    1 1
0 1 2 3 4 5 6 7 8 9 0 1
| | | | | | | | | | | |
1          2          3

因此,要使用“隔壁邻居”方法指定给边的值为:

                    1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2
|1 1 1 1|2 2 2 2|3 3 3 3|
                    1 1
0 1 2 3 4 5 6 7 8 9 0 1
| | | | | | | | | | | |
1 1 1 2 2 2 2 2 2 3 3 3
而边
3
被分配给
2
,因为
2
具有位置
5.5
,而
1
具有位置
0
(5.5-3=2.5)
。 类似地,边
8
被分配给
2
,因为
(8-5.5=2.5)<(11-8=3)


评论 在物理学中,“面元阵列解释”通常更有用,因为测量通常是“在适当的域中对某个面元进行某种积分的结果”(特别是在给定的时间间隔收集的任何形式的信号,包括图像),因此我希望对
scipy.ndimage.zoom()进行“面元解释”)
但我承认“边缘解释”同样有效(尽管我不确定哪些应用程序从中受益最多)



(感谢@Patol75将我指向右侧)

这是一个bin/edge数组解释问题。
scipy.ndimage.zoom()
的行为基于数组值的边缘解释,而为整数缩放因子(模仿
np.repeat()
)生成大小相同的块的行为基于bin解释

让我们用一些“图片”来说明

Bin解释 考虑数组
[1 2 3]
,让我们将每个值分配给一个bin。 每个箱子的边缘应为:
0