Une histoire sur le traitement d'image et le dessin par juste calcul matriciel sans compter sur la bibliothèque de traitement d'image. Également possible avec Pythonista
** Cliquez ici pour les informations de base **
Au lieu de m'appuyer sur Open CV ou Pillow, j'écrirai en fait divers traitements d'images en utilisant numpy et matplotlib. C'est une combinaison qui peut également être utilisée avec l'application iOS Pythonista.
import numpy as np
import matplotlib.pyplot as plt
De plus, les fonctions suivantes sont pratiques pour afficher des images. (Pour plus de détails, Basics)
def img_show(img : np.ndarray, cmap = 'gray', vmin = 0, vmax = 255, interpolation = 'none') -> None:
'''np.Afficher une image avec un tableau comme argument.'''
#Définissez dtype sur uint8
img = np.clip(img,vmin,vmax).astype(np.uint8)
#Afficher l'image
plt.imshow(img, cmap = cmap, vmin = vmin, vmax = vmax, interpolation = interpolation)
plt.show()
plt.close()
Pour dessiner une figure, utilisez msgid pour obtenir les coordonnées sur l'image.
x, y = np.mgrid[:100,:100]
Notez que la direction positive de $ x $ est vers le bas et la direction positive de $ y $ est correcte.
x, y = np.mgrid[:100,:100]
x_0, y_0 = (50, 60) #Point central
x_size, y_size = (10, 20) #La taille du rectangle
#Dessinez un rectangle
rect = ((2*abs(x - x_0) < x_size) & (2*abs(y - y_0) < y_size)).astype(np.uint8)
img_show(rect*255)
$ \ frac {(x-x_0) ^ 2} {a ^ 2} + \ frac {(y-y_0) ^ 2} {b ^ 2} --1 <0 $ est utilisé.
x, y = np.mgrid[:100,:100]
x_0, y_0 = (20, 40) #Point central
a, b = (5, 10)
ellipse = ((x - x_0)**2/a**2 + (y - y_0)**2/b**2 - 1<0).astype(np.uint8)
img_show(ellipse*255)
J'ai essayé d'utiliser la fonction d'erreur de l'algorithme de Bresenham.
Supposons que vous vouliez tracer une ligne droite M: $ ax + by + c = 0 $. Si vous définissez la condition $ a \ geq -b \ geq 0, a> 0 $, vous pouvez dessiner un point pour chaque colonne et approcher la ligne droite M. En d'autres termes, pour chaque $ y $, il suffit de choisir un $ x $ suffisamment proche de M.
Soit A: $ (x_1, y_1) $ le point central d'un pixel Considérant le point B: $ \ left (- \ frac {b} {a} y- \ frac {c} {a}, y_1 \ right) $ sur M où les coordonnées $ y $ correspondent, pour ce point A La différence entre les coordonnées $ x $ $ e $ est $ - \ frac {b} {a} y_1- \ frac {c} {a} -x_1 $. Ensuite, la condition qu'il soit suffisamment proche de M peut s'écrire $ 0,5 \ leq e <0,5 $. Parce que le même point A et le même point B sont dans le même pixel.
x,y = np.mgrid[:5,:5]
a,b,c = 2,-1,-1
e = -(b/a)*y-c/a-x
#array([[ 0.5, 1. , 1.5, 2. , 2.5],
# [-0.5, 0. , 0.5, 1. , 1.5],
# [-1.5, -1. , -0.5, 0. , 0.5],
# [-2.5, -2. , -1.5, -1. , -0.5],
# [-3.5, -3. , -2.5, -2. , -1.5]])
line = ((-0.5<=e)&(e<0.5)).astype(np.uint8)
#array([[0, 0, 0, 0, 0],
# [1, 1, 0, 0, 0],
# [0, 0, 1, 1, 0],
# [0, 0, 0, 0, 1],
# [0, 0, 0, 0, 0]], dtype=uint8)
img_show(line*255)
Si vous n'aimez pas les types à virgule flottante, multipliez $ e $ par $ 2a $. La condition qu'il soit suffisamment proche de M peut être écrite comme $ -a \ leq e <a $.
x,y = np.mgrid[:20,:20]
a,b,c = 2,-1,-1
e = 2*(-b*y-c-a*x)
line = ((-a<=e)&(e<a)).astype(np.uint8)
img_show(line*255)
Enfin, en supposant que $ a == 0 \ land b == 0 $ n'existe pas et que $ a \ geq -b \ geq 0, a> 0 $ n'est pas pris en compte, l'algorithme suivant est approprié. ..
x,y = np.mgrid[:20,:20]
a,b,c = 13,14,-200
e = 2*(-b*y-c-a*x)
threshold = max(abs(a),abs(b))
line = ((-threshold<=e)&(e<threshold)).astype(np.uint8)
img_show(line*255)
Les chiffres produits par cet algorithme sont les mêmes que ceux produits par l'algorithme de Bresenham.
Je l'ai fait moi-même. ** Cliquez ici pour plus de détails **
Ce qui précède dessine $ -3x-7y + 60 = 0 $ sur une figure carrée de 1000 pixels. Ce qui suit est une ligne droite créée par l'algorithme de Bresenham.
Recommended Posts