Ceci est une continuation de Dernière fois.
La fonction «cv2.putText ()» qui décrit le texte dans OpenCV ne peut pas utiliser le japonais. Comme c'est possible avec PIL, il existe de nombreuses méthodes sur le Web qui n'utilisent PIL que pour cette partie, mais j'ai publié une fonction unique qui peut être une alternative à cv2.putText ()
simplement parce que je l'ai essayé pour le moment. Il n'y avait pas de place.
Alors je l'ai fait moi-même. Je suis désolé s'il existe une méthode standard simplement parce que mes compétences en recherche sont faibles.
version: OpenCV 4.1.2.30 Pillow 7.0
(x, y)
.cv2.FONT_HERSHEY_SIMPLEX
peuvent être spécifiés.La cible est un objet ImageDraw.Draw créé à partir d'une image PIL.
(x, y)
.cv2.putText ()
est un argument significatif car c'est une police vectorielle. Ce n'est pas grave si ce n'est pas dans PIL.
A part cela, il semble possible de remplacer cv2.putText ()
par ʻImageDraw.text () `.cv2.imshow ()
ne peut pas être utilisé Google Colab a sa propre fonction ** cv2_imshow () **.
Ensuite, nous avons nommé la fonction d'origine qui décrit les polices japonaises dans OpenCV ** cv2_putText () **.
Tout d'abord, préparez deux fonctions. C'est une fonction qui convertit OpenCV et PIL, que j'ai écrit dans cet article.
python
import numpy as np
import cv2
from PIL import Image, ImageDraw, ImageFont
def pil2cv(imgPIL):
imgCV_RGB = np.array(imgPIL, dtype = np.uint8)
imgCV_BGR = np.array(imgPIL)[:, :, ::-1]
return imgCV_BGR
def cv2pil(imgCV):
imgCV_RGB = imgCV[:, :, ::-1]
imgPIL = Image.fromarray(imgCV_RGB)
return imgPIL
python
def cv2_putText_1(img, text, org, fontFace, fontScale, color):
x, y = org
b, g, r = color
colorRGB = (r, g, b)
imgPIL = cv2pil(img)
draw = ImageDraw.Draw(imgPIL)
fontPIL = ImageFont.truetype(font = fontFace, size = fontScale)
draw.text(xy = (x,y), text = text, fill = colorRGB, font = fontPIL)
"""
Je l'ajouterai ici plus tard
"""
imgCV = pil2cv(imgPIL)
return imgCV
C'est la même chose que de nombreux prédécesseurs pour créer une image PIL une fois, dessiner du texte japonais dessus, puis le renvoyer à une image OpenCV, mais cv2.putText (img, text, org, fontFace, fontScale, color, thick) La particularité est qu'il peut être utilisé de la même manière que
.
Bien sûr, si vous dites "Je veux utiliser le japonais, mais la police et la taille sont fixes", vous pouvez définir les arguments par défaut.
Comparons les résultats de sortie de cv2.putText ()
et cv2_putText ()
.
python
import numpy as np
import cv2
from PIL import Image, ImageDraw, ImageFont
def pil2cv(imgPIL):
#Ceux listés ci-dessus
def cv2pil(imgCV):
#Ceux listés ci-dessus
def cv2_putText_1(img, text, org, fontFace, fontScale, color):
#Ceux listés ci-dessus
def main():
img = np.full((200,400,3), (160,160,160), dtype=np.uint8)
#Ordinairement cv2.putText()Dessiner du texte avec
text = "OpenCV"
x, y = 50, 100
fontCV = cv2.FONT_HERSHEY_SIMPLEX
fontScale = 1
colorBGR = (255,0,0)
thickness = 1
cv2.putText(img = img,
text = text,
org = (x,y),
fontFace = fontCV,
fontScale = fontScale,
color = colorBGR,
thickness = thickness)
"""
Je l'ajouterai ici plus tard
"""
#Dessinez du texte japonais avec votre propre fonction
text = "Japonais aussi\n possible"
x, y = 200,100
fontPIL = "Dflgs9.TTC" #DF Reiga Song
size = 40
colorBGR = (255,0,0) # cv2.putText()Comme avec, défini dans l'ordre de BGR
img = cv2_putText_1(img = img,
text = text,
org = (x,y),
fontFace = fontPIL,
fontScale = size,
color = colorBGR)
cv2.imshow("cv2_japanese_test", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
Le résultat est le suivant.
Les coordonnées y doivent avoir la même valeur, mais les hauteurs sont désactivées. C'est parce que, comme je l'ai écrit dans la section critique, * org * dans cv2.putText ()
spécifie le coin inférieur gauche, et * xy * dans ʻImageDraw.text () `spécifie le coin supérieur droit.
Traitons-le pour que vous puissiez le comprendre.
python
# cv2_putText_1()Ajoutez ce qui suit à la ligne de commentaire de
w, h = draw.textsize(text, font = fontPIL)
draw.rectangle([(x,y), (x+w,y+h)], outline = (255,0,0), width = 1)
draw.ellipse([(x-3,y-3), (x+3,y+3)], None, (255,0,0), 1)
# main()Ajoutez ce qui suit à la ligne de commentaire de
(w, h), b = cv2.getTextSize(text = text,
fontFace = fontCV,
fontScale = fontScale,
thickness = thickness)
pt1 = (x, y - h)
pt2 = (x + w, y + b)
cv2.rectangle(img, pt1, pt2, (0,0,255), 1)
cv2.circle(img, (x,y), 5, (0,0,255))
Le résultat est le suivant.
Dans l'article précédent, je n'ai pas utilisé la ligne de base obtenue par cv2.getTextSize ()
, mais cette fois j'ai essayé de dessiner un carré en l'incluant.
Je ne sais pas pourquoi les carrés PIL ne correspondent pas subtilement au texte japonais. Peut-être que le bogue mentionné par cette personne est lié.
Quoi qu'il en soit, pour rendre votre propre fonction compatible avec * org * dans cv2.putText ()
, vous devez modifier cette partie.
Voici une version modifiée de la norme de hauteur.
python
def cv2_putText_2(img, text, org, fontFace, fontScale, color):
x, y = org
b, g, r = color
colorRGB = (r, g, b)
imgPIL = cv2pil(img)
draw = ImageDraw.Draw(imgPIL)
fontPIL = ImageFont.truetype(font = fontFace, size = fontScale)
w, h = draw.textsize(text, font = fontPIL)
draw.text(xy = (x,y-h), text = text, fill = colorRGB, font = fontPIL)
imgCV = pil2cv(imgPIL)
return imgCV
Vous pouvez obtenir une image comme celle-ci en remplaçant cv2_putText_1
dans main ()
par cv2_putText_2
.
Similaire à cv2.putText ()
, j'ai pu dessiner le texte en spécifiant le coin inférieur gauche.
Cependant, je n'aime pas la spécification que * org * spécifie en bas à gauche dans cv2.putText ()
, donc je préfère cv2_putText_1 ()
.
Si vous spécifiez la police et la taille de la police avec cv2.putText ()
, la taille du texte à dessiner est déterminée. Si vous calculez la taille appropriée avec la police spécifiée, vous pouvez modifier le programme existant comme indiqué dans ici avec une modification minimale. Vous pouvez changer de police TrueType! J'ai pensé, mais j'ai arrêté parce que c'était gênant. ..
Si vous en faites une fonction, vous pouvez utiliser les polices japonaises de la même manière que cv2.putText ()
. C'était une histoire.
Cependant, bien sûr, notez que le japonais n'est pas disponible dans le nom de fenêtre de cv2.imshow ()
ou dans le nom de fichier de cv2.imwrite ()
.
Au fait, comment pouvons-nous créer (b, g, r)
à partir du taple (r, g, b)
?
Dans ma fonction cette fois, je retire chaque élément et change l'ordre pour faire un nouveau taple, mais ce n'est pas une solution élégante.
Vous pouvez convertir les taples en liste, inverser l'ordre, puis les convertir à nouveau en taples, mais c'est loin d'être élégant.
python
r, g, b = 0, 128, 255
RGB = (r, g, b)
BGR = tuple(list(RGB)[::-1])
print (RGB) # (0, 128, 255)
print (BGR) # (255, 128, 0)
S'il vous plaît laissez-moi savoir s'il existe une bonne façon de faire l'expérience de aha, comme ʻimg [:,:, :: -1] `lors de la conversion d'une image RVB en BGR.
Recommended Posts