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()

Creative Commons Lizenzvertrag     Dieses Werk von Marvin Kastner ist lizenziert unter einer Creative Commons Namensnennung 4.0 International Lizenz.