Unzumutbar langsam

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

pythontester hat geschrieben:Puh ihr habt schon mein Pythoncode und den daemlichen C/C++ Aqualanzcode zerpflueckt. Da wird mein C mit C++ ANleihen Code noch mehr zerrissen.

Ich habe sowas nie studiert, das was ich kann erlesen oder ergoogled. Mir ist es es etwas befremdlich, warum Anfanger und Amateure hier so zerrissen werden.
Wenn die Anfaenger und Amateure sich erst einmal auskotzen darueber, wie bloed Python ist, sollte das nicht wundern, oder?

Dein Code ist - jenseits aller formalen Bemerkungen - schon alleine hierdurch schwierig:

Code: Alles auswählen

 raw_pixel_list = numpy.array(png_dest.getdata())
Dadurch wird jedes der >1000000 Pixel einmal in die Python-Welt reingezerrt, was bedeutet aus einem 4-Byte-Wert eine komplexe Python-Struktur zu machen, das ganze in eine Liste von Tupeln gesteckt, um danach wieder auseinandergedroeselt zu werden, um in eine effiziente C-Struktur gewandelt zu werden. Das alleine dauert auf meinem MacBook Air ~2 Sekunden, auf meinem PI2 14.

Der folgende Code, basieren auf opencv, welches das Bild gleich als Numpy-Array liefert, braucht auf dem PI 2 Sekunden!!!

Code: Alles auswählen

import sys
import cv2

image = cv2.imread(sys.argv[1])
print(type(image))
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Ich hab mich gestern abend nochmal damit auseinander gesetzt.

Bei der C/C++ Variante, ist es wohl wirklich effizienter, nich alle 1 024 000 Pixel in ein neues grosses array zu packen, sondern mit einer Funktion ?!? die Bytes aus dem Vector mit dem Byte aus dem anderen Vector zu vergleichen. Damit muss kein riesen Array vergehalten werden. Und das ganze casten per sstringstream oder sprintf entfaellt. Immerhin war die Datei imdem das gesamte Array gespeichert wurde fast 25MB gross, das bedeudet doch auch 25MB Arbeitspeicher?!?

In Python fand ich keine Funktion in der PIL,sondern nur diese getdata Funktion. Opencv ist leider schlecht dokumentiert. Wie ist es denn in Python? Liefert getdata evtl. auch nur reine Bytes?

Wir wollen ja Vergleiche, indem beide Programme das identische verarbeiten.

Aber im Ansatz sollte man versuchen, keine aufgeblasenen Daten auf einmal in ein Programm zu verarbeiten, sondern zugunsten der Effizenz und des Speichers, diese Daten nur bei Bedarf zu erzeugen bzw. zu vergleichen.

Immerhin wurde die Arbeistspeichernutzung rund 60MB gross, was einfach etwas viel ist.

Das heisst ich muesste ja auch ein bytearray in python erstellen, um das ganze Overhead zu vermeiden.

Egal wie das jetzt endet, ich hab dieses simple Bild in Bild suchen und Bild "menschlich lesbar" kraeftig unterschaetzt. Dieses Array erstellen, kann numpy mit reshape als Befehl.

Aber ein Nachteil hat Python jetzt wirklich, der Programmierer muss sich viel mehr im klaren sein, was er an Datentypen braucht, und welche schnell zu verarbeiten sind.

Was ich recht interessant fand, war diese Seite. https://waymoot.org/home/python_string/ . Was in mein Fall ja bedeuten wuerden, das es sinnvoller waere, das mein "0000001 000:255:128:255" schneller zu verarbeiten waere, wenn ich alle Werte per Liste erfasse und dann per join in an den String haenge.

Es fehlt halt das kluge Koepfchen, der Compiler, der Codeoptimierungen vornimmt. Bei Python muss der Entwickler mehr beruecksichtigen.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

OpenCV ist eine der eher besser dokumentierten Open Source Projekte da draussen, und es gibt eine Vielzahl von Tutorials und Beispielen. Python & C++. Habe ich aber schon drauf verwiesen.

Mit der OpenCV kannst du auch problemlos Ausschnitte aus Bildern definieren, die dann speichereffizient nur mit einer Referenz zu dem darunter liegenden grossen Array arbeiten, usw.

Auch die diversen notwendigen Wandlungen wie zB nach graustufen/float die fuer viel CV-Algorithmik benoetigt werden sind natuerlich schon vorhanden - willst du das alles selbst schreiben?
BlackJack

@pythontester: Mir ist immer noch nicht klar was diese Umwandlung aller Pixel in Zeichenketten eigentlich soll? Warum machst Du das?

Ein `PIL.Image` kann man in ein Numpy-Array umwandeln in dem man einfach die `numpy.array()`-Funktion damit aufruft.

OpenCV ist schlecht dokumentiert? Ich finde die API ist ganz gut dokumentiert. Das Thema ist halt nicht gerade einfach, also wird man sich noch einiges an Wissen ausserhalb anlesen müssen, je nach dem was man machen möchte. Die Dokumentation enthält auch Links zu weiterführenden Tutorials.

Ob 60 MiB Arbeitsspeicher viel oder wenig ist, hängt davon ab was man macht und welche Daten im Speicher liegen (müssen). Wobei ich mich hier gerade wieder Frage ob wir gerade wieder von Pixeln reden die als für Menschen ”lesbare” Zeichenketten vorliegen, wieder mit der Frage verbunden wozu zur Hölle man das brauchen sollte.

Auch in C oder C++ musst Du Dir über die Datentypen und Operationen und deren Speicherverbrauch und Laufzeitkomplexität im klaren sein, wie Dein auskommentierter Teil mit dem `tostr()` zeigt. Auch dort musst Du als Programmierer sehen dass das unnötigerweise eine quadratische anstatt einer linearen Laufzeit in Abhängigkeit von der Anzahl der Pixel hat.

Der C++-Compiler ist kein kluges Köpfchen der Dir das Denken abnimmt. Hier geht es um algorithmische Komplexität, das erledigt kein Compiler für Dich, dann bräuchte man nämlich keine Programmierer mehr wenn der Compiler aus jeder halbwegs verständlichen aber unnötig umständlichen Lösungsbeschreibung den optimalen Code ausspucken könnte. Und auch in C++ wirst Du bei speziellen Problemen andere Datentypen aus Bibliotheken ausserhalb der Standardbibliothek verwenden, über deren Eigenschaften (Operationen/Speicherverbrauch/Laufzeit) Du Dich genau so informieren musst wie über Datentypen in Python.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Das Problem ist einfach, das ich momentan nix kapier. Sorry bin wohl zu hohl fuer opencv. Hab bereits gegoogled, aber mir ergibt sich keine ordentliche Doku.

Ideal waeren natuerlich 3 Zeilen.
Voll PNG Laden
Objekt PNG laden
x,y=Objekt PNG in Voll PNG

Ich hab opencv bild in bild erkennenung gegoogled.

Hat einer evtl. den namen der Funktionparat, die ein png in ein anjderen png sucht?

Fuer das Grundverstaendnis, nehmen wir einfach eine PNG. Gelber Hintergrund und schwarze Schrift. Schatten, Unschaerfen und unterschiedliche Kanaele ausgeklammert.

In meinen PNG stehen 4 zeilen Text.

Das ist ein toller Test,
um etwas in einer Bilddatei zu finden.
Warum nicht auch mehrfache Objekte?
:-) Ende des PNG's.

Steht in diesen PNG mit 200x300 Pixel.

Es wurde "toller","um" "e" ausgeschnitten und entsprechend exportiert. Es muessten 13 "e" gefunden werden, 2 "um" und 1 "toller".

Das waere jetzt was zum antesten, mit opencv. in 42 Sekunden, fand mein mein altes Python script mit Hilfe von Getpixel alle Vorkommnisse.

Ich hab halt ein "leichten " Schaden, ich muss und moechte immer alles genau sehen und kontrollieren. Nach abgeschlossen Testphasen, wird das idR. aus den Source geloescht bzw. auskommentiert.
BlackJack

@pythontester: Ich verstehe die Leute nicht, die nach Dokumentation googlen und dann nichts finden. Dokumentation findet man in aller Regel nicht *irgendwo* im Netz, sondern beim jeweiligen Projekt. Oben auf der opencv.org-Startseite findet man in den Navigationslinks „DOCUMENTATION“ und wenn man da drüber geht, bekommt man eine Auswahl an Links: „reference“, „tutorials“, „books“, „links“, „quick start“, „cheat sheet“, und „wiki“. Auf der Seite gibt es einen Kasten „quick links“ mit „Online documentation“ als ersten Link, gleich gefolgt vom Link zum Forum des Projekts.

Ich will mich nicht über Deine Rechtschreibung mokieren, aber die Beiträge haben doch den ein oder anderen Rechtschreibfehler und unvollständige und damit manchmal nicht leicht verständliche Sätze. Wenn Du nach „erkennenung“ suchst, solltest Du den Korrekturvorschlag der Suchmaschine annehmen. ;-)

Die Funktion heisst `matchTemplate()`.

Mehr als eine Million Pixelwerte in Offset/RGB-Werte-Zeichenketten sind keine sinnvolle Debugging-Information. Die kann man sich zwar “durchlesen“, aber kaum jemand wird sich durch diese Daten im Kopf ein Bild machen können, im wahrsten Sinne des Wortes.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Problem, dass du loesen moechtest (und du hast keine wirkliche Loesung dafuer, denn Kameras liefern ueblicherweise nicht hochpraezise Pixel-genau wiederholte Ergebnisse) heisst in CV-Lingo "Template matching", und dafuer gibt es reihenweise Beispiele. ZB in der offiziellen, sehr guten Doku:

http://opencv-python-tutroals.readthedo ... ching.html

Und bevor du jetzt schon wieder schnellschiesst mit 'ist nicht, geht nicht, will nicht' - unten, nach dem Beispiel mit Messi, findet sich genau dein Ansatz - mehrfach Objekte finden.

CV ist kompliziert. Das macht man nicht mal so eben. Da muss man viel lernen, und verstehen. Dazu kauft man Buecher, und liest sich ein. OpenCV ist der richtige Ort dafuer. Aber das habe ich jetzt zum letzten mal gesagt.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Hallo,
angespornt und gleichzeitig vom Lernwillen angespornt, habe ich mich gestern bei gemacht, und entgegen euren Willen, meine C Variante entsprechend aufgebarbeitet.

Die Verarbeitung, der simplen chars hat einen enormen Boost gegegben. Auch wenn ich sagen muss, das mir die Kontrolle fehlt. Ich muss mich auf die Matches verlassen, ohne abzugleichen.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn es nur ein Tool gaebe, mit dem man einfach einzelne Schritte und Zwischenergebnisse eines komplexen Bildanalyseprozesses darstellen koennte - das waere wunderbar....
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Hallo,
nach nun weiteren Tagen, muss ich euch mitteilen, das ich das Python Projekt eingestellt habe.

Mir fehlt bei Python irgendwie das Denken, und dieses Zwangsformatieren, Befehle enden mi neuer Zeile usw. .

Zudem hab ich zu C/C++ noch aus frueheren Jahren den C++ Builder 6 Enterprise rumliegen und etliche Buecher. Und ja peinigt mich, es wirkt einfach performater und eleganter eine kompilierte EXE zu haben. In ein Python Script kann schnell Schindluder getrieben werden.

Ich hab jetzt die Bildsuche auf dem Pi auf unter 15 Sekunden gedrueckt bekommen, und habe nur noch mit den array Template gearbeitet. Die Filterung auf den moeglichen Bereich vorgenommen(bei ein 8x8 Bild, und ein 3x3 Quellobjekt, suche ich nur noch das 6x6 ab. Eine weitere Vorfilterung wurde mit einer Bereichsreduzierung getroffen. Zum Beispiel nur von 2,2 bis 5,5 suchen. Im grossen Bildern, war dies eine enorme Geschwindigkeitssteigerung, die ich bestimmt mit Python auch realisieren koennte. Mit einer recht guten Auswahl hat man fast das Echtzeitgefuehl.

Die Verarbeitung von Kamera Bildern gestaltet sich trotzallem sehr schwierig. Ich denke das werde ich einstellen, ich bin etwas zu bloed fuer solche super komplizierten Systeme. Ich hatte den Ansatz, das ich einfach die RGB Werte um x% toleriere. ZB 100,20,180 und 10 % Toleranz, waeren 90-110,18-22, 162-198 oder 90-110,10-30-170-190. Das klappt nur bei gleichen Belichtungseffekten. Testweise mit der Webcam in der Besenkammer. Aber das Bild kann auch einfach mal ewas "verrutscht", gezerrt oder gestaucht sein. Und an dem Punkt scheitert die stumpfe, Pixel by Pixel Variante. Das leicht versetzte klappte noch, aber es zu komplex fuer ein Hobby deppen, der sowas nie studierte.

Opencv habe ich vermieden, da dort wieder etliche Libs und Arbeiten am System noetig sind.

Mit lodev und den Boost Libs, kann ich das auf Windows, als auch Linux benutzen. Auf ein Win XP mit 1GB Ram und ein Atom, ist es kaum merkbar, das etwas rechnet. Auf mein Desktop PC mit 8gb RAM und ein Core i7, kann man von Echtzeitverarbeitung sprechen.

Nur beim Pi merkt man das er einfach nix perfomantes kann, aber 15 Sekunden sind ok. bei den 2,5W Verbrauch, ist es egal ob er nun nach 5 Sekunden die Messwerte oder Screenshots verareitet hat oder nach 35 Sekunden.

Allerdings war es egal warum, in Python langsamer, 10 Millionen mal if a == b: zu vergleichen als in C/C++.

Und es sind halt closed Source Sachen, wo keiner mal eben eine Serveradresse oder Benutzernamen und Kennwort ins Skript schreiben kann.

Es bringt der sicherste VPN Tunnel oder Server, nix wenn die Daten fuer alle auslesbar sind.

Ich bedanke mich trotzdem fuer eure Muehen, und befuerchte fast, das Python mich ueber kurz oder lang einholen wird. Der erste Hersteller hat eine Plugin Engine fuer Python. Damit wuerde das rumquaelen ueber Sockets und externe Aufbereitung entfallen, und es kann bequem per Plugin gearbeitet werden.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

pythontester hat geschrieben:Und es sind halt closed Source Sachen, wo keiner mal eben eine Serveradresse oder Benutzernamen und Kennwort ins Skript schreiben kann.
Das ist Blödsinn, Ich lese dir ein Passwort genauso aus einer .exe aus (ganz banal: `strings secure.exe`).



Ob du nun C, C++ oder Python lernen willst, deine Entscheidung, generell wirst du aber nicht um Libs wie OpenCV herumkommen, wenn du tatsächlich etwas erreichen willst, anstatt die Funktionalität von OpenCV in schlechter nach zu implementieren. Wenn man sich ein bisschen damit auseinander setzt, kann auch ein Hobby-Programmierer "der sowas nie studierte" eine Lösung für dein Problem programmieren.

Ich empfehle dir einfach von vorne zu beginnen, schrittweise versuchen zu verstehen was passiert und wie man etwas besser machen kann, so lernt man programmieren. Wenn du Grundlagen da sind, wird alles leicht(er).
the more they change the more they stay the same
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Ganze hier wirkt eher wie ein Stream of (sub)consciousness statt einem ernsthaften Versuch, sich Hilfe von erfahreneren Leuten zu holen. Hobbyist und nicht-studiert-sein sind in meinen Augen gar keine Kriterien - dazu habe ich zu viele Diplominformatiker getroffen, denen ich noch nicht mal die Programmierung einer kleinen Endlosschleife zutrauen wuerde, wenn man es von ihnen verlangt.

Aber die Art, darauf zu bestehen, nichts dazu zu lernen, indem man mal in Frage stellt, was man selbst zu wissen glaubt, nachdem man schon Hinweise bekommen hat - tja. Da ist halt nix zu machen. Muss ja auch nicht :)
BlackJack

Natürlich nützen VPN-Tunnel und abgesicherte Server dagegen das die Daten für alle auslesbar sind. Der Datenverkehr über den Tunnel ist verschlüsselt, also nicht auslesbar und dafür das man die Daten nicht aus dem Quelltext herauslesen kann wurden Zugriffsrechte erfunden. Und wenn man paranoid ist, Verschlüsselung des Datenträgers. Falls aber jemand Zugriff auf die Hardware hat, dann hast Du in jedem Fall verloren ­— auch bei nativ kompilierten Binärdateien. Denn auch dort kann man die Daten auslesen, und auch neue reinschreiben, und letztendlich auch immer Wrapper um das Programm schreiben und Daten im laufenden Betrieb abgreifen oder austauschen. Denn jedes Passwort oder Zugangsdaten die vom Programm verwendet werden, müssen spätestens zur Verwendung im Klartext zur Verfügung stehen.

Und natürlich sind in CPython 10 Millionen ``if``\s langsamer ausgeführt als bei einem nativ kompilierten Programm. Darum verwendet man ja auch die entsprechenden Bibliotheken, die in C oder C++ (oder Fortran) geschrieben sind, von Python aus, um einerseits schnelle Ausführungsgeschwindigkeit zu haben und andererseits die Vorteile einer dynamischen Sprache bei der Entwicklungsgeschwindigkeit zu haben.

Wenn Du auch in C++ die Bilder nicht mehr verarbeiten willst, weil der simple Ansatz nicht ausreicht, wo liegt denn dann noch das Problem bei Python? (Oder irgend einer anderen, nicht so fürchterlich barocken Sprache wie C++) Komplexität von Sprache und Bibliotheken kann es ja eher nicht sein wenn C++ und Boost-Bibliotheken stattdessen zum Einsatz kommen sollen. C++ ist IMHO eine deutlich komplexere Sprache und es ist damit deutlich schwieriger korrekte Programme zu schreiben, weil es einfacher ist sich in den Fuss zu schiessen, die Fehlermeldungen bei Template-Problemen teilweise sehr unverständlich sind, und man sich um Speicherverwaltung mehr Gedanken machen muss. Es erfordert mehr Disziplin C++ zu schreiben das einem nicht um die Ohren fliegt.
Antworten