python - multiplicar - numpy tutorial español pdf
Remuestreo de una matriz numpy que representa una imagen (4)
Estoy buscando cómo volver a muestrear una matriz numpy que represente datos de imágenes en un nuevo tamaño, preferiblemente teniendo la opción del método de interpolación (más cercano, bilineal, etc.). Sé que hay
scipy.misc.imresize
que hace exactamente esto envolviendo la función de cambio de tamaño de PIL. El único problema es que, dado que usa PIL, la matriz numpy debe ajustarse a los formatos de imagen, lo que me da un máximo de 4 canales de "color".
Quiero poder cambiar el tamaño de las imágenes arbitrarias, con cualquier cantidad de canales de "color". Me preguntaba si hay una manera simple de hacer esto en scipy / numpy, o si tengo que hacer mi propio.
Tengo dos ideas sobre cómo prepararme yo mismo:
- una función que ejecuta
scipy.misc.imresize
en cada canal por separado - crear el mío usando
scipy.ndimage.interpolation.affine_transform
El primero probablemente sea lento para datos grandes, y el segundo no parece ofrecer ningún otro método de interpolación excepto splines.
¿Has mirado Scikit-image ? Sus funciones transform.pyramid_*
pueden ser útiles para usted.
Recientemente he encontrado un problema con scipy.ndimage.interpolation.zoom, que he enviado como informe de error: https://github.com/scipy/scipy/issues/3203
Como alternativa (o al menos para mí), he descubierto que skimage.transform.resize de scikit-image funciona correctamente: http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.resize
Sin embargo, funciona de manera diferente a la interpolación.zoom de scipy: en lugar de especificar un mutliplier, especifique la forma de salida que desea. Esto funciona para imágenes 2D y 3D.
Para solo imágenes 2D, puede usar transform.rescale y especificar un multiplicador o escala como lo haría con interpolation.zoom.
Según su descripción, desea scipy.ndimage.zoom
.
La interpolación bilineal sería order=1
, la más cercana es order=0
y la cúbica es la predeterminada ( order=3
).
zoom
es específicamente para datos de cuadrícula regular que desea volver a muestrear a una nueva resolución.
Como un ejemplo rápido:
import numpy as np
import scipy.ndimage
x = np.arange(9).reshape(3,3)
print ''Original array:''
print x
print ''Resampled by a factor of 2 with nearest interpolation:''
print scipy.ndimage.zoom(x, 2, order=0)
print ''Resampled by a factor of 2 with bilinear interpolation:''
print scipy.ndimage.zoom(x, 2, order=1)
print ''Resampled by a factor of 2 with cubic interpolation:''
print scipy.ndimage.zoom(x, 2, order=3)
Y el resultado:
Original array:
[[0 1 2]
[3 4 5]
[6 7 8]]
Resampled by a factor of 2 with nearest interpolation:
[[0 0 1 1 2 2]
[0 0 1 1 2 2]
[3 3 4 4 5 5]
[3 3 4 4 5 5]
[6 6 7 7 8 8]
[6 6 7 7 8 8]]
Resampled by a factor of 2 with bilinear interpolation:
[[0 0 1 1 2 2]
[1 2 2 2 3 3]
[2 3 3 4 4 4]
[4 4 4 5 5 6]
[5 5 6 6 6 7]
[6 6 7 7 8 8]]
Resampled by a factor of 2 with cubic interpolation:
[[0 0 1 1 2 2]
[1 1 1 2 2 3]
[2 2 3 3 4 4]
[4 4 5 5 6 6]
[5 6 6 7 7 7]
[6 6 7 7 8 8]]
Editar: Como señaló Matt S., hay un par de advertencias para hacer zoom en las imágenes de múltiples bandas. Estoy copiando la siguiente porción casi textualmente de una de mis respuestas anteriores :
El zoom también funciona para matrices 3D (y nD). Sin embargo, tenga en cuenta que si hace zoom por 2x, por ejemplo, hará zoom en todos los ejes.
data = np.arange(27).reshape(3,3,3)
print ''Original:/n'', data
print ''Zoomed by 2x gives an array of shape:'', ndimage.zoom(data, 2).shape
Esto produce:
Original:
[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[18 19 20]
[21 22 23]
[24 25 26]]]
Zoomed by 2x gives an array of shape: (6, 6, 6)
En el caso de imágenes multibanda, generalmente no desea interpolar a lo largo del eje "z", creando nuevas bandas.
Si tiene algo así como una imagen RGB de 3 bandas que desea ampliar, puede hacerlo especificando una secuencia de tuplas como factor de zoom:
print ''Zoomed by 2x along the last two axes:''
print ndimage.zoom(data, (1, 2, 2))
Esto produce:
Zoomed by 2x along the last two axes:
[[[ 0 0 1 1 2 2]
[ 1 1 1 2 2 3]
[ 2 2 3 3 4 4]
[ 4 4 5 5 6 6]
[ 5 6 6 7 7 7]
[ 6 6 7 7 8 8]]
[[ 9 9 10 10 11 11]
[10 10 10 11 11 12]
[11 11 12 12 13 13]
[13 13 14 14 15 15]
[14 15 15 16 16 16]
[15 15 16 16 17 17]]
[[18 18 19 19 20 20]
[19 19 19 20 20 21]
[20 20 21 21 22 22]
[22 22 23 23 24 24]
[23 24 24 25 25 25]
[24 24 25 25 26 26]]]
Si desea volver a muestrear, entonces debe consultar el libro de cocina de rebinning para rebinning . En particular, la función de congrid
definida al final soportará el rebinning o la interpolación (equivalente a la función en IDL con el mismo nombre). Esta debería ser la opción más rápida si no quiere la interpolación.
También puede usar directamente scipy.ndimage.map_coordinates
, que hará una interpolación spline para cualquier tipo de remuestreo (incluidas las grillas no estructuradas). Encuentro map_coordinates para ser lento para matrices grandes (nx, ny> 200).
Para la interpolación en cuadrículas estructuradas, tiendo a usar scipy.interpolate.RectBivariateSpline
. Puede elegir el orden de la spline (lineal, cuadrático, cúbico, etc.) e incluso independientemente para cada eje. Un ejemplo:
import scipy.interpolate as interp
f = interp.RectBivariateSpline(x, y, im, kx=1, ky=1)
new_im = f(new_x, new_y)
En este caso, está haciendo una interpolación bi-lineal (kx = ky = 1)
. El tipo de interpolación "más cercano" no es compatible, ya que todo lo que hace es una interpolación spline sobre una malla rectangular. Tampoco es el método más rápido.
Si buscas interpolación bi-lineal o bicúbica, generalmente es mucho más rápido hacer dos interpolaciones 1D:
f = interp.interp1d(y, im, kind=''linear'')
temp = f(new_y)
f = interp.interp1d(x, temp.T, kind=''linear'')
new_im = f(new_x).T
También puede usar kind=''nearest''
, pero en ese caso deshacerse de las matrices transversales.