Ich bin auf der Suche nach einem Resample für ein Numpy-Array, das Bilddaten in einer neuen Größe darstellt, vorzugsweise mit der Wahl der Interpolationsmethode (am nächsten, bilinear usw.). Ich weiß, dass es gibt
scipy.misc.imresize
dies geschieht genau durch Umbrechen der PIL-Größenänderungsfunktion. Das einzige Problem ist, dass das Numpy-Array, da es PIL verwendet, den Bildformaten entsprechen muss, sodass ich maximal 4 "Farb" -Kanäle habe.
Ich möchte in der Lage sein, beliebige Bilder mit einer beliebigen Anzahl von "Farb" -Kanälen in der Größe anzupassen. Ich habe mich gefragt, ob es einen einfachen Weg gibt, dies in scipy/numpy zu tun, oder ob ich meinen eigenen rollen muss.
Ich habe zwei Ideen, wie ich mir eine zusammenstellen kann:
scipy.misc.imresize
auf jedem Kanal separatscipy.ndimage.interpolation.affine_transform
Die erste Methode ist für große Datenmengen wahrscheinlich langsam, und die zweite Methode bietet keine andere Interpolationsmethode als Splines.
Basierend auf Ihrer Beschreibung möchten Sie scipy.ndimage.zoom
.
Bilineare Interpolation wäre order=1
, am nächsten ist order=0
und kubisch ist die Standardeinstellung (order=3
).
zoom
ist speziell für Daten mit regelmäßigem Raster gedacht, für die Sie eine neue Auflösung festlegen möchten.
Ein kurzes Beispiel:
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)
Und das Ergebnis:
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]]
Edit: Wie Matt S. ausführte, gibt es einige Einschränkungen beim Zoomen von Multiband-Bildern. Ich kopiere den folgenden Teil fast wörtlich aus einem meiner frühere Antworten :
Das Zoomen funktioniert auch für 3D-Arrays (und nD-Arrays). Beachten Sie jedoch, dass Sie, wenn Sie beispielsweise um das Zweifache zoomen, entlang all Achsen zoomen.
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
Dies ergibt:
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)
Bei Bildern mit mehreren Bändern möchten Sie normalerweise nicht entlang der "z" -Achse interpolieren, um neue Bänder zu erstellen.
Wenn Sie so etwas wie ein 3-Band-RGB-Bild haben, das Sie zoomen möchten, können Sie dies tun, indem Sie eine Folge von Tupeln als Zoomfaktor angeben:
print 'Zoomed by 2x along the last two axes:'
print ndimage.zoom(data, (1, 2, 2))
Dies ergibt:
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]]]
Wenn Sie ein Resample erstellen möchten, sollten Sie in Scipys Kochbuch nach Rebinning suchen. Insbesondere die am Ende definierte Funktion congrid
unterstützt Rebinning oder Interpolation (entspricht der gleichnamigen Funktion in IDL). Dies sollte die schnellste Option sein, wenn Sie keine Interpolation wünschen.
Sie können auch direkt scipy.ndimage.map_coordinates
verwenden, um eine Spline-Interpolation für jede Art von Resampling (einschließlich unstrukturierter Gitter) durchzuführen. Ich finde map_coordinates langsam für große Arrays (nx, ny> 200).
Für die Interpolation auf strukturierten Gittern verwende ich normalerweise scipy.interpolate.RectBivariateSpline
. Sie können die Reihenfolge des Splines (linear, quadratisch, kubisch usw.) und sogar unabhängig für jede Achse auswählen. Ein Beispiel:
import scipy.interpolate as interp
f = interp.RectBivariateSpline(x, y, im, kx=1, ky=1)
new_im = f(new_x, new_y)
In diesem Fall führen Sie eine bi-lineare Interpolation durch (kx = ky = 1)
. Die nächstgelegene Art der Interpolation wird nicht unterstützt, da dies nur eine Spline-Interpolation über ein Rechtecknetz ist. Es ist auch nicht die schnellste Methode.
Wenn Sie nach bi-linearer oder bikubischer Interpolation suchen, ist es im Allgemeinen viel schneller, zwei 1D-Interpolationen durchzuführen:
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
Sie können auch kind='nearest'
Verwenden, in diesem Fall jedoch die Quer-Arrays entfernen.
Hast du dir Scikit-Bild angesehen? Es ist transform.pyramid_*
Funktionen könnten für Sie nützlich sein.
Ich habe kürzlich ein Problem mit scipy.ndimage.interpolation.zoom gefunden, das ich als Fehlerbericht eingereicht habe: https://github.com/scipy/scipy/issues/32
Als Alternative (oder zumindest für mich) habe ich festgestellt, dass die Datei skimage.transform.resize von scikit-image korrekt funktioniert: http://scikit-image.org/docs/dev/api/skimage.transform) .html # skimage.transform.resize
Dies funktioniert jedoch anders als die interpolation.zoom von scipy - anstatt einen Multiplikator anzugeben, geben Sie die gewünschte Ausgabeform an. Dies funktioniert für 2D- und 3D-Bilder.
Für nur 2D-Bilder können Sie transform.rescale verwenden und einen Multiplikator oder eine Skala wie bei interpolation.zoom angeben.
Diese Lösung skaliert X und Y des eingespeisten Bildes, ohne die RGB-Kanäle zu beeinflussen:
import numpy as np
import scipy.ndimage
matplotlib.pyplot.imshow(scipy.ndimage.zoom(image_np_array, zoom = (7,7,1), order = 1))
Hoffe das ist nützlich.