Scipy插值如何将3x3矩阵调整为5x5?

11 投票
2 回答
11604 浏览
提问于 2025-04-16 15:18

编辑: Paul已经在下面解决了这个问题。谢谢!

我想把一个3x3的矩阵变成5x5的,填充中间的点,可以用interpolate.interp2d或者interpolate.RectBivariateSpline(或者其他有效的方法)。

如果有一个简单的现成函数可以做到这一点,我想用它,但我还没找到。例如,一个函数可以像这样工作:

# upscale 2x2 to 4x4
matrixSmall = ([[-1,8],[3,5]])
matrixBig = matrixSmall.resample(4,4,cubic)

所以,如果我从一个3x3的矩阵/数组开始:

0,-2,0
-2,11,-2
0,-2,0

我想计算一个新的5x5矩阵("I"表示插值的值):

0, I[1,0], -2, I[3,0], 0
I[0,1], I[1,1], I[2,1], I[3,1], I[4,1]
-2, I[1,2], 11, I[3,2], -2
I[0,3], I[1,3], I[2,3], I[3,3], I[4,3]
0, I[1,4], -2, I[3,4], 0

我一直在搜索、阅读和尝试各种测试代码,但我还没有搞清楚我想做的事情的正确语法。我也不确定在某些地方是否需要使用meshgrid、mgrid或linspace。

编辑:已修复并正常工作 感谢Paul

import numpy, scipy
from scipy import interpolate

kernelIn = numpy.array([[0,-2,0],
             [-2,11,-2],
             [0,-2,0]])

inKSize = len(kernelIn)
outKSize = 5

kernelOut = numpy.zeros((outKSize,outKSize),numpy.uint8)

x = numpy.array([0,1,2])
y = numpy.array([0,1,2])

z = kernelIn

xx = numpy.linspace(x.min(),x.max(),outKSize)
yy = numpy.linspace(y.min(),y.max(),outKSize)

newKernel = interpolate.RectBivariateSpline(x,y,z, kx=2,ky=2)

kernelOut = newKernel(xx,yy)

print kernelOut

2 个回答

9

如果你已经在使用scipy库,我觉得可以用scipy.ndimage.interpolate.zoom来实现你想要的功能:

import numpy
import scipy.ndimage

a = numpy.array([[0.,-2.,0.], [-2.,11.,-2.], [0.,-2.,0.]])
out = numpy.round(scipy.ndimage.interpolation.zoom(input=a, zoom=(5./3), order = 2),1)

print out
#[[  0.   -1.   -2.   -1.    0. ]
# [ -1.    1.8   4.5   1.8  -1. ]
# [ -2.    4.5  11.    4.5  -2. ]
# [ -1.    1.8   4.5   1.8  -1. ]
# [  0.   -1.   -2.   -1.    0. ]]

这里的“缩放因子”是5./3,因为我们是把一个3x3的数组变成一个5x5的数组。如果你查看文档,会发现你还可以为两个方向单独设置缩放因子,这样就可以对非方形的矩阵进行放大了。默认情况下,它使用的是三阶样条插值,我不太确定这是不是最好的选择。

我在一些图片上试过,效果很好。

10

只有两个小问题:

1) 你的 xx 和 yy 超出了 x 和 y 的范围(你 可以 进行外推,但我猜你并不想这样做。)

2) 你的样本数量对于 kx 和 ky 设置为 3(默认值)来说太少了。把它降低到 2,这样就能得到一个二次拟合,而不是三次的。

import numpy, scipy
from scipy import interpolate

kernelIn = numpy.array([
    [0,-2,0],
    [-2,11,-2],
    [0,-2,0]])

inKSize = len(kernelIn)
outKSize = 5

kernelOut = numpy.zeros((outKSize),numpy.uint8)

x = numpy.array([0,1,2])
y = numpy.array([0,1,2])

z = kernelIn

xx = numpy.linspace(x.min(),x.max(),outKSize)
yy = numpy.linspace(y.min(),y.max(),outKSize)

newKernel = interpolate.RectBivariateSpline(x,y,z, kx=2,ky=2)

kernelOut = newKernel(xx,yy)

print kernelOut
##[[  0.      -1.5     -2.      -1.5      0.    ]
## [ -1.5      5.4375   7.75     5.4375  -1.5   ]
## [ -2.       7.75    11.       7.75    -2.    ]
## [ -1.5      5.4375   7.75     5.4375  -1.5   ]
## [  0.      -1.5     -2.      -1.5      0.    ]]

撰写回答