Eine Geschichte über Bildverarbeitung und Zeichnen durch reine Matrixberechnung, ohne auf die Bildverarbeitungsbibliothek angewiesen zu sein. Auch mit Pythonista möglich
** Klicken Sie hier für Grundlagen **
Anstatt mich auf Open CV oder Pillow zu verlassen, werde ich tatsächlich verschiedene Bildverarbeitungen mit numpy und matplotlib schreiben. Diese Kombination kann auch mit der iOS-App Pythonista verwendet werden.
import numpy as np
import matplotlib.pyplot as plt
Darüber hinaus sind die folgenden Funktionen zum Anzeigen von Bildern praktisch. (Einzelheiten finden Sie unter Grundlagen)
def img_show(img : np.ndarray, cmap = 'gray', vmin = 0, vmax = 255, interpolation = 'none') -> None:
'''np.Zeigen Sie ein Bild mit Array als Argument an.'''
#Setzen Sie dtype auf uint8
img = np.clip(img,vmin,vmax).astype(np.uint8)
#Bild anzeigen
plt.imshow(img, cmap = cmap, vmin = vmin, vmax = vmax, interpolation = interpolation)
plt.show()
plt.close()
Um eine Figur zu zeichnen, verwenden Sie msgid, um die Koordinaten auf dem Bild zu erhalten.
x, y = np.mgrid[:100,:100]
Beachten Sie, dass die positive Richtung von $ x $ nach unten und die positive Richtung von $ y $ richtig ist.
x, y = np.mgrid[:100,:100]
x_0, y_0 = (50, 60) #Zentraler Punkt
x_size, y_size = (10, 20) #Die Größe des Rechtecks
#Zeichne ein Rechteck
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 $ wird verwendet.
x, y = np.mgrid[:100,:100]
x_0, y_0 = (20, 40) #Zentraler Punkt
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)
Ich habe versucht, die Fehlerfunktion von Bresenhams Algorithmus zu verwenden.
Angenommen, Sie möchten eine gerade Linie M zeichnen: $ ax + by + c = 0 $. Wenn Sie die Bedingung $ a \ geq -b \ geq 0, a> 0 $ festlegen, können Sie für jede Spalte einen Punkt zeichnen und die gerade Linie M approximieren. Mit anderen Worten, für jedes $ y $ müssen Sie nur ein $ x $ auswählen, das nahe genug an M liegt.
Sei A: $ (x_1, y_1) $ der Mittelpunkt eines Pixels Betrachtet man Punkt B: $ \ left (- \ frac {b} {a} y- \ frac {c} {a}, y_1 \ right) $ auf M, wobei $ y $ -Koordinaten für diesen Punkt A übereinstimmen Die $ x $ -Koordinatendifferenz $ e $ beträgt $ - \ frac {b} {a} y_1- \ frac {c} {a} -x_1 $. Dann kann die Bedingung, dass sie nahe genug an M liegt, als $ 0,5 \ leq e <0,5 $ geschrieben werden. Weil sich der gleiche Punkt A und der gleiche Punkt B im selben Pixel befinden.
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)
Wenn Sie Gleitkommatypen nicht mögen, multiplizieren Sie $ e $ mit $ 2a $. Die Bedingung, dass es nahe genug an M liegt, kann als $ -a \ leq e <a $ geschrieben werden.
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)
Unter der Annahme, dass $ a == 0 \ land b == 0 $ nicht existiert und $ a \ geq -b \ geq 0, a> 0 $ nicht berücksichtigt wird, ist der folgende Algorithmus geeignet. ..
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)
Die von diesem Algorithmus erzeugten Zahlen sind die gleichen wie die von Bresenhams Algorithmus erzeugten.
Ich habe es selbst gemacht. ** Klicken Sie hier für Details **
Das Obige zeichnet $ -3x-7y + 60 = 0 $ auf einer quadratischen 1000-Pixel-Figur. Das Folgende ist eine gerade Linie, die mit dem Bresenham-Algorithmus erstellt wurde.
Recommended Posts