2011-04-07 13 views
10

EDITAR: Paul ha resuelto este a continuación. ¡Gracias!¿Interpolación de Scipy cómo redimensionar/remuestrear la matriz de 3x3 a 5x5?

Estoy tratando de remuestrear (exclusivo) una matriz de 3x3 a 5x5, completando los puntos intermedios con interpolate.interp2d o interpolate.RectBivariateSpline (o lo que sea que funcione).

Si hay una función simple y existente para hacer esto, me gustaría usarla, pero aún no la he encontrado. Por ejemplo, una función que funcionaría como:

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

Por lo tanto, si comienzo con una matriz 3x3/matriz:

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

Quiero calcular una nueva matriz de 5x5 ("I", que significa interpolé valor):

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 

he estado buscando y leyendo y tratando diversos código de prueba diferente, pero bastante no he descubierto la sintaxis correcta para lo que estoy tratando de hacer. Tampoco estoy seguro de si necesito usar meshgrid, mgrid o linspace en ciertas líneas.

EDIT: Se ha corregido y trabajando Gracias a 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 

Respuesta

9

Sólo dos pequeños problemas:

1) Su xx, yy está fuera de los límites de x, y (que puede extrapolar , pero supongo que no desea).

2) Su tamaño de muestra es demasiado pequeño para kx y ky de 3 (valor predeterminado). Baje a 2 y obtenga un ajuste cuadrático en lugar de cúbico.

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

¡Muchas gracias por la solución rápida! Eso es exactamente lo que estaba buscando. Había intentado linspace antes, pero con el formato incorrecto y me perdí completamente kx, ky. – moski

9

Si está utilizando scipy ya, creo scipy.ndimage.interpolate.zoom puede hacer lo que se necesita:

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

Aquí el "factor de zoom" es 5./3 porque vamos a partir de una matriz de 3x3 a una matriz 5x5 . Si lee los documentos, dice que también puede especificar el factor de zoom de forma independiente para los dos ejes, lo que significa que también puede ampliar las matrices no cuadradas. Por defecto, usa interpolación de spline de tercer orden, que no estoy seguro es el mejor.

Lo probé en algunas imágenes y funciona muy bien.

+0

Gracias por señalar eso. No había encontrado esa función. Voy a probar eso también. Me pregunto qué está causando la diferencia significativa en los valores de salida interpolados entre este nd.image.interpolate.zoom e interpolate.RectBivariateSpline. – moski

Cuestiones relacionadas