更快的方式来执行numpy数组的逐点插值?

时间:2011-04-07 21:23:22

标签: numpy performance curve-fitting smoothing

我有一个3D数据立方体,有两个空间维度,第三个是2D图像每个点的多波段光谱。

H[x, y, bands]

给定波长(或波段数),我想提取对应于该波长的2D图像。这只是一个像H[:,:,bnd]这样的数组切片。类似地,给定空间位置(i,j),该位置处的频谱为H[i,j]

我还希望在光谱上“平滑”图像,以对抗光谱中的低光噪声。这是针对频段bnd,我选择一个大小为wind的窗口,并将n度多项式拟合到该窗口中的频谱。使用polyfit和polyval,我可以找到频带bnd的那个点的拟合频谱值。

现在,如果我想从拟合值中得到bnd的整个图像,那么我必须在图像的每个(i,j)处执行此窗口拟合。我还想要bnd的二阶导数图像,即每个点处拟合光谱的二阶导数的值。

在点上运行,我可以对每个x*y光谱进行polyfit-polyval-polyder。虽然这有效,但这是一个逐点操作。是否有一些pytho-numponic方法可以更快地完成这项工作?

1 个答案:

答案 0 :(得分:1)

如果对固定的dx集合进行最小二乘多项式拟合(x + dx [i],y [i]),然后在x处计算得到的多项式,则结果为(固定)线性组合y [i]。对于多项式的导数也是如此。所以你只需要切片的线性组合。查看“Savitzky-Golay过滤器”。

已编辑以添加S-G过滤器如何工作的简短示例。我没有检查任何细节,因此你不应该依赖它是正确的。

所以,假设你采用宽度为5和度数为2的滤波器。也就是说,对于每个波段(暂时忽略开始和结束时的波段),我们将在两侧采用一个和两个波段,拟合二次曲线,并在中间看它的值。

所以,如果f(x)〜= ax ^ 2 + bx + c和f(-2),f(-1),f(0),f(1),f(2)= p,q ,r,s,t然后我们想要4a-2b + c~ = p,a-b + c~ = q等。最小二乘拟合意味着最小化(4a-2b + cp)^ 2 +(a-b + cq)^ 2 +(cr)^ 2 +(a + b + cs)^ 2 +(4a + 2b + ct)^ 2,这意味着(取a,b,c的偏导数):

  • 4(4A-2B + C-P)+(A-B + C-Q)+(A + B + C-S)4(4A + 2B + C-T)= 0
  • -2(图4a-2B + C-P) - (A-B + C-Q)+(A + B + C-S)2(4A + 2B + C-T)= 0
  • (4A-2B + C-P)+(A-B + C-Q)+(C-R)+(A + B + C-S)+(4A + 2B + C-T)= 0

或,简化,

  • 22a + 10c = 4p + q + s + 4t
  • 10b = -2p-q + s + 2t
  • 10a + 5c = p + q + r + s + t

所以a,b,c = pq / 2-rs / 2 + t,(2(tp)+(sq))/ 10,(p + q + r + s + t)/ 5-(2p- q-2R-S + 2T)。

当然c是拟合多项式的值为0,因此是我们想要的平滑值。因此,对于每个空间位置,我们有一个输入光谱数据的矢量,我们通过乘以一个矩阵来计算平滑的光谱数据,该矩阵的行(除了第一对和最后一对)看起来像[0 ... 0 -9 / 5 4/5 11/5 4/5 -9/5 0 ... 0],中心11/5位于矩阵的主对角线上。

所以你可以为每个空间位置做一个矩阵乘法;但由于它是相同的矩阵,你可以通过一次调用tensordot来完成它。因此,如果S包含我刚刚描述的矩阵(呃,等等,不,我刚刚描述的矩阵的转置),A就是你的三维数据立方体,你的光谱平滑数据立方体将是numpy.tensordot(A,S)

这是重复我的警告的一个好点:我没有检查上面几段中的任何细节,这只是为了说明它是如何工作的,以及为什么你可以做整个事物在单个线性代数运算中。