Ceci est une suite de Gestion des images transparentes avec OpenCV-Making sprites dance-.
C'est excitant de faire pivoter le sprite. Je me souviens de la carte SYSTEM II de Namco. Assaut ou ordre. J'ai acheté Namco Museum VOL.4 avant d'acheter la PlayStation elle-même.
Dans OpenCV, vous pouvez faire pivoter l'image par incréments de 90 degrés avec cv2.rotate ()
, mais il n'y a pas de fonction pour la faire pivoter à n'importe quel angle. Il existe une fonction plus avancée, alors utilisez-la.
La transformation Affin est un mappage qui combine une transformation principale telle que la rotation et la mise à l'échelle avec un mouvement parallèle. En bref
\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}
C'est une conversion. Il est difficile de programmer sous cette forme
\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}
Je vais l'exprimer comme. Le fond est quelque peu désagréable, mais il n'y a qu'une égalité de «1 = 1».
cette
\begin{pmatrix}
a & b & c \\
d & e & f \\
\end{pmatrix}
Est défini et appliqué à la fonction cv2.warpAffine ()
.
Cependant, lors de la rotation de l'image, dérangez
\begin{pmatrix}
cosθ & -sinθ & 0 \\
sinθ & cosθ & 0 \\
\end{pmatrix}
Il n'est pas nécessaire de calculer. Vous pouvez utiliser la matrice obtenue par cv2.getRotationMatrix2D ()
.
Ajoutons le mouvement parallèle par vous-même.
--src Image d'origine.
-M matrice de conversion 2 * 3.
--dsize Spécifiez la taille de l'image de sortie avec une touche de (largeur, hauteur)
.
Je me demande à quoi ressemble la matrice de conversion.
Source 1
import cv2
angle = 30 # degrees
M = cv2.getRotationMatrix2D((0,0), angle, 1)
print (M)
print (M.shape)
print (M.dtype)
Résultat 1
[[ 0.8660254 0.5 0. ]
[-0.5 0.8660254 0. ]]
(2, 3)
float64
cos30 degrés = √3 / 2 = 0.8660254 ... C'est donc exactement ce qu'est la matrice de rotation ...? La position négative est différente, non? Apparemment, contrairement au plan xy utilisé en mathématiques, le calcul correspond à un système de coordonnées où le fond est positif.
Alors, convertissons l'image en utilisant ceci.
Source 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()
Le résultat est le suivant.
L'image originale | résultat |
---|---|
Je comprends l'angle de rotation et le centre de rotation, mais je veux dire: "Attendez une minute, l'image dépasse en premier lieu."
Comment éviter de sortir du lot? Je vais calculer quoi faire.
Lorsqu'un rectangle (rouge) dont les deux côtés sont w et h est incliné d'un angle a, la taille du quadrilatère circonscrit (bleu) est
python
rot_w = w*cos(a) + h*sin(a)
rot_h = w*sin(a) + h*cos(a)
Sera. Si la température s'écarte de 0 à 90 degrés, le sinus et le cosinus seront négatifs, donc pour être exact, chaque terme doit être une valeur absolue. Oh, je comprends enfin. Cette formule est apparue dans l'article des ancêtres décrit plus tard, et je me demandais en quoi elle était différente de la matrice de rotation.
Ainsi, vous pouvez déplacer la position en parallèle pour qu'elle tienne dans ce rectangle bleu. Puisque (0,0) est le centre de rotation, nous pensons en fonction du centre de l'image.
Source 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()
Le résultat est le suivant. L'image ne sort plus de la fenêtre, mais cela ne peut pas être aidé car l'animation est basée sur la restriction que la position de la fenêtre (position supérieure gauche de l'image) est commune.
Afin de spécifier le centre et de le faire pivoter afin que l'image créée ne devienne pas sauvage, la taille de la toile sur laquelle l'image pivotée est dessinée doit être déterminée à l'avance. Trouver la taille du campus n'est pas difficile. De la distance entre le centre de rotation et les quatre coins, le plus grand correspond au rayon. La taille de la toile est le double.
Probablement en bon état, la source suivante exprime la formule pour trouver le rayon en une seule ligne. Maintenant, il est difficile de comprendre quel genre de calcul je fais. Ce n'est pas bon de courir très habilement.
Source 4
import cv2
import numpy as np
filename = "hoge.png "
img = cv2.imread(filename)
h, w = img.shape[:2]
xc, yc = 140, 60 #Centre de rotation
angle = 0
#Trouvez la valeur maximale de la distance entre le centre de rotation et les quatre coins
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()
Le résultat est le suivant.
Ajoutez le traitement ci-dessus à la fonction sprite de previous.
Il aurait pu être préférable d'arrondir avec math.ceil ()
au lieu de ʻint () `.
Source 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]
#Trouvez la valeur maximale de la distance entre le centre de rotation et les quatre coins
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))))
#Tourner
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)) #Quadrilatère externe contenant une image pivotée
#Ne rien faire si le carré extrinsèque entier est en dehors de l'image d'arrière-plan
x0, y0 = x+xc-r, y+yc-r
if not ((-2*r < x0 < bw) and (-2*r < y0 < bh)) :
return back
#Obtenez uniquement l'image d'arrière-plan du carré extrinsèque
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]
#Combinez le quadrilatère circonscrit et l'arrière-plan avec la méthode du masque
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)] #Coordonnée en haut à gauche pour mettre l'image
xc, yc = 140, 60 #Centre de rotation de l'image de premier plan
angle = 0
while True:
back = img_back.copy()
for x,y in pos:
img = putSprite_mask2(back, img_front, (x,y), angle, (xc,yc))
#Assurez-vous qu'il est correctement représenté (non requis)
cv2.circle(img, (x,y), 5, (0,255,0), -1) #Marque en haut à gauche de l'image de premier plan
cv2.circle(img, (x+xc,y+yc), 5, (0,0,255), -1) #Marque au centre de rotation
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()
C'est fait.
En fait, je voulais obtenir le même comportement en minimisant le quadrilatère circonscrit et en contrôlant finement les coordonnées en haut à gauche, mais je ne pouvais pas bien résoudre les problèmes de figures et de matrices, c'est-à-dire au niveau des mathématiques du lycée. Il n'y en avait pas. Hein? Pourquoi ne fais-tu pas la queue au lycée maintenant? !!
Crée et enregistre une image qui pivote autour du centre de l'image d'origine selon l'angle spécifié. Comment éviter que la partie saillante ne soit coupée en faisant pivoter l'image d'opencv Comprendre complètement la conversion Affin
Recommended Posts