{"id":436,"date":"2018-05-31T19:51:47","date_gmt":"2018-05-31T17:51:47","guid":{"rendered":"https:\/\/lobo.mensa.uberspace.de\/wp\/?p=436"},"modified":"2018-06-16T02:06:59","modified_gmt":"2018-06-16T00:06:59","slug":"stroemende-tensoren-teil-3","status":"publish","type":"post","link":"https:\/\/lobo.uber.space\/wp\/?p=436","title":{"rendered":"Str\u00f6mende Tensoren \u2013 Teil 3"},"content":{"rendered":"<div class=\"ArtikelSerie\">\r\nDies ist der dritte Teil der Artikelserie <em>Str\u00f6mende Tensoren<\/em>.\r\n<ul class=\"ArtikelListe\">\r\n<li><a href=\"https:\/\/lobo.mensa.uberspace.de\/wp\/?p=341\">Teil 1<\/a><\/li>\r\n<li><a href=\"https:\/\/lobo.mensa.uberspace.de\/wp\/?p=386\">Teil 2<\/a><\/li>\r\n<li><a href=\"https:\/\/lobo.mensa.uberspace.de\/wp\/?p=436\">Teil 3<\/a><\/li>\r\n<li><a href=\"https:\/\/lobo.mensa.uberspace.de\/wp\/?p=460\">Teil 4<\/a><\/li>\r\n<\/ul>\r\n<\/div>\n<p>Nun baue ich mir ein kleines GUI, mit dem ich die Daten verwalte und die Eingabe und Verifikation der Daten etwas vereinfachen m\u00f6chte.<\/p>\n<p>Es soll auf jeden Fall ein Bild angezeigt werden. Auf dem Bild soll die Position des W\u00fcrfels angezeigt werden. Zus\u00e4tzlich wird mindestens eine Eingabe f\u00fcr den Wert ben\u00f6tigt, den der W\u00fcrfel auf dem Bild anzeigt und ein Knopf um ein weiteres Bild mit der Kamera zu machen.<\/p>\n<p><!--more--><\/p>\n<p>F\u00fcr den Anfang f\u00fcge ich noch die Position als Eingabefelder und eine Liste von Bildern hinzu. Des weiteren Kn\u00f6pfe um das aktuelle Bild dem neuronalen Netzwerk zu f\u00fcttern, um die ge\u00e4nderten Daten in die Liste zu \u00fcbernehmen und um eine Trainingsiteration des Netzwerks zu starten.<\/p>\n<p>Der erste Entwurf sieht also im Qt-Designer folgenderma\u00dfen aus: <img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/lobo.mensa.uberspace.de\/wp\/wp-content\/uploads\/2018\/05\/2018-05-29_10-09-10-300x258.png\" alt=\"MainWindow im Designer\" width=\"350\" height=\"301\" class=\"ImageFloatRight alignnone size-medium wp-image-437\" srcset=\"https:\/\/lobo.uber.space\/wp\/wp-content\/uploads\/2018\/05\/2018-05-29_10-09-10-300x258.png 300w, https:\/\/lobo.uber.space\/wp\/wp-content\/uploads\/2018\/05\/2018-05-29_10-09-10.png 448w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/p>\n<p>Im linken Bereich wird das Bild zu sehen sein, im Feld zwischen den Kn\u00f6pfen \u201eChange Data\u201d und \u201eTrain\u201d wird die Liste der Bilder angezeigt.<\/p>\n<p>Mit PyQt5 bekommt man in Python sehr schnell ein GUI zusammengebaut. Im Qt-Designer zieht man sich die Elemente seines Fensters zusammen und \u00fcbersetzt dann das resultierende XML-File mit pyuic3 in Python-Code.<\/p>\n<p>Diesen bindet man einfach in sein Programm ein, hier \u00fcber <code class=\"codecolorer python blackboard\"><span class=\"python\"><span class=\"kw1\">from<\/span> main_window <span class=\"kw1\">import<\/span> Ui_main_window<\/span><\/code>, leitet von der entsprechenden Qt-Klasse ab und bindet die erzeugte Klasse ein:<\/p>\n<div class=\"codecolorer-container python blackboard\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/><\/div><\/td><td><div class=\"python codecolorer\"><span class=\"kw1\">class<\/span> MainWindow <span class=\"br0\">&#40;<\/span>QtWidgets.<span class=\"me1\">QMainWindow<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">def<\/span> <span class=\"kw4\">__init__<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span><span class=\"br0\">&#41;<\/span>:<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; QtWidgets.<span class=\"me1\">QMainWindow<\/span>.<span class=\"kw4\">__init__<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">self<\/span>.<span class=\"me1\">ui<\/span> <span class=\"sy0\">=<\/span> Ui_main_window <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">self<\/span>.<span class=\"me1\">ui<\/span>.<span class=\"me1\">setupUi<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span><span class=\"br0\">&#41;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>Das so erzeugte Ger\u00fcst mu\u00df nun nat\u00fcrlich noch mit Leben gef\u00fcllt werden. Dazu werden die entsprechenden Signale der Elemente mit den Methoden verbunden welche die entsprechenden Aktionen ansto\u00dfen. Dies geschieht durch einfache Aufrufe in der Init-Methode: <code class=\"codecolorer python blackboard\"><span class=\"python\"><span class=\"kw2\">self<\/span>.<span class=\"me1\">ui<\/span>.<span class=\"me1\">snap_image_btn<\/span>.<span class=\"me1\">clicked<\/span>.<span class=\"me1\">connect<\/span> <span class=\"br0\">&#40;<\/span><span class=\"kw2\">self<\/span>.<span class=\"me1\">snapImageClicked<\/span><span class=\"br0\">&#41;<\/span><\/span><\/code>. Klickt der Benutzer nun auf den Knopf \u201eSnap Image\u201d wird die Methode <code class=\"codecolorer python blackboard\"><span class=\"python\">snapImageClicked<\/span><\/code> der Klasse <code class=\"codecolorer python blackboard\"><span class=\"python\">MainWindow<\/span><\/code> aufgerufen.<\/p>\n<p>F\u00fcr die Liste der Bilder verwende ich hier das Model\/View Konzept von Qt. Als darstellende Klasse wird ein <a href=\"http:\/\/doc.qt.io\/qt-5\/QTreeView.html\"><code class=\"codecolorer python blackboard\"><span class=\"python\">QTreeView<\/span><\/code><\/a> verwendet. Ich m\u00f6chte hier zwar keine Baumstruktur darstellen sondern nur eine Liste, das wird von dieser Klasse jedoch genauso unterst\u00fctzt und sie bietet mir auf einfache Art die M\u00f6glichkeit, da\u00df immer eine ganze Zeile selektiert wird, mehrere Spalten angezeigt werden und ein Header existiert.<\/p>\n<p>Die Daten werden dementsprechend in einer von <a href=\"http:\/\/doc.qt.io\/qt-5\/QStandardItemModel.html\"><code class=\"codecolorer python blackboard\"><span class=\"python\">QStandardItemModel<\/span><\/code><\/a> abgeleitete Klasse verwaltet. In C++ w\u00fcrde man hier ein <a href=\"http:\/\/doc.qt.io\/qt-5\/QAbstractItemModel.html\"><code class=\"codecolorer python blackboard\"><span class=\"python\">QAbstractItemModel<\/span><\/code><\/a> verwenden. In Python ist dies leider nicht m\u00f6glich, da das Konzept von pur virtuellen Methoden und damit von abstrakten Klassen nicht existiert.<br \/>\nIch verwende einfach nicht die Methode <code class=\"codecolorer python blackboard\"><span class=\"python\">setItem<\/span><\/code> des <a href=\"http:\/\/doc.qt.io\/qt-5\/QStandardItemModel.html\"><code class=\"codecolorer python blackboard\"><span class=\"python\">QStandardItemModel<\/span><\/code><\/a> sondern \u00fcberlade die Methoden <code class=\"codecolorer python blackboard\"><span class=\"python\">data<\/span><\/code> und <code class=\"codecolorer python blackboard\"><span class=\"python\">headerData<\/span><\/code> um die entsprechenden Eintr\u00e4ge der verwalteten Daten und der \u00dcberschriften f\u00fcr die Anzeige zur\u00fcck zu geben.<\/p>\n<p>Die Liste der Bilder mit ihren zugeh\u00f6rigen Werten sind in einer JSON-formatierten Datei gespeichert. Die Dateinamen der Bilder beziehen sich in dieser Datei immer auf das Verzeichnis, in dem die Datei steht.<\/p>\n<p>Eine solche Liste kann \u00fcber die Men\u00fcpunkte des File-Men\u00fcs geladen und gespeichert werden.<\/p>\n<p>Um bei weiteren Programml\u00e4ufen den Dateidialog wieder im zuletzt benutzten Verzeichnis zu \u00f6ffnen, habe ich mir eine kleine Konfigurationsklasse gebaut, die das zuletzt benutzte Verzeichnis verwaltet und seine Daten in eine Konfigurationsdatei absenken und aus ihr laden kann (bisher \u00fcber das Pythonmodul pickle, jedoch werde das noch umbauen auf JSON). Hier werden in Zukunft noch weitere Konfigurationsdaten des Programms landen.<\/p>\n<p>Im n\u00e4chsten Teil werde ich mich vermutlich um die Aufnahme eines Bildes k\u00fcmmern. Dies soll, \u00fcber das Netzwerk angesto\u00dfen, auf einem Raspberry-Pi geschehen. Es wird also n\u00f6tig sein, \u00fcber ssh ein Kommando auf einem entfernten Rechner anzusto\u00dfen und das Bild vorzugsweise \u00fcber Std-Out der SSH-Verbindung auf den anfragenden Rechner zu \u00fcbertragen.<\/p>\n<p><a href=\"https:\/\/lobo.mensa.uberspace.de\/wp\/?p=460\">Zum vierten Teil<\/a><\/p>\n<div class=\"LinkListe\">\r\n<p>Links zu weiterf\u00fchrenden Informationen dieser Artikelserie:<\/p>\r\n<ul>\r\n<li><a href=\"https:\/\/gitlab.com\/Azador\/dice\">Dice - die Quellen dieses Projekts auf GitLab<\/a><\/li>\r\n<li><a href=\"https:\/\/www.tensorflow.org\/\">TensorFlow<\/a><\/li>\r\n<li><a href=\"http:\/\/www.dkriesel.com\/science\/neural_networks\">D. Kriesel \u00fcber Neuronale Netzwerke<\/a><\/li>\r\n<li><a href=\"http:\/\/doc.qt.io\/qt-5\/\">Qt5 API<\/a><\/li>\r\n<\/ul>\r\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Nun baue ich mir ein kleines GUI, mit dem ich die Daten verwalte und die Eingabe und Verifikation der Daten etwas vereinfachen m\u00f6chte. Es soll auf jeden Fall ein Bild angezeigt werden. Auf dem Bild soll die Position des W\u00fcrfels angezeigt werden. Zus\u00e4tzlich wird mindestens eine Eingabe f\u00fcr den Wert ben\u00f6tigt, den der W\u00fcrfel auf &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/lobo.uber.space\/wp\/?p=436\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eStr\u00f6mende Tensoren \u2013 Teil 3\u201c<\/span> weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[64,63,9],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=\/wp\/v2\/posts\/436"}],"collection":[{"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=436"}],"version-history":[{"count":15,"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=\/wp\/v2\/posts\/436\/revisions"}],"predecessor-version":[{"id":493,"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=\/wp\/v2\/posts\/436\/revisions\/493"}],"wp:attachment":[{"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=436"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=436"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lobo.uber.space\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=436"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}