[PYTHON] Sprites mit OpenCV drehen

Einführung

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.

Drehen Sie das Bild mit OpenCV

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.

Studieren der Affin-Konvertierung

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.

Erstellen Sie eine Rotationsmatrix cv.getRotationMatrix2D (Mitte, Winkel, Skalierung)

Fügen wir die Parallelbewegung selbst hinzu.

Affine Konvertierung von Bildern cv.warpAffine (src, M, dsize)

--src Originalbild.

Trainieren

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
uchuhikoushi_point.png uchuhikoushi_anim_0.gif

Ich verstehe den Drehwinkel und den Drehpunkt, aber ich möchte sagen: "Moment mal, das Bild ragt überhaupt heraus."

Überhang vermeiden

Wie vermeide ich es herauszustechen? Ich werde berechnen, was zu tun ist.

rot_cad_2.png

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.

uchuhikoushi_anim_1.gif

Geben Sie den Drehpunkt an

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ß. rot_cad_3.png

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. uchuhikoushi_anim_2.gif

Kombinieren Sie das gedrehte Bild mit dem Hintergrundbild

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. uchuhikoushi_anim_3.gif

Am Ende

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? !!

Referenzartikel

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

Sprites mit OpenCV drehen
Sprites mit OpenCV # 2 drehen ~ Mastering cv2.warpAffine () ~
Katze zurück mit OpenCV erkennen
Binarisierung mit OpenCV / Python
Datenerweiterung mit openCV
Drehen Sie das Sprite mit OpenCV # 3 ~ Berechnen Sie es selbst, ohne es anderen zu überlassen ~
Einfache TopView mit OpenCV
Stolpern Sie mit opencv3 von Homebrew
Gesichtserkennung mit OpenCV von Python
"Apple-Verarbeitung" mit OpenCV3 + Python3
Versuchen Sie die Kantenerkennung mit OpenCV
Bildbearbeitung mit Python OpenCV
Kameraerfassung mit Python + OpenCV
[Python] Verwenden von OpenCV mit Python (Basic)
Binarisieren Sie Fotodaten mit OpenCV
Loop-Video-Laden mit opencv
Gesichtserkennung mit Python + OpenCV
Holen Sie sich Bildfunktionen mit OpenCV
Gesichtserkennung / Schneiden mit OpenCV
Probieren Sie OpenCV mit Google Colaboratory aus
Erstellung eines Kaskadenklassifikators mit opencv
Verwenden von OpenCV mit Python @Mac
Bilderkennung mit Keras + OpenCV
Anime-Gesichtserkennung mit OpenCV
Leuchtendes Leben mit Python und OpenCV
Grundlagen der Echtzeit-Bildverarbeitung mit opencv
Zeichne unscharfe Sprites mit cocos2d / pyglet
[Python] Verwenden von OpenCV mit Python (Bildfilterung)
Neuronales Netzwerk mit OpenCV 3 und Python 3
[Python] Verwenden von OpenCV mit Python (Bildtransformation)
[Python] Verwenden von OpenCV mit Python (Kantenerkennung)
Löschen Sie bestimmte Farben mit OpenCV + PySimpleGUI
Einführung von OpenCV in Mac mit Homebrew
Einfache Python + OpenCV-Programmierung mit Canopy
Mit OpenCV die einfachsten Fehler finden
[OpenCV] Persönliche Identifikation mit Gesichtsfoto
Versuchen Sie die Gesichtserkennung mit Python + OpenCV
Schneiden Sie das Gesicht mit Python + OpenCV aus
Gesichtserkennung mit Kamera mit opencv3 + python2.7
OpenCV-Funktionserkennung mit Google Colaboratory
Suchen Sie mit opencv nach phasenidentischen zusammengesetzten Wörtern
Laden Sie das GIF-Bild mit Python + OpenCV
Katzenerkennung mit OpenCV (Modellverteilung)
Finden Sie Bildähnlichkeit mit Python + OpenCV
Versuchen Sie, das Bild mit opencv2 zu verwischen
Verwenden Sie OpenCV mit Python 3 in Window
Zeichnen Sie eine Illustration mit Python + OpenCV
Verfolgen Sie Baseballbälle mit Python + OpenCV
Graphbasierte Segmentierung mit Python + OpenCV
Objekterkennung mit openCV durch traincascade
Zeichnen Sie Figuren mit OpenCV und PIL
Ich habe versucht, das Gesicht mit OpenCV zu erkennen
Implementierte Inter-Frame-Differenzmethode mit OpenCV
Zeichnen Sie einen Pfeil (Vektor) mit opencv / python
Grundlegendes Studium von OpenCV mit Python
Ich möchte Objekte mit OpenCV erkennen
Erstellen Sie einen Videoplayer mit PySimpleGUI + OpenCV
Speichern Sie Videos Frame für Frame mit Python OpenCV
Versuchen Sie, die Kamera mit Pythons OpenCV zu verwenden
Bilder mit Pupil, Python und OpenCV aufnehmen