Ich suche nach einer Möglichkeit, ein Numpy-Array, das Bilddaten in einer neuen Größe darstellt, neu abzutasten, wobei ich vorzugsweise die Interpolationsmethode (am nächsten, bilinear usw.) auswählen kann. Ich weiß, dass es gibt
scipy.misc.imresize
Dies geschieht genau, indem die Größenänderungsfunktion von PIL umschlossen wird. 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, die Größe beliebiger Bilder mit einer beliebigen Anzahl von "Farb" -Kanälen zu ändern. 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 selbst eine zusammenstellen kann:
- Eine Funktion, die
scipy.misc.imresize
auf jedem Kanal separat ausgeführt wird - erstelle meine eigene mit
scipy.ndimage.interpolation.affine_transform
Die erste wäre wahrscheinlich langsam für große Datenmengen, und die zweite scheint keine andere Interpolationsmethode als Splines zu bieten.
quelle
scipy.interpolate.griddata
? Linkinterp2d
, aber es ist nicht nur extrem fehlerhaft, sondern ich bin mir nicht einmal sicher, ob es die Daten korrekt herunterrechnet.Antworten:
Basierend auf Ihrer Beschreibung möchten Sie
scipy.ndimage.zoom
.Bilineare Interpolation wäre
order=1
, am nächsten istorder=0
, und kubisch ist die Standardeinstellung (order=3
).zoom
ist speziell für regelmäßig gerasterte Daten gedacht, die Sie auf eine neue Auflösung neu abtasten möchten.Als schnelles 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]]
Bearbeiten: Wie Matt S. betonte, gibt es einige Einschränkungen beim Zoomen von Multiband-Bildern. Ich kopiere den folgenden Teil fast wörtlich aus einer meiner früheren Antworten :
Das Zoomen funktioniert auch für 3D- (und nD-) Arrays. Beachten Sie jedoch, dass Sie, wenn Sie beispielsweise um das Zweifache zoomen, entlang aller 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 Mehrbandbildern 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]]]
quelle
scipy.ndimage.zoom(data, (3,3,1))
Zum Beispiel, um ein 3D-Array entlang der x- und y-Dimensionen um den Faktor 3 zu zoomen, während die dritte Dimension in Ruhe gelassen wird.scipy.ndimage.zoom
tatsächlich anders mit den Kanten der Matrix umscipy.misc.imresize
? Beim Zoomen mit einem Wert10
der Seiten sind nur 5 Werte breit (mit istimresize
es10
).Wenn Sie ein Resample durchführen möchten, sollten Sie sich Scipys Kochbuch ansehen, um es erneut zu erstellen . Insbesondere unterstützt die
congrid
am Ende definierte Funktion das Rebinning oder die Interpolation (entspricht der Funktion in IDL mit demselben Namen). Dies sollte die schnellste Option sein, wenn Sie keine Interpolation wünschen.Sie können auch direkt verwenden
scipy.ndimage.map_coordinates
, wodurch eine Spline-Interpolation für jede Art von Resampling (einschließlich unstrukturierter Gitter) durchgeführt wird. Ich finde map_coordinates für große Arrays langsam (nx, ny> 200).Für die Interpolation auf strukturierten Gittern verwende ich eher
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ächste" Art der Interpolation wird nicht unterstützt, da dies lediglich eine Spline-Interpolation über ein rechteckiges Netz ist. Es ist auch nicht die schnellste Methode.Wenn Sie nach einer bi-linearen oder bi-kubischen 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 verwenden
kind='nearest'
, aber in diesem Fall die Querfelder entfernen.quelle
Hast du dir Scikit-image angesehen ? Seine
transform.pyramid_*
Funktionen könnten für Sie nützlich sein.quelle
Ich habe kürzlich ein Problem mit scipy.ndimage.interpolation.zoom gefunden, das ich als Fehlerbericht eingereicht habe: https://github.com/scipy/scipy/issues/3203
Als Alternative (oder zumindest für mich) habe ich festgestellt, dass skimage.transform.resize von scikit-image ordnungsgemäß funktioniert: http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage .transform.resize
Es 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 Skalierung wie bei interpolation.zoom angeben.
quelle
zoom
. Ich werde Skimageresize
im Auge behalten, danke!resize
die Größe der Werte im Array (Bild) bei? Ich habe es gerade zum ersten Mal versucht, und für ein 16-Bit-Graustufenbild war dies nicht der Fall. Das ursprüngliche Array hatte einen Median von ~ 32000 und die Größe der Bilder hat einen Median zwischen 0 und 1.Sie können verwenden
interpolate.interp2d
.Wenn Sie beispielsweise ein Bild betrachten, das durch ein Numpy-Array dargestellt wird
arr
, können Sie die Größe wie folgt auf eine beliebige Höhe und Breite ändern:W, H = arr.shape[:2] new_W, new_H = (600,300) xrange = lambda x: np.linspace(0, 1, x) f = interp2d(xrange(W), xrange(H), arr, kind="linear") new_arr = f(xrange(new_W), xrange(new_H))
Wenn Ihr Bild mehrere Kanäle hat, müssen Sie natürlich die Interpolation für jeden Kanal durchführen.
quelle
Diese Lösung skaliert X und Y des zugeführten 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.
quelle