Wie kann ich mit scipy.ndimage.interpolation.affine_transform um ein Bild zu drehen, über seine Mitte?
Ich bin verwirrt durch die API zu scipy.ndimage.interpolation.affine_transform
. Und die Beurteilung durch dieses Problem ich bin nicht der einzige. Ich bin eigentlich zu wollen, mehr tun, interessante Dinge mit affine_transform
als nur das Bild drehen, aber eine Drehung machen würde für den Anfang. (Und ja, ich bin mir wohl bewusst,scipy.ndimage.interpolation.drehen
, aber herauszufinden, wie zu fahren affine_transform
ist das, was mich hier interessiert).
Wenn ich will, das zu tun diese Art der Sache, die in Systemen wie OpenGL, ich bin der Meinung in Bezug auf die Berechnung der Transformation, die für eine 2x2-drehmatrix R
über ein Zentrum c
, und deshalb denken Punkte p
transformiert (p-c)R+c
= pR+c-cR
gibt, die eine c-cR
Begriff verwendet werden, da die übersetzung Bestandteil einer Transformation. Jedoch, nach der Ausgabe oben, scipy ist affine_transform
bedeutet "offset ersten" also, wir müssen eigentlich zum berechnen eines offset - s
so dass (p-c)R+c=(p+s)R
die mit ein bisschen umbauen gibt s=(c-cR)R'
wo R'
ist die inverse von R
.
Wenn ich stecken Sie diesen in einem ipython notebook (pylab-Modus; code unten vielleicht braucht einige zusätzliche Importe):
img=scipy.misc.lena()
#imshow(img,cmap=cm.gray);show()
centre=0.5*array(img.shape)
a=15.0*pi/180.0
rot=array([[cos(a),sin(a)],[-sin(a),cos(a)]])
offset=(centre-centre.dot(rot)).dot(linalg.inv(rot))
rotimg=scipy.ndimage.interpolation.affine_transform(
img,rot,order=2,offset=offset,cval=0.0,output=float32
)
imshow(rotimg,cmap=cm.gray);show()
Bekomme ich
welche leider nicht gedreht, der über das Zentrum.
Also, was ist der trick, ich bin hier noch fehlt?
- Gerade dabei einige quick & dirty Tests habe ich bemerkt, dass unter den negativen Wert der Versatz scheint sich zu drehen über das Zentrum.
- Aha! Ja, sehr gut, bestätigt sich hier. Es scheint, mein Modell von scipy system sollte
(p-s)R
. Stellen, dass als Antwort und ich würde es akzeptieren.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gerade dabei einige quick & dirty Tests habe ich bemerkt, dass unter den negativen Wert der Versatz scheint sich zu drehen über das Zentrum.
Einmal treddy die Antwort, hab mir ein arbeiten Grundlinie schaffte ich es, ein besser funktionierendes Modell der
affine_transform
. Es ist eigentlich nicht so seltsam, wie die Frage verknüpft, in der ursprünglichen Frage Hinweise.Grundsätzlich ist jeder Punkt (Koordinate)
p
in das Bild verwandelt sich zupT+s
woT
unds
sind die matrix-und offset an die Funktion übergeben.Wenn wir also wollen, Punkt
c_out
in der Ausgabe zugeordnet werden, und entnahm vonc_in
von der input-Bild mit rotationR
und (möglicherweise richtungsabhängigen) SkalierungS
wir müssenpT+s = (p-c_out)RS+c_in
werden kann, angeordnet werden, um die Ausbeutes = (c_int-c_out)T
(mitT=RS
).Aus irgendeinem Grund habe ich dann übergeben müssen
transform.T
zuaffine_transform
aber ich werde nicht zu befürchten, dass zu viel; wahrscheinlich etwas mit der Zeile-Koordinaten und Transformationen auf der rechten Seite (angenommen oben) vs-Spalte-Koordinaten und Transformationen auf der linken Seite.So, hier ist ein einfacher test, rotierende einen zentrierten Bild:
Hier ist es geändert für die verschiedenen Bildgrößen
Und hier eine version mit anisotropen Skalierung um einen Ausgleich für die anisotrope Auflösung des Bildes.
Basierend auf der Erkenntnis von @timday, dass
matrix
undoffset
definiert sind, im Ausgabe-Koordinatensystem, ich hätte folgende Lektüre die Frage, die passt mit standard-Notationen in der linearen algebra und erlaubt zu verstehen, die Skalierung von Bildern sowie. Ich benutze hierT.inv=T^-1
als pseudo-python-notation bedeutet die inverse einer matrix und*
bedeuten das Skalarprodukt.Für jeden Punkt
o
in der Ausgabe Bild,affine_transform
findet den entsprechenden Punkti
im input-Bildes alsi=T.inv*o+s
, womatrix=T.inv
ist die inverse 2x2 Transformationsmatrix, die man verwenden würde, um zu definieren, den nach vorne affine transformation undoffset=s
ist die übersetzung definiert in der Ausgabe von Koordinaten. Für eine Reine rotationT=R=[[cos,-sin],[sin,cos]]
, und in diesem speziellen Fallmatrix=T.inv=T.T
, das ist der Grund, warum @timday anwenden musste die Umsetzung noch (alternativ könnte man nur das negative Winkel).Wert für die offset -
s
zu finden ist genau so, wie beschrieben von @timday: wennc_in
positioniert werden soll, nachdem die affine transformation, beic_out
(z.B. die input-Zentrum platziert werden soll am Ausgang Zentrum), dannc_in=T.inv*c_out+s
oders=c_in-T.inv*c_out
(Hinweis: die herkömmliche mathematische Ordnung der matrix Produkt hier verwendeten matrix*Vektor, das ist der Grund, warum @timday, die den revers um, brauchte nicht eine Umsetzung an diesem Punkt in seinem code).Wenn man will, eine Skalierung
S
erste und dann eine DrehungR
gilt, dassT=R*S
und daherT.inv=S.inv*R.inv
(beachten Sie die umgekehrte Reihenfolge). Zum Beispiel, wenn jemand will, um das Bild doppelt so breit in die Spalten-Richtung ('x'), dannS=diag((1, 2))
daherS.inv=diag((1, 0.5))
.Wenn das Bild zuerst gedreht, dann gestreckt, die Bestellung des skalarprodukts muss Umgekehrt werden: