QImage Pixel Info

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Hallo allerseits,

ich möchte die relative Helligkeit eines Kanals in einem QImage berechnen, dazu habe ich mir folgende Funktion geschrieben:

Code: Alles auswählen

    def calculate_brightness(self, image):
        width, height = image.size().width(), image.size().height()
        maximum = width*height*255
        total = 0
        for row in xrange(height):
            for column in xrange(width):
                pixel = image.pixel(column, row)
                color = QtGui.QColor(pixel)
                total += color.red()
        return total/maximum
Laut Doku ist aber die Funktion QImage.pixel(x,y) äußerst teuer. So nun bin ich im Internet auf Lösungen gestoßen, die scanLine verwenden. Leider bekomme ich hier ein Pointer zurück mit dem ich nicht weiß was ich damit machen soll :)

Code: Alles auswählen

line_pointer = image.scanLine(row)
Hat da jemand eine Idee oder vielleicht ein ganz anderen Vorschlag?

Grüße,
anogayales
lunar

@anogayales: Hast Du ein echtes Performance-Problem mit "QImage.pixel()"?
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Ja, leider schon. Die Berechnung dauert bereits auf einem 200x200 Pixel QImage zwischen 60 ms - 100 ms und ich krieg zum Teil 60 Bilder pro Sekunde -> ~ alle 16 ms. Die Berechung wurde bereits in einen QThread ausgelagert. Es wird immer maximal die Helligkeit von nur einem Bild berechnet.

Ich bekomm das QImage übrigens über qglwidget.html#grabFrameBuffer http://doc.qt.nokia.com/4.7-snapshot/qg ... rameBuffer und muss darauf relativ zügig reagieren können.

Es wundert mich, dass das so langsam ist. Bevor ich die Helligkeit berechne wird das Bild skaliert. Der Skaliervorgang dauert nur einen Bruchteil von der Helligkeitsberechnung. Ich nehme mal an, dass beim Skalieren auch jeder Pixelwert abgefragt werden muss, zumindest hab ich als ich sowas mal von Hand programmiert hab jeden 2x2 Block auf einen 1 Pixel Block abgebildet.

Grüße,
anogayales
deets

QThread hilft dir da gar nix.

Ich wuerde eher versuchen, and die rohen Pixeldaten zu kommen, und die dann mit Numpy oder OpenCV zu verarzten.
lunar

@anogayales: Das Skalieren ist in C++ implementiert. Eine Python-Schleife kann da nicht mithalten.

Ich glaube auch nicht, dass der Zugriff per "image.pixel()" ein Engpass ist, sondern vielmehr die Iteration über das Bild in Python. Du kannst zwar "QImage.scanLine()" versucht, der Rückgabetyp ist ein "sip.voidptr", dessen API in der Sip-Referenz beschrieben ist. Davon musst Du dann eine Kopie erzeugen, diese mit der korrekten Größe (eines "unsigned int") versehen, und anschließend kannst Du dann mit dem Index-Operator auf einzelne Pixelwerte zugreifen. Das ist aber alles nicht so einfach, weil Du so nicht mehr mit echten Pixeln arbeitest, sondern mit rohen Bytes, direkt aus dem Speicher des "QImage"-Objekts. Dementsprechend musst Du unter anderem selbst auf die Bereichsprüfung achten, selbst aus unsigned int Werten RGB-Werte extrahieren, usw.

Ich rate Dir daher eher dazu, die Bildanalyse mit numpy oder opencv durchzuführen. Beide Bibliotheken bietet ziemlich wahrscheinlich schon fertige Funktionen für diesen Zweck an.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

deets hat geschrieben:QThread hilft dir da gar nix.
Ich wollte es nur der Vollständigkeit halber erwähnen.
deets hat geschrieben:Ich wuerde eher versuchen, and die rohen Pixeldaten zu kommen, und die dann mit Numpy oder OpenCV zu verarzten.
Wie komm ich an diese?

Es gibt bereits Module die diese Umwandlung machen, z.B. http://kogs-www.informatik.uni-hamburg. ... array/doc/ trotzdem wollte ich erstmal keine externen Abhängigkeiten in mein Programm reinarbeiten, vorallem hab ich qimage2ndarray noch nicht getestet :)

Edit: numpy hört sich gut an, qimage2ndarray wird dann gleich mal getestet.

Grüße,
anogayales
lunar

@anogayales: Wieso überhaupt der Umweg über "QImage"? Lade die Bilder doch einfach direkt mit numpy...
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Ich bekomme doch die Bilder über qglwidget.grabFrameBuffer und das liefer mit ein QImage zurück, oder kann ich da noch irgendwie anderes rankommen?

Grüße,
anogayales
lunar

@anogayales: Du hast bisher nicht gesagt, woher die Bilder kommen, und ich kann wirklich nicht hellsehen.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Dritter Beitrag von oben. Kann gut sein, dass ich diesen grade editiert hab, also du deinen Beitrag verfasst hast.

qimage2ndarray fällt wohl auch flach, da man dazu ein C Erweiterung brauch und ich diese nicht für alle möglichen Endgeräte vorkompilieren kann und will. Dann bleibts wohl oder übel bei der langsamen Variante.

Gibt es vielleicht einen weg wie ich direkt aus dem OpenGL Buffer ein numpy array erstellen kann?

Grüße,
anogayales
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Schau mal hier http://kogs-www.informatik.uni-hamburg. ... ndarray.py
Das scheint eine Vorversion von qimage2ndarray ohne weitere Modulabhängigkeiten gewesen zu sein. Vllt. reicht das ja für Deine Zwecke.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Kleiner Test zeigt mir, dass das wohl funktioniert. Vielen Dank. Über die Geschwindigkeit kann ich noch keine Aussage machen.


Edit: Bei einem 500x500 Bild lieg ich bei 4-6 ms also schon ein großer Unterschied.

Grüße,
anogayales
Antworten