Scipy интерполяция, как изменить размер / изменить размер матрицы 3x3 до 5x5? - PullRequest
10 голосов
/ 07 апреля 2011

РЕДАКТИРОВАТЬ: Пол решил это ниже. Спасибо!

Я пытаюсь ресамплировать (масштабировать) матрицу 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 в определенных строках.

РЕДАКТИРОВАТЬ: исправлено и работает Спасибо Полу

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 голосов
/ 08 апреля 2011

Если вы уже используете 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 кМассив 5х5.Если вы читаете документы, это говорит о том, что вы также можете указать коэффициент масштабирования независимо для двух осей, что означает, что вы также можете масштабировать неквадратные матрицы.По умолчанию он использует сплайн-интерполяцию третьего порядка, что, я не уверен, является лучшим.

Я пробовал его на некоторых изображениях, и он прекрасно работает.

9 голосов
/ 08 апреля 2011

Только две небольшие проблемы:

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.    ]]
...