Numpy elementweise Mittelwertberechnung für 2D-Array

Oct 01 2020

Ich bin neu in Python und habe das Problem, den elementweisen Mittelwert in einem 2D-Numpy-Array zu berechnen. Ich habe im Web gesucht und nicht den optimalen Algorithmus für dieses Zeug gefunden.

So habe ich zum Beispiel dieses 2D-Array:

array = np.arange(20).reshape(4,5)
array

Out[7]: 
    array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14],
           [15, 16, 17, 18, 19]])

Ich möchte ein weiteres 2D-Numpy-Array erhalten, dessen Elemente den elementweisen Mittelwerten der vorherigen Matrix entsprechen. Außerdem ist es mein Ziel, die Ausgabematrix mit der gleichen Form wie die Eingabematrix zu haben.

Zum Beispiel habe ich einen 3 * 3-Block von Nachbarschaftselementen ausgewählt und mit dem ersten Element der Matrix (Null) begonnen:

Da es sich um ein Eckelement handelt, können wir den Mittelwert von 3 * 3 nicht berechnen. Ich gehe also davon aus, dass wir den Mittelwert von 2 * 2 berechnen können: (0 + 1 + 5 + 6): 4 = 3

Dann verschieben wir unseren 3 * 3-Block zum nächsten Element:

Berechnen Sie den Mittelwert auf die gleiche Weise usw. für die erste Zeile der Matrix. Zeile für Zeile, Element für Element verschieben:

Und berechnen Sie ihren Mittelwert auf die gleiche Weise: (0 + 1 + 2 + 5 + 6 + 7 + 10 + 11 + 12): 9 = 6

Und mach weiter so.

Können Sie mir bitte sagen, wie es möglich ist, die Matrix der mittleren Elemente mit der gleichen Form wie eine Eingabematrix zu erstellen? Soll ich es mit for-Schleife mit 2 Variablen betreiben? Und wie geht man mit 'Rand'-Elementen um, bei denen wir keinen vollständigen 3 * 3-Block des Nachbarelements anwenden können?

Wir werden uns sehr über Ihre Hilfe freuen!

PS Bei meinen Berechnungen gehe ich davon aus, dass für diesen Fall die endgültige Ergebnismatrix vorliegt:

Antworten

2 obchardon Oct 01 2020 at 17:47

Wenn die Verwendung scipyeine Option ist, können Sie eine 2D-Faltung verwenden :

import numpy as np
from scipy import signal

# Example input
x = np.array([[ 0,  1,  2,  3,  4],
              [ 5,  6,  7,  8,  9],
              [10, 11, 12, 13, 14],
              [15, 16, 17, 18, 19]])

# The moving window
y = np.ones((3,3))

# We convolve x with y and then we normalize those value with another convolution
#  |        first convolution        |/|              second convolution               |
r = signal.convolve2d(x,y,mode='same')/signal.convolve2d(np.ones(x.shape),y,mode='same')

Und es produziert:

array([[ 3. ,  3.5,  4.5,  5.5,  6. ],
       [ 5.5,  6. ,  7. ,  8. ,  8.5],
       [10.5, 11. , 12. , 13. , 13.5],
       [13. , 13.5, 14.5, 15.5, 16. ]])

wie es funktioniert ?

Die erste Faltung ergibt also die Summe des gewünschten Elements:

array([[ 12,  21,  27,  33,  24],
       [ 33,  54,  63,  72,  51],
       [ 63,  99, 108, 117,  81],
       [ 52,  81,  87,  93,  64]])

Und der zweite erzeugt die Überlegung (wie viele Elemente wurden an jeder Position summiert):

 array([[4., 6., 6., 6., 4.],
        [6., 9., 9., 9., 6.],
        [6., 9., 9., 9., 6.],
        [4., 6., 6., 6., 4.]])
1 Valdi_Bo Oct 01 2020 at 18:37

Sie können Ihre Aufgabe ausschließlich mit Numpy erledigen .

Definieren Sie die folgende Funktion, um den Mittelwert eines Elements und seiner Nachbarn zu berechnen:

def meanSurroud(arr, r, c):
    return np.mean(arr[max(r - 1, 0) : r + 2, max(c - 1, 0) : c + 2])

Rufen Sie es dann für jeden Index in Ihrem Quellarray auf und speichern Sie das Ergebnis in einem Zielarray:

result = np.empty_like(array, dtype=float)
for ind in np.ndindex(array.shape):
    result[ind] = meanSurroud(array, ind[0], ind[1])

Das Ergebnis ist:

array([[ 3. ,  3.5,  4.5,  5.5,  6. ],
       [ 5.5,  6. ,  7. ,  8. ,  8.5],
       [10.5, 11. , 12. , 13. , 13.5],
       [13. , 13.5, 14.5, 15.5, 16. ]])