Der vorherige Artikel "Sprites mit OpenCV drehen" konnte während der Sommerferien nicht fertiggestellt werden, und ich konnte ihn am Wochenende auflösen.
Am Tag nach dem Hochladen kam mir jedoch eine neue Idee. Immerhin ist die Umgebung mit vielen Versuchungen nicht gut. Sie müssen sich in eine härtere Umgebung versetzen, um studieren zu können. Arbeitsplatz. </ strike>
Es gab ein interessantes, nicht wesentliches Argument von "cv2.warpAffine ()", das ich beim letzten Mal weggelassen habe. Referenzartikel: Zeichnen Sie mit OpenCV ein weiteres Bild auf ein Bild
--src Originalbild. Erforderlich.
cv2.INTER_NEAREST
etc.
--BorderMode-Hintergrundverarbeitungsmethode (außerhalb des Originalbilds). Der Standardwert ist "cv2.BORDER_CONSTANT".
--BorderValue Die Farbe bei borderMode = cv2.BORDER_CONSTANT
. Der Standardwert ist "0". Siehe unten.Erstellen Sie eine kleine Funktion, um das Ergebnis der Bildverarbeitung leicht verständlich zu machen. Bitte beachten Sie, dass nur der Mindestteil beschrieben wird.
python
def makeSampleImg(img4): #Bringen Sie ein RGBA 4-Kanal-Bild mit
h, w = img.shape[:2]
#A sowie die Umgebung zu färben=Es ist ein Fehler, es 255 (undurchsichtig) zu machen
cv2.rectangle(img, (0,0), (w-1,h-1), (0,0,255,255), 1)
return img
img_origin = cv2.imread(filename, -1) #RGBA-Bild
img4 = makeSampleImg(img_origin)
img3 = img4[:, :, :3] #Beseitigen Sie das A-Element und machen Sie es zu einem RGB-Bild
Das Originalbild | Kleine Verarbeitung | 3 Kanäle |
---|---|---|
Machen Sie den Hintergrund mit borderMode = cv2.BORDER_CONSTANT
einfarbig. Da dies der Standardwert von "borderMode" ist, muss er nicht beschrieben werden.
Ich werde es versuchen.
Geben Sie die Hintergrundfarbe an
M = cv2.getRotationMatrix2D((w/2,h/2), 30, 1)
img_rot31 = cv2.warpAffine(img3, M, (w, h), borderValue=(255,255,0)) #Vordergrund RGB, Hintergrund RGB
img_rot32 = cv2.warpAffine(img3, M, (w, h), borderValue=(255,255,0,0)) #Vordergrund RGB, Hintergrund RGBA (A Komponente = 0)
img_rot33 = cv2.warpAffine(img3, M, (w, h)) #Vordergrund RGB, kein Hintergrund angegeben
img_rot41 = cv2.warpAffine(img4, M, (w, h), borderValue=(255,255,0)) #Vordergrund RGBA, Hintergrund RGB
img_rot42 = cv2.warpAffine(img4, M, (w, h), borderValue=(255,255,0,0)) #Vordergrund-RGBA, Hintergrund-RGBA (A-Komponente = 0)
img_rot43 = cv2.warpAffine(img4, M, (w, h)) #Vordergrund RGBA, kein Hintergrund angegeben
img_rot44 = cv2.warpAffine(img4, M, (w, h), borderValue=(255,255,0,255)) #Vordergrund-RGBA, Hintergrund-RGBA (mit A-Komponente)
** Wenn der Vordergrund ein RGB-Bild ist **, wird die A-Komponente ignoriert, auch wenn 4 RGBA-Kanäle als Hintergrundfarbe angegeben sind (img_rot32). Es versteht sich, dass, wenn borderValue nicht angegeben ist, der Hintergrund schwarz ist (img_rot33 bzw. die Standardberechnung), die Hintergrundfarbe jedoch "(0,0,0)".
img_rot31 | img_rot32 | img_rot33 |
---|---|---|
** Wenn der Vordergrund ein RGBA-Bild ist **, werden 4 RGBA-Kanäle ausgegeben, auch wenn 3 RGB-Kanäle als Hintergrundfarbe angegeben sind. Die zu diesem Zeitpunkt angegebene A-Komponente ist "0". Da A Deckkraft und nicht Transparenz ist, ist dies "0", was bedeutet, dass selbst wenn ein BGR-Wert definiert wird, der nicht RGB ... war, dieser als Ergebnis transparent ist (img_rot41). Selbst wenn borderValue nicht angegeben ist, wird der Hintergrund transparent (img_rot43), aber es ist leicht zu verstehen, wenn Sie glauben, dass die Hintergrundfarbe "(0,0,0,0)" ist. Wenn Sie für die A-Komponente einen anderen Wert als "0" festlegen, wird dieser natürlich richtig gefärbt (img_rot44).
img_rot41 | img_rot42 | img_rot43 | img_rot44 |
---|---|---|---|
Wenn Sie borderMode = cv2.BORDER_TRANSPARENT
setzen, können Sie das Hintergrundbild mit dst
angeben.
Wie so oft bei OpenCV wird bei Verwendung von "cv2.warpAffine ()" das durch "dst" angegebene Hintergrundbild verarbeitet. Wenn Sie das Originalbild behalten möchten, müssen Sie "dst = back.copy ()" setzen.
Ich habe erwartet, dass es transparent sein würde, weil es TRANSPARENT ist. Wenn ich also nicht "dst" angeben würde, wäre es ein transparenter Hintergrund, aber es war nicht so einfach. Oh! Irgendwie möchte ich Ikura essen.
Geben Sie das Hintergrundbild an
back = cv2.imread(back_name) #RGB-Bild mit der gleichen Größe wie das Vordergrundbild
back4 = cv2.cvtColor(back, cv2.COLOR_BGR2BGRA) #Erstellen eines RGBA-Images Eine Komponente ist 255 anstelle von 0
M = cv2.getRotationMatrix2D((w/2,h/2), 30, 1)
img_rot35 = cv2.warpAffine(img3, M, (w, h), borderMode=cv2.BORDER_TRANSPARENT, dst=back.copy()) #Vordergrund RGB, Hintergrund RGB
img_rot36 = cv2.warpAffine(img3, M, (w, h), borderMode=cv2.BORDER_TRANSPARENT, dst=back4.copy()) #Vordergrund RGB, Hintergrund RGBA
img_rot37 = cv2.warpAffine(img3, M, (w, h), borderMode=cv2.BORDER_TRANSPARENT) #Vordergrund RGB, kein Hintergrund angegeben
img_rot45 = cv2.warpAffine(img4, M, (w, h), borderMode=cv2.BORDER_TRANSPARENT, dst=back.copy()) #Vordergrund RGBA, Hintergrund RGB
img_rot46 = cv2.warpAffine(img4, M, (w, h), borderMode=cv2.BORDER_TRANSPARENT, dst=back4.copy()) #Vordergrund RGBA, Hintergrund RGBA
img_rot47 = cv2.warpAffine(img4, M, (w, h), borderMode=cv2.BORDER_TRANSPARENT) #Vordergrund RGBA, kein Hintergrund angegeben
Sowohl der Vordergrund als auch der Hintergrund verhielten sich beim RGB-Bild wie erwartet (img_rot35).
Wenn ich im RGB-Vordergrund kein Hintergrundbild angegeben habe, hat sich das Ergebnis bei jeder Ausführung geändert (img_rot37). numpy
hat eine Funktion namens numpy.empty ()
, die ein nicht initialisiertes Array erstellt. Das Hintergrundbild (oder besser gesagt das Numpy-Array) wird wahrscheinlich auch hier mit denselben Spezifikationen erstellt.
Ich bin mir nicht sicher, warum img_rot36, das den RGBA-Hintergrund im RGB-Vordergrund spezifizierte, sich in einen schwarzen Hintergrund mit Staub verwandelte.
img_rot35 | img_rot36 | img_rot37 teil 1 | img_rot37 Teil 2 |
---|---|---|---|
Das RGBA-Bild (img_rot46) sowohl für den Vordergrund als auch für den Hintergrund ist wie erwartet, aber es ist auch ein enttäuschendes Ergebnis. Ich war froh, wenn der Hintergrund im transparenten Teil des Vordergrunds angezeigt wurde, aber es kann nicht geholfen werden, weil ** Affin-Konvertierung überhaupt nicht so ist **. Der Hintergrund von img_rot45, der einen RGB-Hintergrund für den RGBA-Vordergrund spezifizierte, und img_rot47, der kein Hintergrundbild für den RGBA-Vordergrund spezifizierte, wurde transparent. In beiden Fällen scheint dem A-Element "0" hinzugefügt worden zu sein.
Kurz gesagt, die weltliche Schlussfolgerung ist, dass es ratsam ist, es nicht unerwartet zu verwenden.
img_rot45 | img_rot46 | img_rot47 |
---|---|---|
Wie oben erwähnt, habe ich unter Bezugnahme auf den Artikel meines Vorgängers darüber nachgedacht, ein RGBA-Bild einschließlich Transparenz in das Bild einzufügen, aber es war unmöglich zu schließen. Attraktiv sind jedoch die Spezifikationen, die auch dann keinen Fehler verursachen, wenn sie über das Hintergrundbild hinausgehen. Aus diesem Grund habe ich beschlossen, die bisherige Maskenmethode mit der Affin-Konvertierung zu kombinieren. Dann ... ist es geschafft, super einfach. Es gibt keine Probleme mit dem extrinsischen Quadrat oder dem ROI.
Quelle
import cv2
def makeSampleImg(img4):
h, w = img4.shape[:2]
cv2.rectangle(img4, (0,0), (w-1,h-1), (0,0,255,255), 1)
return img4
def putSprite_Affine(back, front4, pos, angle=0, center=(0,0)):
x, y = pos
front3 = front4[:, :, :3]
mask1 = front4[:, :, 3]
mask3 = 255- cv2.merge((mask1, mask1, mask1))
bh, bw = back.shape[:2]
M = cv2.getRotationMatrix2D(center, angle, 1)
M[0][2] += x
M[1][2] += y
front_rot = cv2.warpAffine(front3, M, (bw,bh))
mask_rot = cv2.warpAffine(mask3, M, (bw,bh), borderValue=(255,255,255))
tmp = cv2.bitwise_and(back, mask_rot)
result = cv2.bitwise_or(tmp, front_rot)
return result
if __name__ == "__main__":
filename_front = "uchuhikoushi.png "
filename_back = "space.jpg "
img_front = cv2.imread(filename_front, -1)
img_front = makeSampleImg(img_front) #Fügen Sie dem RGBA-Image einen Frame hinzu (nicht erforderlich)
img_back = cv2.imread(filename_back)
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:
img = img_back.copy()
for x,y in pos:
img = putSprite_Affine(img, 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_Affine", img)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
angle = (angle + 30) % 360
cv2.destroyAllWindows()
Apropos Nachteile: Der Rechenaufwand ist nutzlos groß, da das Maskenbild und das RGB-Bild in das gesamte Hintergrundbild konvertiert werden ("Overhead. AA% E3% 83% BC% E3% 83% 90% E3% 83% BC% E3% 83% 98% E3% 83% 83% E3% 83% 89) scheint groß zu sein. "
Vorderseite in der Mitte der Zeichnung_rot |
---|
Maske mitten in der Zeichnung_rot |
Ergebnis |
Hier wird das vorherige Anime-GIF gepostet, aber in Wirklichkeit dreht sich der Charakter mit dem roten Rahmen. |
Nun wollen wir sehen, wie sich dies auf die Ausführungsgeschwindigkeit auswirkt.
Es ist noch nicht vorbei.
Recommended Posts