7

当使用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 教程页面和另一个StackOverflow 帖子中的模式参数描述形成对比。代码中是否存在错误?

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

在此处输入图像描述

4

2 回答 2

1

It is worth noting that this behavior appears to be a bug, as noted in this SciPy issue: https://github.com/scipy/scipy/issues/2640

The issue appears to effect every extrapolation mode in scipy.ndimage other than mode='mirror'.

于 2019-11-18T07:20:27.770 回答
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 年的一个暗示性命名的提交中更改的:修复 ndimage 边界例程中的关闭错误。更新测试。

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

函数 'shift' 使用样条进行插值。区间上均匀样条的节点向量[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只是将其输入视为样条结的值列表?

于 2018-03-19T22:43:00.013 回答