2017-06-13 1 views
2

Ich habe ein 3-dimensionales, numpiges Array mit der Form Nx64x64. Ich möchte es über die Dimensionen 1 und 2 downsampeln, indem ich den Mittelwert nehme, was zu einem neuen Array mit der Form Nx8x8 führt.Was ist der beste Weg, um ein numpy Array downsampling?

Ich habe ein paar funktionierende Implementierungen, aber ich habe das Gefühl, dass es einen besseren Weg geben muss.

Ich versuchte zunächst zu verwenden np.split:

def subsample(inparray, n): 
    inp = inparray.copy() 
    res = np.moveaxis(np.array(np.hsplit(inp, inp.shape[1]/n)), 1, 0) 
    res = np.moveaxis(np.array(np.split(res, inp.shape[2]/n, axis=3)), 1, 0) 
    res = np.mean(res, axis=(3,4)) 
    return res 

Ich habe auch versucht Ebene Indizierung:

def subsample2(inparray, n): 
    res = np.zeros((inparray.shape[0], n, n)) 
    lin = np.linspace(0, inparray.shape[1], n+1).astype(int) 
    bounds = np.stack((lin[:-1], lin[1:]), axis=-1) 

    for i, b in enumerate(bounds): 
     for j, b2 in enumerate(bounds): 
      res[:, i, j] = np.mean(inparray[:, b[0]:b[1], b2[0]:b2[1]], axis=(1,2)) 
    return res 

ich über die Verwendung von itertools.groupby gewundert hatte, aber es sah auch recht kompliziert.

Kennt jemand eine saubere Lösung?

Antwort

2

Reshape die letzten beiden Achsen in zwei weitere, wie aufzuteilen, dass die letztere Split diejenigen sind von Längen gleich der Blockgrößen, die uns eine 5D Array und dann mean verwenden entlang der dritten und fünften Achsen -

BSZ = (8,8) 
m,n = a.shape[1:] 
out = a.reshape(N,m//BSZ[0],BSZ[0],n//BSZ[1],BSZ[1]).mean(axis=(2,4)) 

Probenlauf auf kleinere Array mit kleineren Blockgröße (2,2) -

1) Eingänge:

In [271]: N = 2 

In [272]: a = np.random.randint(0,9,(N,6,6)) 

In [273]: a 
Out[273]: 
array([[[3, 1, 8, 7, 8, 2], 
     [0, 6, 2, 6, 8, 2], 
     [2, 1, 1, 0, 0, 1], 
     [8, 3, 0, 2, 8, 0], 
     [4, 7, 2, 6, 6, 7], 
     [5, 5, 1, 7, 2, 7]], 

     [[0, 0, 8, 1, 7, 6], 
     [8, 6, 5, 8, 4, 0], 
     [0, 3, 7, 7, 6, 1], 
     [7, 1, 7, 6, 3, 6], 
     [7, 6, 4, 6, 4, 5], 
     [4, 2, 0, 2, 6, 2]]]) 

2) Holen wenige Ausgangswerte für die manuelle Überprüfung:

In [274]: a[0,:2,:2].mean() 
Out[274]: 2.5 

In [275]: a[0,:2,2:4].mean() 
Out[275]: 5.75 

In [276]: a[0,:2,4:6].mean() 
Out[276]: 5.0 

In [277]: a[0,2:4,:2].mean() 
Out[277]: 3.5 

3) vorgeschlagene Ansatz verwenden und manuell überprüfen:

In [278]: BSZ = (2,2) 

In [279]: m,n = a.shape[1:] 

In [280]: a.reshape(N,m//BSZ[0],BSZ[0],n//BSZ[1],BSZ[1]).mean(axis=(2,4)) 
Out[280]: 
array([[[ 2.5 , 5.75, 5. ], 
     [ 3.5 , 0.75, 2.25], 
     [ 5.25, 4. , 5.5 ]], 

     [[ 3.5 , 5.5 , 4.25], 
     [ 2.75, 6.75, 4. ], 
     [ 4.75, 3. , 4.25]]]) 
0

Sie zoom - scipy.ndimage verwenden können. Mit dieser Lib können Sie entlang einer Ihrer 3 Achsen zoomen.

Verwandte Themen