Erprobe Ziffernerkennung¶
Hier wird der Code aus dem Notebook „02 Erkennung von Ziffern.ipynb“ geladen. Die trainierte Ziffernerkennung wird in eine Anwendung eingebettet.
[ ]:
%%capture
%run "02 Erkennung von Ziffern.ipynb"
[ ]:
print(f"Genauigkeit von k nächste Nachbarn: {neigh.score(X_test, y_test):.02%}")
print(f"Genauigkeit vom Random Forest: {clf.score(X_test, y_test):.02%}")
Bette diese Prädiktoren nun in eine Anwendung ein.
[ ]:
import PIL
import PIL.ImageDraw
import tkinter
import numpy as np
Skaliere Bild auf 8x8 Pixel und wandle es in einen 1d-Array um, damit es als Eingabe für die ML-Algorithmen verwendet werden kann.
[ ]:
def resize_image(pil_image):
"resizes a PIL image to 8x8 pixels and scales the intensity values to 0..16"
resized_digit_image = pil_image.resize((8, 8), PIL.Image.Resampling.LANCZOS)
resized_digit_array = np.array(resized_digit_image)
new_100_percent = np.partition(resized_digit_array.flatten(), -9)[-9]
rescaled_digit_repr = (
(resized_digit_array - resized_digit_array.min()) / (new_100_percent - resized_digit_array.min())
) * 16
np.clip(rescaled_digit_repr, 0, 16, out=rescaled_digit_repr)
return rescaled_digit_repr
Definiere eine kleine einfache Tkinter-Anwendung für eine Zifferneingabe.
[ ]:
class App:
width = 300
height = 300
output_image = PIL.Image.new("L", (width, height))
center = height // 2
white = (255, 255, 255)
def __init__(self):
self.main = tkinter.Tk()
self.canvas = tkinter.Canvas(self.main, width=self.width, height=self.height, bg='white')
self.canvas.pack()
self.draw = PIL.ImageDraw.Draw(self.output_image)
self.canvas.pack(expand=tkinter.YES, fill=tkinter.BOTH)
self.canvas.bind("<B1-Motion>", self.paint)
button_left = tkinter.Button(text="predict", command=self.execute_estimator)
button_left.pack(side='left')
button_right = tkinter.Button(text="clear", command=lambda: [
self.canvas.delete("all"), self.label_text_link.set("\n")])
button_right.pack(side='left')
self.label_text_link = tkinter.StringVar()
self.label_text_link.set("\n")
label = tkinter.Label(self.main, textvariable=self.label_text_link)
label.pack()
def paint(self, event):
x1, y1 = (event.x - 1), (event.y - 1)
x2, y2 = (event.x + 1), (event.y + 1)
self.canvas.create_oval(x1, y1, x2, y2, fill="white", width=5)
self.draw.line([x1, y1, x2, y2], fill="white", width=5)
def execute_estimator(self):
rescaled_digit_repr = resize_image(self.output_image)
plt.imshow(rescaled_digit_repr)
plt.show()
try:
digit_category_rf = clf.predict([rescaled_digit_repr.flatten()])
digit_category_knn = neigh.predict([rescaled_digit_repr.flatten()])
prediction_output_as_text = f"RF predicted: {digit_category_rf[0]}\nKNN predicted: {digit_category_knn[0]}"
except ValueError as e:
prediction_output_as_text = f"Encountered a problem:\n{str(e)[:20]}..."
print(prediction_output_as_text)
self.label_text_link.set(prediction_output_as_text)
self.output_image = PIL.Image.new("L", (self.width, self.height))
self.draw = PIL.ImageDraw.Draw(self.output_image)
def run(self):
self.main.mainloop()
Starte Tkinter-Applikation. Diese geht in einem neuen Fenster auf, welches unabhängig vom Browser ist, in welchem dieses Jupyter Notebook angezeigt wird. Die Applikation ist ein kleines Fenster, in dem man mit der Maus Ziffern schreiben kann. Mit dem Klick auf predict
werden dann die ML-Modelle zur Vorhersage genutzt. Unten wird für jede Vorhersage die Umwandlung des Inputs als 8x8-Matrix angezeigt.
[ ]:
App().run()
Dieses Werk von Marvin Kastner ist lizenziert unter einer Creative Commons Namensnennung 4.0 International Lizenz.