【问题标题】:Shift interpolation does not give expected behaviour移位插值没有给出预期的行为
【发布时间】:2018-08-23 03:21:08
【问题描述】:

当使用scipy.ndimage.interpolation.shift 沿一个带有周期性边界处理 (mode = 'wrap') 的轴移动一个 numpy 数据数组时,我得到了一个意想不到的行为。该例程尝试强制第一个像素 (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的实际移位输出

在我如何调用函数或我如何理解 mode = 'wrap' 的行为方面是否有一些错误?当前结果与来自相关scipy tutorial page 和另一个StackOverflow post 的模式参数描述形成对比。代码中是否存在错误?

使用的 Scipy 版本是 0.18.1,分布在 anaconda-2.2.0

【问题讨论】:

  • 使用的Scipy版本是0.18.1,分布在anaconda-2.2.0
  • 不要评论添加说明,而是编辑(注意:已经为你做过)
  • 看起来shift() 在数据移动后执行了边界条件。因此,当 shift_pix 为 1 时,它将 a 转换为 [0, 1, 2, 3, 4, 5, 6, 7, 8],然后 然后 进行换行,将 8 带到前面。我不知道它为什么会这样。
  • @ArthurDent:我不确定事实是否如此。请注意,输出值为[8, 1, 2, 3, 4, 5, 6, 7, 8, 9]。如果我理解正确你的建议,那么包装宁愿给[8, 0, 1, 2, 3, 4, 5, 6, 7, 8]
  • @bproxauf [8, 0, 1, 2, 3, 4, 5, 6, 7, 8] 不是你得到的吗?第二个图中移位数据的第二个元素等于 0,而不是 1。当我执行 b = shift(a, shift=1, mode='wrap') 时,它会产生 [8, 0, 1, 2, 3, 4, 5, 6, 7, 8]。此外,我花在查看 shift 函数源代码上的时间比我愿意承认的要多,但它是用 C 语言编写的,对我来说有点太复杂了,无法解读。据我所知,它看起来应该首先执行换行,但我不能确定。如果你想看,请告诉我。

标签: python scipy interpolation ndimage


【解决方案1】:

您观察到的行为似乎是故意的。

问题的原因在于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 

很明显,sz = len - 1 对您观察到的行为负责。它从 sz = len 更改为可追溯到 2007 年的一个暗示性命名的提交:Fix off-by-on errors in ndimage boundary routines. Update tests.

我不知道为什么要引入这样的变化。我想到的一种可能的解释如下:

函数 'shift' 使用 splines 进行插值。 区间[0, k] 上的均匀样条的节点向量就是[0,1,2,...,k]。当我们说样条线应该环绕时,很自然地要求结点0k 的值相等,以便可以将样条线的许多副本粘合在一起,形成一个周期函数:

0--1--2--3-...-k              0--1--2--3-...-k              0--1-- ...
               0--1--2--3-...-k              0--1--2--3-...-k      ...

也许shift 只是将其输入视为样条结的值列表?

【讨论】:

    【解决方案2】:

    值得注意的是,此行为似乎是一个错误,如此 SciPy 问题中所述: https://github.com/scipy/scipy/issues/2640

    该问题似乎会影响mode 中除mode='mirror' 之外的scipy.ndimage 中的所有推断。

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 1970-01-01
      • 2021-04-03
      • 1970-01-01
      • 1970-01-01
      • 2018-09-18
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多