提问人:bproxauf 提问时间:3/14/2018 最后编辑:Drisebproxauf 更新时间:11/18/2019 访问量:963
移位插值未给出预期行为
Shift interpolation does not give expected behaviour
问:
当使用 scipy.ndimage.interpolation.shift 通过周期性边界处理 () 沿一个轴移动 numpy 数据数组时,我得到一个意外的行为。该例程尝试强制第一个像素 () 与最后一个像素 () 相同,而不是“最后一个加一 ()”。mode = 'wrap'
index 0
index N-1
index N
最小示例:
# module import
import numpy as np
from scipy.ndimage.interpolation import shift
import matplotlib.pyplot as plt
# print scipy.__version__
# 0.18.1
a = range(10)
plt.figure(figsize=(16,12))
for i, shift_pix in enumerate(range(10)):
# shift the data via spline interpolation
b = shift(a, shift=shift_pix, mode='wrap')
# plotting the data
plt.subplot(5,2,i+1)
plt.plot(a, marker='o', label='data')
plt.plot(np.roll(a, shift_pix), marker='o', label='data, roll')
plt.plot(b, marker='o',label='shifted data')
if i == 0:
plt.legend(loc=4,fontsize=12)
plt.ylim(-1,10)
ax = plt.gca()
ax.text(0.10,0.80,'shift %d pix' % i, transform=ax.transAxes)
蓝线:移位前的数据 绿线:预期的移位
行为
红线:scipy.ndimage.interpolation.shift 的实际移位输出
我如何调用函数或如何理解它的行为是否存在一些错误?当前结果与相关 scipy 教程页面和另一篇 StackOverflow 帖子中的模式参数描述形成鲜明对比。代码中是否存在差一错误?mode = 'wrap'
使用的 Scipy 版本是 0.18.1,在 anaconda-2.2.0 中分发
答:
看来你观察到的行为是故意的。
问题的原因在于 C 函数map_coordinate
该函数将移位后的坐标转换为移位前的坐标:
map_coordinate(double in, npy_intp len, int mode)
该函数用作执行实际移位的子例程。它的有趣部分如下所示:NI_ZoomShift
示例。让我们看看(来自问题)的输出是如何计算的。output = shift(np.arange(10), shift=4, mode='wrap')
NI_ZoomShift
以某种特殊方式计算边缘值,所以让我们看一下(有点简化)的计算:output[0]
output[9]
output[1]
# input = [0,1,2,3,4,5,6,7,8,9]
# output = [ ,?, , , , , , , , ] '?' == computed position
# shift = 4
output_index = 1
in = output_index - shift # -3
sz = 10 - 1 # 9
in += sz * ((-5 / 9) + 1)
# += 9 * (( 0) + 1) == 9
# in == 6
return input[in] # 6
很明显,这是您观察到的行为的原因。它从可追溯到 2007 年的一个暗示性命名的提交中进行了更改:修复 ndimage 边界例程中的 off-by-on 错误。更新测试。sz = len - 1
sz = len
我不知道为什么要引入这样的变化。我想到的可能解释之一如下:
函数“shift”使用样条进行插值。
区间上均匀样条的结向量简单来说就是 。当我们说样条应该换行时,很自然地要求 knots 和 的值相等,这样样条的许多副本就可以粘在一起,形成一个周期函数:[0, k]
[0,1,2,...,k]
0
k
0--1--2--3-...-k 0--1--2--3-...-k 0--1-- ...
0--1--2--3-...-k 0--1--2--3-...-k ...
也许只是将其输入视为样条结的值列表?shift
值得注意的是,此行为似乎是一个错误,如本期 SciPy 中所述:https://github.com/scipy/scipy/issues/2640
该问题似乎影响了除 之外的所有外推。mode
scipy.ndimage
mode='mirror'
评论
shift()
a
[0, 1, 2, 3, 4, 5, 6, 7, 8]
8
[8, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[8, 0, 1, 2, 3, 4, 5, 6, 7, 8]
[8, 0, 1, 2, 3, 4, 5, 6, 7, 8]
b = shift(a, shift=1, mode='wrap')
[8, 0, 1, 2, 3, 4, 5, 6, 7, 8]