Dies ist eine Fortsetzung von Umgang mit transparenten Bildern mit OpenCV-Making Sprites Dance-.
Es ist aufregend, das Sprite zu drehen. Ich erinnere mich an Namcos SYSTEM II-Board. Angriff oder Befehl. Ich habe Namco Museum VOL.4 gekauft, bevor ich die PlayStation selbst gekauft habe.
In OpenCV können Sie das Bild mit cv2.rotate ()
in 90-Grad-Schritten drehen, es gibt jedoch keine Funktion, um es in einem beliebigen Winkel zu drehen. Es gibt eine erweiterte Funktion, verwenden Sie sie also.
Die Affintransformation ist ein Mapping, das primäre Transformationen wie Rotation und Skalierung mit paralleler Bewegung kombiniert. Zusamenfassend
\begin{pmatrix}
x' \\
y'
\end{pmatrix}
=
\begin{pmatrix}
a & b \\
d & e
\end{pmatrix}
\begin{pmatrix}
x \\
y
\end{pmatrix}
+
\begin{pmatrix}
c \\
f
\end{pmatrix}
Es ist eine Bekehrung. Es ist schwer, in dieser Form zu programmieren
\begin{pmatrix}
x' \\
y' \\
1
\end{pmatrix}
=
\begin{pmatrix}
a & b & c \\
d & e & f \\
0 & 0 & 1
\end{pmatrix}
\begin{pmatrix}
x \\
y \\
1
\end{pmatrix}
Ich werde es ausdrücken als. Der Boden ist etwas unangenehm, aber es gibt nur eine Gleichheit von "1 = 1".
Dies
\begin{pmatrix}
a & b & c \\
d & e & f \\
\end{pmatrix}
Wird definiert und auf die Funktion cv2.warpAffine ()
angewendet.
Achten Sie jedoch beim Drehen des Bildes darauf
\begin{pmatrix}
cosθ & -sinθ & 0 \\
sinθ & cosθ & 0 \\
\end{pmatrix}
Es besteht keine Notwendigkeit zu berechnen. Sie können die von cv2.getRotationMatrix2D ()
erhaltene Matrix verwenden.
Fügen wir die Parallelbewegung selbst hinzu.
--src Originalbild.
Ich frage mich, wie die Konvertierungsmatrix aussieht.
Quelle 1
import cv2
angle = 30 # degrees
M = cv2.getRotationMatrix2D((0,0), angle, 1)
print (M)
print (M.shape)
print (M.dtype)
Ergebnis 1
[[ 0.8660254 0.5 0. ]
[-0.5 0.8660254 0. ]]
(2, 3)
float64
cos30 Grad = √3 / 2 = 0,8660254 ... Genau das ist also die Rotationsmatrix ...? Die Minusposition ist anders, oder? Im Gegensatz zur in der Mathematik verwendeten xy-Ebene entspricht die Berechnung offenbar einem Koordinatensystem, bei dem der Boden positiv ist.
Lassen Sie uns das Bild also tatsächlich damit konvertieren.
Quelle 2
import cv2
filename = "hoge.png "
img = cv2.imread(filename)
h, w = img.shape[:2]
center = (140,60)
angle = 0
while True:
angle = (angle + 10) % 360
M = cv2.getRotationMatrix2D(center, angle, 1)
img_rot = cv2.warpAffine(img, M, (w, h))
cv2.imshow(filename, img_rot)
key = cv2.waitKey(100) & 0xFF
if key == ord("q"):
break
cv2.destroyAllWindows()
Das Ergebnis ist dies.
Das Originalbild | Ergebnis |
---|---|
Ich verstehe den Drehwinkel und den Drehpunkt, aber ich möchte sagen: "Moment mal, das Bild ragt überhaupt heraus."
Wie vermeide ich es herauszustechen? Ich werde berechnen, was zu tun ist.
Wenn ein Rechteck (rot), dessen zwei Seiten w und h sind, um einen Winkel a geneigt ist, ist die Größe des umschreibenden Vierecks (blau)
python
rot_w = w*cos(a) + h*sin(a)
rot_h = w*sin(a) + h*cos(a)
Wird sein. Wenn die Temperatur von 0 bis 90 Grad abweicht, sind Sinus und Cosinus negativ, daher muss jeder Term ein absoluter Wert sein. Oh, ich verstehe endlich. Diese Formel erschien in dem später beschriebenen Artikel der Vorfahren, und ich fragte mich, was sie von der Rotationsmatrix unterschied.
Sie können die Position also parallel verschieben, sodass sie in dieses blaue Rechteck passt. Da (0,0) das Rotationszentrum ist, denken wir basierend auf der Bildmitte.
Quelle 3
import cv2
import numpy as np
filename = "hoge.png "
img = cv2.imread(filename)
h, w = img.shape[:2]
angle = 0
while True:
angle = (angle + 10) % 360
a = np.radians(angle)
w_rot = int(np.round(w*abs(np.cos(a)) + h*abs(np.sin(a))))
h_rot = int(np.round(w*abs(np.sin(a)) + h*abs(np.cos(a))))
M = cv2.getRotationMatrix2D((w/2,h/2), angle, 1)
M[0][2] += -w/2 + w_rot/2
M[1][2] += -h/2 + h_rot/2
img_rot = cv2.warpAffine(img, M, (w_rot,h_rot))
cv2.imshow(filename, img_rot)
key = cv2.waitKey(100) & 0xFF
if key == ord("q"):
break
cv2.destroyAllWindows()
Das Ergebnis ist dies. Das Bild ragt nicht mehr aus dem Fenster heraus, aber es kann nicht geholfen werden, da die Animation auf der Einschränkung basiert, dass die Fensterposition (obere linke Position des Bildes) üblich ist.
Um die Mitte festzulegen und zu drehen, damit das erstellte Bild nicht wild wird, sollte die Größe der Leinwand, auf der das gedrehte Bild gezeichnet wird, im Voraus festgelegt werden. Die Größe des Campus zu finden ist nicht schwierig. Von dem Abstand zwischen dem Drehpunkt und den vier Ecken entspricht der größte dem Radius. Die Größe der Leinwand ist doppelt so groß.
Wahrscheinlich in gutem Zustand, drückt die folgende Quelle die Formel zum Ermitteln des Radius in nur einer Zeile aus. Jetzt ist es schwer zu verstehen, welche Art von Berechnung ich mache. Es ist nicht gut, sehr geschickt zu laufen.
Quelle 4
import cv2
import numpy as np
filename = "hoge.png "
img = cv2.imread(filename)
h, w = img.shape[:2]
xc, yc = 140, 60 #Rotationszentrum
angle = 0
#Finden Sie den Maximalwert des Abstands zwischen dem Drehpunkt und den vier Ecken
pts = np.array([(0,0), (w,0), (w,h), (0,h)])
ctr = np.array([(xc,yc)])
r = np.sqrt(max(np.sum((pts-ctr)**2, axis=1)))
winH, winW = int(2*r), int(2*r)
while True:
angle = (angle + 10) % 360
M = cv2.getRotationMatrix2D((xc,yc), angle, 1)
M[0][2] += r - xc
M[1][2] += r - yc
imgRot = cv2.warpAffine(img, M, (winW,winH))
cv2.imshow("", imgRot)
key = cv2.waitKey(100) & 0xFF
if key == ord("q"):
break
cv2.destroyAllWindows()
Das Ergebnis ist dies.
Fügen Sie die obige Verarbeitung zur Sprite-Funktion von [previous] hinzu (https://qiita.com/mo256man/items/f7524dd34718a01fb3df). Es wäre vielleicht besser gewesen, mit "math.ceil ()" statt mit "int ()" aufzurunden.
Quelle 5
import cv2
import numpy as np
def putSprite_mask2(back, front4, pos, angle=0, center=(0,0)):
x, y = pos
xc, yc = center
fh, fw = front4.shape[:2]
bh, bw = back.shape[:2]
#Finden Sie den Maximalwert des Abstands zwischen dem Drehpunkt und den vier Ecken
pts = np.array([(0,0), (fw,0), (fw,fh), (0,fh)])
ctr = np.array([(xc,yc)])
r = int(np.sqrt(max(np.sum((pts-ctr)**2, axis=1))))
#Drehen
M = cv2.getRotationMatrix2D((xc,yc), angle, 1)
M[0][2] += r - xc
M[1][2] += r - yc
imgRot = cv2.warpAffine(front4, M, (2*r,2*r)) #Externes Viereck mit gedrehtem Bild
#Tun Sie nichts, wenn sich das gesamte äußere Quadrat außerhalb des Hintergrundbilds befindet
x0, y0 = x+xc-r, y+yc-r
if not ((-2*r < x0 < bw) and (-2*r < y0 < bh)) :
return back
#Holen Sie sich nur das Hintergrundbild des äußeren Quadrats
x1, y1 = max(x0, 0), max(y0, 0)
x2, y2 = min(x0+2*r, bw), min(y0+2*r, bh)
imgRot = imgRot[y1-y0:y2-y0, x1-x0:x2-x0]
#Kombinieren Sie das umschreibende Viereck und den Hintergrund mit der Maskenmethode
front_roi = imgRot[:, :, :3]
mask1 = imgRot[:, :, 3]
mask_roi = 255 - cv2.merge((mask1, mask1, mask1))
roi = back[y1:y2, x1:x2]
tmp = cv2.bitwise_and(roi, mask_roi)
tmp = cv2.bitwise_or(tmp, front_roi)
back[y1:y2, x1:x2] = tmp
return back
if __name__ == "__main__":
filename_back = "space.jpg "
filename_front = "uchuhikoushi.png "
img_back = cv2.imread(filename_back)
img_front = cv2.imread(filename_front, -1)
pos = [(0, 50), (300,200), (400,400), (500,-50), (-100,1000)] #Obere linke Koordinate, um das Bild zu platzieren
xc, yc = 140, 60 #Drehpunkt des Vordergrundbildes
angle = 0
while True:
back = img_back.copy()
for x,y in pos:
img = putSprite_mask2(back, img_front, (x,y), angle, (xc,yc))
#Stellen Sie sicher, dass es korrekt dargestellt wird (nicht erforderlich).
cv2.circle(img, (x,y), 5, (0,255,0), -1) #Markieren Sie oben links im Vordergrundbild
cv2.circle(img, (x+xc,y+yc), 5, (0,0,255), -1) #Markieren Sie in der Mitte der Drehung
cv2.putText(img, f"angle={angle}", (10,440), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
cv2.imshow("putSprite_mask2", img)
key = cv2.waitKey(0) & 0xFF
if key == ord("q"):
break
angle = (angle + 30) % 360
cv2.destroyAllWindows()
Es ist fertig.
Eigentlich wollte ich das gleiche Verhalten erreichen, indem ich das umschreibende Viereck minimierte und die oberen linken Koordinaten fein kontrollierte, aber ich konnte die Probleme mit Zahlen und Matrizen, dh dem Mathematikniveau der High School, nicht gut lösen. Es gab keine. Eh? Warum stellst du dich jetzt nicht in der High School auf? !!
Erstellt und speichert ein Bild, das um den angegebenen Winkel um die Mitte des Originalbilds gedreht wird. So verhindern Sie, dass der hervorstehende Teil durch Drehen des Bildes von opencv abgeschnitten wird Affin-Konvertierung vollständig verstehen
Recommended Posts