Hallo!
Mir war mal wieder langweilig deshalb habe ich hier ein kleines Skript, welches die aktuellen Wind- und Temperaturverhältnisse der Außenalster (Hamburg) von einen Webcam-Foto (http://alsterwetter.de/) ausliest und ausgibt, geschrieben: http://www.python-forum.de/pastebin.php?mode=view&s=269
Über konstruktive Kritik würde ich mich sehr freuen.
VG
microkernel
Alsterwetter.de: Daten aus Foto lesen
- microkernel
- User
- Beiträge: 271
- Registriert: Mittwoch 10. Juni 2009, 17:27
- Wohnort: Frankfurt
- Kontaktdaten:
- microkernel
- User
- Beiträge: 271
- Registriert: Mittwoch 10. Juni 2009, 17:27
- Wohnort: Frankfurt
- Kontaktdaten:
Hat keiner etwas anzumerken? Niemanden stört Zeile 65?
Prinzipiell ist das Problem auch gar nicht schlecht gelöst. Einige Dinge könnten jedoch noch anders gelöst werden.
- BLOCKCOUNT_TO_CHAR würde ich Ordnen, dann sieht es nicht ganz so nach Chaos aus.
- DATA_LINES könnte in der jetztigen Form auch einfach eine Liste mit den Namen sein, die angegebene Nummerierung ergibt sich aus den Indizes. In Zeile 65 schießt du dir natürich selber in den Fuß, da du die 5 hart in den Code schreibst. Da wirst du in vier Wochen nicht mehr wissen, was gemeint ist. Benutze also ein Dictionary. Zu jeder Zeile müsstest du zusätlich noch eine Methode angeben, auf welchem Weg die Daten extrahiert werden sollen.
- Der Klasse CHAR_SIZE solltest du ruhig drei Zeilen können, alles in eine Zeile zu quetschen ist nicht notwendig. Den Kommentar kannst du dir auch sparen.
- AlsterWetterShot sollte von ``object`` erben.
- ``if not fp: fp = self.__get()`` solltest du auch in zwei Zeilen teilen. Wahrscheinlich meinst du auch nicht ``if not fp`` sondern ``if fp is not None``.
- ``__get`` steht nicht für "privat", hier reicht ein Unterstrich vollkommen aus. Eigentlich kannst du die Funktion auch einfach ``get`` nennen, da sie von außen gefahrlos aufgerufen werden kann. Allerdigs ist "get" (oder "_get" oder "__get") ein schlechter Name. Man kann aus dem Namen nicht schließen, was die Funktion liefert.
- ``stream`` sollte auch wieder geschlossen werden.
- ``line = lineno * 8; out = ''`` sollte wieder in zwei Zeilen geteil werden.
- ``column = int()`` lässt sich schöner als ``column = 0`` ausdrücken.
- ``out`` sollte ein Liste sein, welche du später mit ``"".join(out)`` zu einem String zusammensetzt.
- Zeile 63 ist natürlich ein Chaos und der Reguläre Ausdruck sollte besser an die Klasse ausgelagert werden. Dann kann man ihn auch vorher kompilieren.
- Zeile 65 sollte aufgeteilt werden. Hinzu kommt, dass du die "magic numbers" loswerden solltest. Das lässt sich mit String-Operationen sicher besser lösen.
- Insgesamt fehlt natürlich bei dir jegliche Fehlerbehandlung. Was passiert, wenn das Bild nicht geladen werden kann oder wenn die Daten nicht mehr zuverlässig gefunden werden?
- ``readhead`` sollte in zwei Funktionen aufgeteilt werden. Zum einen das lesen der "normalen" Information, zum anderen das Lesen der Zeit. Weiter obenen habe ich ja bereits etwas dazu geschrieben.
- Und natürlich stellt sich die Frage, ob hier die Klasse wirklich angebracht ist. Wenn die Einzige Verwendung in der Form ``AlsterWetterShot().readhead()``liegt, dann ist das ein Zeichen, dass nur eine Funktion benötigt wird. Etwas besser wird es, wenn das ``readhead`` in der ``__init__``-Methode durchgeführt wird und man von außen auf die gelesenen Daten zugreift. Der Favorit bleibt aber weiterhin die Funktion.
Das sieht jetzt nach vielen Punkten aus, die sind jetzt aber alle nicht besonders dramatisch. Gut finde ich den Ansatz der Erkennung der einzelnen Symbole, das hast du recht geschickt gelöst. Da könnte man natürlich noch beliebieg verfeinern. Aber wozu der Aufwand, wenn es funktioniert.
Sebstian
- BLOCKCOUNT_TO_CHAR würde ich Ordnen, dann sieht es nicht ganz so nach Chaos aus.
- DATA_LINES könnte in der jetztigen Form auch einfach eine Liste mit den Namen sein, die angegebene Nummerierung ergibt sich aus den Indizes. In Zeile 65 schießt du dir natürich selber in den Fuß, da du die 5 hart in den Code schreibst. Da wirst du in vier Wochen nicht mehr wissen, was gemeint ist. Benutze also ein Dictionary. Zu jeder Zeile müsstest du zusätlich noch eine Methode angeben, auf welchem Weg die Daten extrahiert werden sollen.
- Der Klasse CHAR_SIZE solltest du ruhig drei Zeilen können, alles in eine Zeile zu quetschen ist nicht notwendig. Den Kommentar kannst du dir auch sparen.
- AlsterWetterShot sollte von ``object`` erben.
- ``if not fp: fp = self.__get()`` solltest du auch in zwei Zeilen teilen. Wahrscheinlich meinst du auch nicht ``if not fp`` sondern ``if fp is not None``.
- ``__get`` steht nicht für "privat", hier reicht ein Unterstrich vollkommen aus. Eigentlich kannst du die Funktion auch einfach ``get`` nennen, da sie von außen gefahrlos aufgerufen werden kann. Allerdigs ist "get" (oder "_get" oder "__get") ein schlechter Name. Man kann aus dem Namen nicht schließen, was die Funktion liefert.
- ``stream`` sollte auch wieder geschlossen werden.
- ``line = lineno * 8; out = ''`` sollte wieder in zwei Zeilen geteil werden.
- ``column = int()`` lässt sich schöner als ``column = 0`` ausdrücken.
- ``out`` sollte ein Liste sein, welche du später mit ``"".join(out)`` zu einem String zusammensetzt.
- Zeile 63 ist natürlich ein Chaos und der Reguläre Ausdruck sollte besser an die Klasse ausgelagert werden. Dann kann man ihn auch vorher kompilieren.
- Zeile 65 sollte aufgeteilt werden. Hinzu kommt, dass du die "magic numbers" loswerden solltest. Das lässt sich mit String-Operationen sicher besser lösen.
- Insgesamt fehlt natürlich bei dir jegliche Fehlerbehandlung. Was passiert, wenn das Bild nicht geladen werden kann oder wenn die Daten nicht mehr zuverlässig gefunden werden?
- ``readhead`` sollte in zwei Funktionen aufgeteilt werden. Zum einen das lesen der "normalen" Information, zum anderen das Lesen der Zeit. Weiter obenen habe ich ja bereits etwas dazu geschrieben.
- Und natürlich stellt sich die Frage, ob hier die Klasse wirklich angebracht ist. Wenn die Einzige Verwendung in der Form ``AlsterWetterShot().readhead()``liegt, dann ist das ein Zeichen, dass nur eine Funktion benötigt wird. Etwas besser wird es, wenn das ``readhead`` in der ``__init__``-Methode durchgeführt wird und man von außen auf die gelesenen Daten zugreift. Der Favorit bleibt aber weiterhin die Funktion.
Das sieht jetzt nach vielen Punkten aus, die sind jetzt aber alle nicht besonders dramatisch. Gut finde ich den Ansatz der Erkennung der einzelnen Symbole, das hast du recht geschickt gelöst. Da könnte man natürlich noch beliebieg verfeinern. Aber wozu der Aufwand, wenn es funktioniert.
Sebstian
Das Leben ist wie ein Tennisball.
Hallo nochmals,
funktioniert bei mir nun auch. Es war ein formatierungsproblem.
aber ich hätte ein generelle frage:
werden die Daten aus einem Bild gelesen? oder sind die daten im Bild als String versteckt der dann nu ausgelesen werden muss?
könnte ich stattdessen z.B auch ein Ortsschild fotografieren und den Namen auslesen lassen?
funktioniert bei mir nun auch. Es war ein formatierungsproblem.
aber ich hätte ein generelle frage:
werden die Daten aus einem Bild gelesen? oder sind die daten im Bild als String versteckt der dann nu ausgelesen werden muss?
könnte ich stattdessen z.B auch ein Ortsschild fotografieren und den Namen auslesen lassen?
- microkernel
- User
- Beiträge: 271
- Registriert: Mittwoch 10. Juni 2009, 17:27
- Wohnort: Frankfurt
- Kontaktdaten:
Nein, die Daten sind nicht als "String" oder ähnliches im Bild gespeichert. Das Snippet liest sozusagen die Daten vom Bild ab.erdmulch hat geschrieben:aber ich hätte ein generelle frage:
werden die Daten aus einem Bild gelesen? oder sind die daten im Bild als String versteckt der dann nu ausgelesen werden muss?
In diesem Fall nein, da das Snippet speziell auf das gerenderte Bild der Webcam angepasst ist, wo sich die Daten immer an der gleichen Stelle in der gleichen Größe und etc. befinden. Dass, wonach du wahrscheinlich gerade suchst, nennt sich ORC (http://de.wikipedia.org/wiki/Texterkennung)erdmulch hat geschrieben:könnte ich stattdessen z.B auch ein Ortsschild fotografieren und den Namen auslesen lassen?