[PYTHON] Dessinez des figures avec OpenCV et PIL

introduction

Si vous faites un papier de mise en conserve, vous le comprendrez dans le processus. Ceci est un article pour moi. J'avais l'intention d'écrire un article spécialisé dans OpenCV, mais pour une raison quelconque, j'ai dû également écrire sur PIL. Certains arguments sont omis.

OpenCV

Créer une image monochrome de base numpy.full (shape, fill_value, dtype)

Comme les données d'image d'OpenCV sont un tableau numpy, vous pouvez créer une image monochrome avec np.full (). Dans le cas d'un fond noir, une description plus simple peut être faite, mais il ne suffit pas de s'en souvenir individuellement, elle est donc omise.

Dessinez une figure

La fonction suivante traite l'image spécifiée. Qu'est-ce que ça veut dire? img = cv2.line(img, ...) Et la valeur de retour n'a pas à être réaffectée à elle-même cv2.line(img, ...) La valeur de ʻimgchange simplement en écrivant. Si vous ne souhaitez pas que cela se produise, vous devez copier l'image d'origine en tant qu'objet distinct. C'est pourquoi j'ai mis ʻimg_rect = img_origin.copy ()dans cet article.

Tracez une ligne cv2.line (img, pt1, pt2, couleur, épaisseur)

Dessinez un rectangle carré cv2. (img, pt1, pt2, couleur, épaisseur)

Dessine un cercle cv2.circle (img, centre, rayon, couleur, épaisseur)

Utilisez cv2.ellipse () pour dessiner un arc.

Dessinez une ellipse ou un arc cv2.ellipse (img, centre, axes, angle, startAngle, endAngle, couleur, épaisseur)

L'angle peut être un petit nombre. De plus, le sens de rotation de l'axe x à l'axe y est positif. Les coordonnées mathématiques xy sont dans le sens antihoraire, mais dans le système de coordonnées de l'ordinateur, l'axe y est vers le bas, donc le sens antihoraire est positif. En d'autres termes, ce genre de chose. ellipse.png

Eh bien, même si j'écris jusqu'à présent, je ne l'utiliserai pas de toute façon.

Dessinez un polygone cv2.polylines (img, pts, isClosed, couleur, épaisseur)

Écrire * pts * est compliqué, mais vous devez le maîtriser pour jouer avec la détection de contour, alors faisons de notre mieux pour nous en souvenir. Dans l'exemple de programme ci-dessous, une fonction personnalisée est intégrée pour dessiner plusieurs fois la même figure. Avez-vous été arrêté par la police du PEP si vous utilisiez l'espace pour les aligner?

polylines_test.py


import numpy as np
import cv2

###Fonction pour décaler les coordonnées
# [(x1,y1), (x2,y2)]Quand(a,b)De[(x1+a,y1+b), (x2+a, y2+b)]faire
def position_offset(pos, offset):
    np_newpos = np.array(pos) + np.array(offset)
    list_newpos = list(map(tuple, np_newpos.tolist()))
    return list_newpos


###Créer une image monochromatique de base
imgCV = np.full((180,200,3), (128,128,128), dtype = np.uint8)

###Faire 3 mêmes lignes de pliage
pos = [(10,10), (80,60), (80,10), (60,30)]
offset1 = (  0,  0)
offset2 = (100, 40)
offset3 = (100,100)
pts1 = np.array(position_offset(pos, offset1))
pts2 = np.array(position_offset(pos, offset2))
pts3 = np.array(position_offset(pos, offset3))

###Dessinez un polygone
#Dessinez un polygone
cv2.polylines(imgCV, [pts1]      , True, (255,0,0), 3)

#Dessinez plusieurs polygones à la fois
cv2.polylines(imgCV, [pts2, pts3], True, (0,0,255), 3)

cv2.imshow("polylines", imgCV)
cv2.waitKey(0)
cv2.destroyAllWindows()

Le résultat est le suivant. CV_test.png

Remplissez le polygone cv2.fillPoly (img, pts, couleur)

Remplissez avec précision les polygones avec des renfoncements. Wikipedia contient un élément appelé Concave Square Dans l'encyclopédie pour enfants que j'ai lue il y a longtemps, elle s'appelait "Arrow's Negata".

Remplissez le polygone convexe cv2.fillConvexPoly (img, points, couleur)

Si vous savez qu'il s'agit d'un polygone convexe, il est plus rapide de l'utiliser. Si vous l'utilisez avec un polygone concave, cela ne provoquera pas d'erreur, mais laissera des zones non peintes.

Dessiner des caractères cv2.putText (img, text, org, fontFace, fontScale, color, thick)

Polices pouvant être utilisées avec cv2.putText ()

Les 8 types suivants peuvent être utilisés. HERSHEY n'est pas un chocolat, mais une police vectorielle développée par le Dr Hercy.

En combinant ceci avec cv2.FONT_ITALIC (car c'est une constante intégrée, ajoutez-la), elle peut être rendue oblique.

Trouvez la largeur et la hauteur du texte cv2.getTextSize (text, fontFace, fontScale, thick)

Utilisez cette fonction lorsque vous souhaitez placer le texte au centre de la figure. Il y a deux sorties. La taille du texte représenté par (largeur, hauteur) et la coordonnée y de la ligne de base vue depuis le point le plus bas de la chaîne. Ce dernier est celui qui apparaît ci-dessous comme "y" et "p".

Exemple de représentation de personnage

putText_test.py


import numpy as np
import cv2

fonts=[cv2.FONT_HERSHEY_SIMPLEX,
       cv2.FONT_HERSHEY_PLAIN,
       cv2.FONT_HERSHEY_DUPLEX,
       cv2.FONT_HERSHEY_COMPLEX,
       cv2.FONT_HERSHEY_TRIPLEX,
       cv2.FONT_HERSHEY_COMPLEX_SMALL,
       cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
       cv2.FONT_HERSHEY_SCRIPT_COMPLEX]

#Créer une image monochromatique de base
img = np.full((360,600,3), (255,255,255), dtype = np.uint8)

for i, font in enumerate(fonts):
    for j in range(2):
        for k in range(2):
            x, y = 200*(j+1)*k+10, i*40+50
            fnt = font if j == 0 else font + cv2.FONT_ITALIC
            text = "sample_{}".format(fnt)
            cv2.putText(img,
                        text = text,
                        org = (x, y),
                        fontFace = fnt,
                        fontScale = 1,
                        color = (0, 0, 255*j),
                        thickness=1)

            #Ligne de base inutilisée
            (w, h), _ = cv2.getTextSize(text = text,
                                        fontFace = fnt,
                                        fontScale = 1,
                                        thickness = 1)
            cv2.rectangle(img, (x, y), (x+w, y-h), (255, 0, 0))
            cv2.circle(img, (x, y), 3, (255, 0, 0))

cv2.imshow("hershey fonts",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

La colonne centrale est une police normale et la colonne de droite est une police italique. La gauche est un composite des deux. Certaines polices n'ont pas l'effet italique.

cv_fonts.png

PIL

Créer une image monochrome de base Image.new (mode, taille, couleur)

Dessinez une figure

Pour dessiner une figure sur une image, créez un objet ImageDraw.Draw au lieu de l'image elle-même et dessinez dessus.

Tracez une ligne (ligne pliée) ImageDraw.line (xy, fill, width, joint)

Probablement un bug, mais lors de l'utilisation de joint =" curve ", la description du groupe de coordonnées doit êtrexy = [(x1, y1), (x2, y2), ...]. Si xy = [x1, y1, x2, y2, ...], une erreur se produira. De plus, si vous tracez une ligne de pliage avec la couleur par défaut sans définir * remplissage *, le traitement de la courbe sera à mi-chemin.

Dessinez un ImageDraw.rectangle carré (xy, remplissage, contour, largeur)

Dessinez un cercle (ellipse) ImageDraw.ellipse (xy, fill, contour, width)

Je me demandais pourquoi il avait de telles spécifications, mais quand j'y ai pensé, il y avait beaucoup de logiciels de dessin avec de telles spécifications.

Dessinez un polygone ImageDraw.polygon (xy, fill, contour)

Si vous connaissez la ligne et le rectangle, vous pouvez le maîtriser. Pour le moment, la largeur de ligne ne peut pas être spécifiée et est fixée à 1.

Autre

PIL.ImageDraw.ImageDraw.point (* xy *, * fill ) au point (multiple) points ImageDraw.arc ( xy *, * début *, * fin *, * remplissage *, * largeur ) ImageDraw.chord ( xy *, * début *, * fin *, * remplissage *, * contour *, * largeur ) ImageDraw.pieslice ( xy *, * start *, * end *, * fill *, * outline *, * width *) peut être utilisé pour dessiner une forme en éventail (arc + rayon). L'unité d'angle est le degré, qui augmente dans le sens des aiguilles d'une montre à partir de 3 heures comme cv2.ellipse () d'OpenCV.

Dessiner des lettres

La méthode de dessin des caractères PIL utilise la police du PC, donc le japonais peut également être utilisé.

Dessiner des caractères ImageDraw.text (xy, texte, remplissage, police)

Spécifiez la police de caractères ImageFont.truetype (police, taille)

Trouvez la largeur et la hauteur du texte ImageDraw.textsize (texte, police)

Contrairement à cv2.getTextSize (), la sortie est uniquement (largeur, hauteur).

Échantillon PIL

C'est devenu beaucoup de choses. Ici aussi, la fonction auto-créée position_offset () est utilisée.

PIL_test.py


import numpy as np
from PIL import Image, ImageDraw, ImageFont

###Fonction pour décaler les coordonnées
# [(x1,y1), (x2,y2)]Quand(a,b)De[(x1+a,y1+b), (x2+a, y2+b)]faire
def position_offset(pos, offset):
    np_newpos = np.array(pos) + np.array(offset)
    list_newpos = list(map(tuple, np_newpos.tolist()))
    return list_newpos


###Créer une image monochromatique de base
imgPIL = Image.new("RGB", (640,480), (128,128,128))

###Créer un objet Draw
draw = ImageDraw.Draw(imgPIL)

###Ligne brisée
pos = [(10,10), (80,60), (80,10), (60,30)]

### line
for i in range(6):
    # y=0 : joint =Ligne pliée lorsque Aucun est défini et que le remplissage est omis.
    draw.line(xy = position_offset(pos,(100*i,0)),
              width = i*5,
              joint = None)

    # y=100 : joint = "curve"Ligne pliée quand
    draw.line(xy = position_offset(pos,(100*i,100)),
              fill = (0,255,255),
              width = i*5,
              joint = "curve")

    # y=Extrémité droite de 200:joint sans spécifier de remplissage= "curve"Comportement quand
    #Il n'est pas nécessaire qu'il soit à l'intérieur de la boucle for, mais je l'ai mis ici pour faciliter la comparaison.
    draw.line(xy = position_offset(pos,(100*5,200)),
              width = 25,
              joint = "curve")
    

###Même si le même groupe de coordonnées que la ligne de polygone est utilisé, il devient un polygone fermé.
#Spécifier le remplissage
draw.polygon(xy = position_offset(pos,(0,200)),
             fill = (255,0,0))

#Spécifier le contour
draw.polygon(xy = position_offset(pos,(100,200)),
             outline = (0,255,0))

#Spécifier le remplissage et le contour
draw.polygon(xy = position_offset(pos,(200,200)),
             fill = (255,0,0),
             outline = (0,255,0))


###rectangle et ellipse
pos=[(10,0), (200,70)] #Changeons l'ordre des deux points
for i in range(3):
    draw.rectangle(xy = position_offset(pos,(200*i,300)),
                   fill = None,
                   outline = (0,0,255),
                   width = i*5) #la largeur peut être 1 même si elle vaut 0

    draw.ellipse(xy = position_offset(pos,(200*i,300)),
                 fill = (255,255,0),
                 outline = (0,255,0),
                 width = i*5)

###arc, accord et pieslice
start, end = 45, 300
#arc Le contour de l'arc est abrégé
draw.arc(xy = position_offset(pos,(0,400)),
         start = start,
         end = end,
         width = 4)

#corde d'accord
draw.chord(xy = position_offset(pos,(200,400)),
           start = start,
           end = end,
           fill = (255,0,0),
           outline = (0,255,0))

#pieslice en forme d'éventail
draw.pieslice(xy = position_offset(pos,(400,400)),
              start = start,
              end = end,
              fill = (255,0,0),
              outline = (0,255,0))


###Dessiner des lettres
#Dessinez des personnages avec des paramètres minimaux
draw.text(xy = (520,190),
          text = "bug? -> ")

#Dessiner des caractères dans la police spécifiée
#La police était DF Reiga Song
font = ImageFont.truetype(font="Dflgs9.TTC",
                          size=30)
draw.text(xy = (440,250),
          text = "punaise? →",
          fill = (0,0,0),          
          font = font)

###Afficher l'image
imgPIL.show()

Le résultat est le suivant. PIL_test.png

À la fin

Merci à teratail d'avoir créé ma propre fonction position_offset (). Merci beaucoup. https://teratail.com/questions/234513

Aperçu de la prochaine fois

Je veux afficher le japonais dans OpenCV. À cette fin, le PIL ne devrait être utilisé que pour cette partie. Il existe de nombreux articles de ce type sur le Web, mais je ne suis pas satisfait d'eux. Je ne vais pas renvoyer mes ancêtres, mais je veux créer une fonction plus pratique.

Recommended Posts

Dessinez des figures avec OpenCV et PIL
Réseau neuronal avec OpenCV 3 et Python 3
Dessinez une illustration avec Python + OpenCV
Dessinez une flèche (vecteur) avec opencv / python
Dessinez une illusion d'aquarelle avec détection des contours en Python3 et openCV3
Capturer des images avec Pupil, python et OpenCV
Dessinez une figure sur la couche d'entités avec ArcPy
Hello World et détection de visage avec OpenCV 4.3 + Python
Installez OpenCV 4.0 et Python 3.7 sur Windows 10 avec Anaconda
Conversion en ondelettes d'images avec PyWavelets et OpenCV
Correspondance des fonctionnalités avec OpenCV 3 et Python 3 (A-KAZE, KNN)
Installation PIL avec pip
Détecter le retour du chat avec OpenCV
Dessinez une animation de flux semblable à la Terre avec matplotlib et cartopy
Capture d'image / comparaison de la vitesse OpenCV avec et sans GPU
Détecter l'état de port du masque avec OpenCV et Raspberry Pi
Comment boucler et lire une vidéo gif avec openCV
Faire pivoter les sprites avec OpenCV
Ubuntu 20.04 sur raspberry pi 4 avec OpenCV et utilisation avec python
RaspberryPi Zero et OpenCV
Augmentation des données avec openCV
[Python] Taille d'image de la caméra Web et paramètres FPS avec OpenCV
Chargement / affichage et accélération de gif avec python [OpenCV]
Résoudre les problèmes liés à l'installation d'OpenCV sur Raspberry Pi et à la capture
Avec et sans WSGI
TopView facile avec OpenCV
Trébucher avec opencv3 de homebrew
Traitement d'image avec PIL
Séparez les images couleur en images RVB et affichez-les avec OpenCV
Créez une caméra de surveillance WEB avec Raspberry Pi et OpenCV
L'histoire de l'affichage d'images avec OpenCV ou PIL (uniquement)
Convertir une vidéo en noir et blanc avec ffmpeg + python + opencv
Programmation avec Python et Tkinter
Dessinez la courbe de Bézier avec Go
Chiffrement et déchiffrement avec Python
Travailler avec le tkinter et la souris
Traitement d'image avec PIL (Pillow)
Reconnaissance faciale avec OpenCV de Python
Dessinez un graphique avec NetworkX
"Traitement Apple" avec OpenCV3 + Python3
Python et matériel - Utilisation de RS232C avec Python -
Dessinez bonjour le monde avec mod_wsgi
Essayez la détection des bords avec OpenCV
Édition d'image avec python OpenCV
Capture de caméra avec Python + OpenCV
[Python] Utilisation d'OpenCV avec Python (basique)
Binariser les données photo avec OpenCV
Détection des bords en temps réel avec OpenCV
Détection de visage avec Python + OpenCV
Obtenez des fonctionnalités d'image avec OpenCV
Super résolution avec SRGAN et ESRGAN
Group_by avec sqlalchemy et sum
Reconnaissance faciale / coupe avec OpenCV
python avec pyenv et venv
Essayez OpenCV avec Google Colaboratory
Dessinez un graphique avec networkx
Avec moi, NER et Flair
Utiliser OpenCV avec Python @Mac
Applications avec PyOpenCL (PIL et PyOpenGL)
Reconnaissance d'image avec Keras + OpenCV
Fonctionne avec Python et R