2017-12-24 2 views
2

Nicht ganz sicher, wie ich diese Frage Titel sollte. Aber wie kann ich einen Abschnitt eines numpigen Arrays erhalten, bei dem einige der Werte außerhalb der Grenze liegen?Füllen Sie einen Bereich außerhalb der Grenzen in einem numply Array

Siehe meinen einfachen Beispiel-Code unten:

def get_section(a, center, square_radius): 
    return a[center[0] - square_radius:center[0] + square_radius + 1, \ 
       center[1] - square_radius:center[1] + square_radius + 1] 



array = [ 
    [1, 2, 3, 4, 5, 6, 7, 8, 9], 
    [2, 3, 4, 5, 6, 7, 8, 9, 1], 
    [3, 4, 5, 0, 7, 8, 9, 1, 2], 
    [4, 5, 6, 7, 8, 9, 1, 2, 3], 
    [5, 0, 7, 8, 9, 4, 5, 6, 7], 
    [6, 7, 8, 9, 1, 2, 3, 4, 5] 
] 
a = np.asarray(array) 
square_radius = 2 


center = [2,3] 
print(get_section(a, center, square_radius)) 

center = [4,1] 
print(get_section(a, center, square_radius)) 

sagen, dass ich ein Array, aber ich mochte einen kleinen Teil davon bekommen, durch das Zentrum und den Radius des Abschnitts Angabe Ich mag würde .

Die erste wird ausdrucken:

[[2 3 4 5 6] 
[3 4 5 6 7] 
[4 5 0 7 8] 
[5 6 7 8 9] 
[0 7 8 9 4]] 

Welche genau das, was ich wollte. Der Einfachheit halber platzierte ich '0' in der Mitte der 2 identifizierten Beispiele.

Aber der zweite []

Für die zweite auszudrucken werde ich in den äußeren Werte mit -1 füllen möchten. So möchte ich es zurückgeben:

[[-1 3 4 5 0] 
[-1 4 5 6 7] 
[-1 5 0 7 8] 
[-1 6 7 8 9] 
[-1 -1 -1 -1 -1]] 

Wie kann ich dies in numpy tun?

Antwort

1

Endlich! Ich habe es mit np.pad getan. Ich bin mir nicht sicher, ob es ein besserer Weg, dies zu tun, da es ziemlich kompliziert, doch endete als, es funktioniert gut:

def get_section(a, center, square_radius): 
    tp = max(0, -(center[0] - square_radius)) 
    bp = max(0, -((a.shape[0]-center[0]-1) - square_radius)) 
    lp = max(0, -(center[1] - square_radius)) 
    rp = max(0, -((a.shape[1]-center[1]-1) - square_radius)) 
    a = np.pad(a, [[tp, bp], [lp, rp]], 'constant', constant_values=-1) 
    return a[center[0] - square_radius + tp:center[0] + square_radius + 1 + tp, \ 
       center[1] - square_radius + lp:center[1] + square_radius + 1 + lp] 

und Tests mit Ihren Beispielen:

>>> center = [2,3] 
>>> print(get_section(a, center, square_radius)) 
[[2 3 4 5 6] 
[3 4 5 6 7] 
[4 5 0 7 8] 
[5 6 7 8 9] 
[0 7 8 9 4]] 
>>> center = [4,1] 
>>> print(get_section(a, center, square_radius)) 
[[-1 3 4 5 0] 
[-1 4 5 6 7] 
[-1 5 0 7 8] 
[-1 6 7 8 9] 
[-1 -1 -1 -1 -1]] 

Warum?

Lassen Sie uns zunächst ein Array definieren die np.pad() Funktion zu testen:

>>> a 
array([[1, 2], 
     [3, 4]]) 

Und dann können wir eine schnelle Demonstration, tun, wie die Polsterung funktioniert, sollte es ziemlich selbsterklärend aus diesem Beispiel sein:

>>> np.pad(a, [[1, 2], [0, 3]], 'constant', constant_values=-1) 
array([[-1, -1, -1, -1, -1], 
     [ 1, 2, -1, -1, -1], 
     [ 3, 4, -1, -1, -1], 
     [-1, -1, -1, -1, -1], 
     [-1, -1, -1, -1, -1]]) 

so wissen wir jetzt, dass wir die -1s hinzufügen können, was Kante wir wollen, wir müssen heraus nur wenn wir das tun (das Quadrat überlappt die Kante wie im zweiten Beispiel) und, wenn ja, wie viele -1s müssen wir zu jeder Kante hinzufügen.

Diese Abstände sind am oberen Rand der Funktion definiert (tp, bp, ... für das obere Pad, das untere Pad ...), die wir durch Berechnungen berechnen.

Die Berechnungen sind im Grunde nur die Entfernung zwischen ihrer Kante und der Mitte und Subtrahieren der square_radius. Wenn wir es jedoch hier belassen, erhalten wir oft negative Abstände (falls der Radius kleiner als der Abstand zur Kante ist, um dies zu umgehen, benutzen wir einfach die max() Funktion mit 0 um das Padding zu machen Abstand nur positiv (Padding ist erforderlich) oder 0 (Padding ist an dieser Kante nicht erforderlich).

Dann mit all diesen definierten, rufen wir einfach die pad Funktion auf a mit diesen Werten.

Schließlich verwenden wir Ihre ursprüngliche "Quadrat-Extraktion" -Technik, um das Quadrat um die Mittelkoordinate zu erhalten. Der einzige Unterschied ist, dass wir hier alle Indizes durch die oberen und linken Pads ausgleichen müssen. Wir müssen dies so tun, als ob wir gerade einen linken 3er-Pad gepolstert hätten, dann wäre das, was ursprünglich ein Mittelpunkt von 4 gewesen wäre, nun ein Mittelpunkt von 1 (da die Indizierung von der Polsterkante aus beginnt). Um dies zu umgehen, versetzen wir die Indizes einfach zurück, indem wir die Padding-Unterschiede zu allen Indizes hinzufügen.

Hoffentlich haben Sie es jetzt!

+0

Ja, ich versuche zu verstehen, wie das funktioniert. Eine harte Zeit haben, lol. Ich lese ein paar Infos über np.pad und ich bekomme, wie es links/rechts und oben/unten aufträgt. Obwohl "a" scheint nicht zu ändern, wenn Sie "a" vor und nach der np.pad-Funktion drucken. Ich verstehe nicht wirklich, warum das Hinzufügen von TP und LP den Trick macht. Ich weiß, es funktioniert, versuche nur zu verstehen. Danke – user1179317

+0

@ user1179317 Ich habe eine Erklärung hinzugefügt. –

+0

Ich denke, ich habe es. Es ist fast so, wie Sie es sich vorstellen können, da die Werte, die zurückgegeben werden, die Werte innerhalb der Grenze des ursprünglichen Arrays sind, dann wird ein Padding für diesen Abschnitt hinzugefügt. War nur ein wenig verwirrend, denn wenn man dem Code folgt, scheint das Padding hinzugefügt worden zu sein, aber dann gibt man nur Werte zurück, die das hinzugefügte Padding ignorieren. – user1179317

Verwandte Themen