QGlWidget die Farbe Weiß als Rot zeichnen

Alles rund um die Programmierung mit Qt
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

QGlWidget die Farbe Weiß als Rot zeichnen

Beitrag von Treehouse »

Hallo zusammen,

ich habe folgendes Problem ich muss die Farbe Weiß von einem 8Bit Grauwertbild als Weiß darstellen und habe leider keine Ahnung wie ich das machen soll.

Ich nutze als Bitspeicher ein QImage Objekt welches ich dann mit folgender Funktion darstellen lasse:

Code: Alles auswählen

glTexImage2D(
		GL_TEXTURE_2D,
		0,
		GL_RGB8,
		m_image.width(),
		m_image.height(),
		0, GL_LUMINANCE,
		GL_UNSIGNED_BYTE,
		m_image.bits());	
Ich habe schon den ColorTable des QImage Objekts geändert so das bei 255 folgendes eingetragen wird (255,0,0). Aber leider hat das nichts gebracht. Die Texture reagiert gar nicht auf diese Änderungen.

Wäre schön wenn mir jemand einen Tip geben könnte.

Gruß

Treehouse
Curtis Newton
Beiträge: 122
Registriert: 11. Juni 2008 18:39

Beitrag von Curtis Newton »

Du konvertierst doch vorher das Bild mit
QGLWidget::convertToGLFormat
Dabei vorher die Palette ändern sollte klappen.

C.
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Ne das mache ich nicht. Das würde in meinem Fall viel zu lange dauern jedes Bild zu konvertieren und eine viel zu große CPU last erzeugen.

Gruß

Treehouse
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Ich müßte irgendwie den ColorTable der Texture ändern könnnen, aber ich weiß nicht wie.

Ich habe das schon mit setColormap probiert aber auch das hat nichts gebracht.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Ich bin zwar kein Experte, aber IMHO passen da "GL_RGB8" und "grayscale" nicht zusammen..
wie verhält es sich denn, wenn du Qt einfach machen lässt (anstelle die uralt-Methoden zu nehmen)?
http://doc.trolltech.com/4.6/qglwidget.html#bindTexture
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Hallo solarix,

das funktioniert nur leider habe ich dann eine CPU Auslastung wenn ich diese Funktion in paintGL aufrufe von 100% bei meiner Bildrate.

Gruß

Treehouse
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Gibt es noch eine andere Möglichkeit die neuen Daten im Qimage Objekt in der Texture zu zeichen ausser über bindTexture?? Das erzeugt bei mir einer sehr hohe CPU last, macht aber genau was es soll.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Aendert denn dieses Bild im Takt deiner Updaterate? Im Normalfall ruft man solche Methoden fuer alle benoetigten Texturen in "glInit()" und verwendet dann die gespeicherten Texture-IDs in "updateGL()"...

siehe http://qt.nokia.com/doc/4.6/opengl-textures.html
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Bei jedem neuen paintGL() liegt ein neuer satz an bits im Qimage vor. Es reicht also nicht diese Bits einmalig an eine Texture zu binden sonderen diese Texture muss auch auf die neuen Bits zeigen. Sonst wird die ganze Zeit das gleiche Bild angezeigt.
N¤X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N¤X »

Woher kommt das Bild denn, wenn es bei jedem PaintGL() ein neues gibt? Ist das ein Bild von einer Kamera? Dann musst du nicht unbedingt OpenGL nehmen um das zu bearbeiten oder darzustellen.
Oder renderst du deine Szene in Graustufen in ne Textur und die dann in nem zweiten Pass auf ein Quad gespannt als Falschfarbenbild? Dann würd ich eher ne Transferfunktion empfehlen, geht in einem Pass und schneller.

Außerdem sieht dein glTexture2D-Aufruf schon etwas komisch aus, meines Wissens nach kann man doch nicht einfach GL_RGB8 nach GL_LUMINANCE konvertieren. Von den Bits her sollte es ja passen, aber wenn da nicht irgend ein fieser Hack erwünscht ist sollte da nix sinnvollen bei rauskommen...

Gib uns mal mehr Informationen Was das für Bilder sind, wo die herkommen, was für ein Format die haben und was du genau damit machen willst.
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Es sind 8Bit Graustufen Bilder und ich habe eine sehr hohe Framezahl. (Die Bilder kommen von einer Kamera) Daher muss ich die Bilder möglichst schnell und effizient darstellen können.

Ich habe auch schon probiert mit dem QPainter zu arbeiten aber leider ist die Performance so schlecht das ich eine CPU last von 60 % bekommen und das schon in der niedrigsten Framerate.

Und der Aufruf den ich oben gezeigt habe funktioniert gut nur das Bild wird halt nicht mit der roten Farbe angezeigt.

Rufe ich hingegen jedes mal die Funktion "bindTexture()" auf wird das bild genau richtig dargestellt nur leider ist dann die CPU last wieder viel zu hoch.

Hier nochmal wie ich das QImage vorbereite für den Pixeltransfer:

Code: Alles auswählen

m_vcolorTable;
		QRgb *colorTable = new QRgb[256];
		for (int i = 0; i < 256; i++) {
			if ( i == 255 ) 
				m_vcolorTable.push_back(qRgb(255, 0, 0));
			else
				m_vcolorTable.push_back(qRgb(i, i, i));
		}


		m_image = QImage(Width, Height, QImage::Format_Indexed8);
		m_image.setColorTable(m_vcolorTable);
Danach brauche ich nur noch mit memcopy die bits in das image kopieren.

Gruß

Treehouse
N&#164;X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N&#164;X »

OK, wenns wirklich nur ums Darstellen geht bezweifle ich, dass openGL dafür das Richtige ist. Was so nämlich passiert ist: Dein Bild kommt von der Kamera in den Hauptspeicher und wird von da aus erstmal über die CPU und den Grafikport in den Grafikspeicher geladen, und da dann endlich gerendert.

Prinzipiell rendert openGL ja schon recht fix, aber das Problem ist immer, dass die Daten dafür erstmal in den Grafikspeicher müssen, und das ist dein Flaschenhals.

An deiner Stelle würde ich mich mal informieren, wie Qt Videos darstellt. Da braucht man ja auch ne hohe Framerate und soweit ich weiß machen die das irgendwie über labels.

Ansonsten wurde hier im Forum glaub schon ein paarmal über Qt und openCV diskutiert. Da openCV grad für Echtzeitbearbeitung und auch primitive Anzeige von Videos ist könnte da vllt auch was interessantes bei rausgekommen sein, einfach mal die Boardsuche benutzen...


Falls du doch an openGL festhalten solltest gibts da wohl so ne Erweiterung (GL_ARB_imaging) mit der man Colortables anwenden kann, das hab ich aber noch nie benutzt. Hier die Beschreibung im DGL-Wiki: glColorTable
Oooder halt doch mit ner Transferfunktion, also die Colortable in openGL als 1D-Textur erstellen (Nearest Neighbour Filterung nicht vergessen!) und die dann an nen Shader übergeben der die als Lookuptable nutzt.
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Oooder halt doch mit ner Transferfunktion, also die Colortable in openGL als 1D-Textur erstellen (Nearest Neighbour Filterung nicht vergessen!) und die dann an nen Shader übergeben der die als Lookuptable nutzt.
Kannst du dieses Verfahren mal genauer erklären, vielleicht mit beispiel code. Weil ich muss ehrlich gestehen das ich das nicht ganz blicke wie du das meinst.

Gruß

Treehouse
N&#164;X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N&#164;X »

Hm, mist, da nimmt man sich endlich mal die Zeit das zu suchen wo ich sowas schonmal gemacht hab, und dann stellt man fest, dass das auf nem andern Rechner ist, auf den man grad keinen Zugriff hat Oo
Also n Beispiel gibts jetzt wohl erstmal leider nicht, aber schon mal das Prinzip:

Du machst dir eine 1D Textur (RGB) die 256 Einträge breit ist. An jeder Position i setzt du die Farbe auf (i, i, i), nur an Position 255 setzt du die Farbe auf (255, 0, 0), also Rot (Normalerweise nimmt man halt float als Format, also statt 255 halt 1.0 etc, aber zum Verständnis ists mit ints glaub verständlicher). Das ist dann deine Lookup Table die du als 1D Textur in den Grafikspeicher lädst (glTexImage1D).

Rendern tust u ja wahrscheinlich einfach ein Quad das den Viewport ganz ausfüllt auf das du dein Bild als Textur aufklebst, das ist soweit auch gut so.

Als letztes brauchst du nur noch nen Fragmentshader, dem du die 1D Textur übergibst. Anstatt dem aktuellen Fragment einfach die entsprechende Farbe aus der 2D Textur zu geben, wie es normal wäre, setzt du die Farbe einfach auf die Farbe der 1D-Textur, wobei du als Texturkoordinate den Grauwert der Farbe aus der 2D Textur an der Stelle der eigentlichen Texturkoordinaten nimmst. (Ich hoffe mal, dass das nicht zu verwirrend formuliert ist ^^")

Dann musst du einfach nurnoch vor dem rendern des Quads den Shader aktivieren und schon sollte alles Weiß durch Rot ersetzt werden.

Diese 1D-Textur ist also eine Lookuptable die eine Transferfunktion beschreibt. Du musst nur halt beachten, dass du bei der 1D-Textur Nearest Neighbour Filtering aktivierst (glTexParameteri(texID, GL_TEXTURE_MIN/MAG_FILTER, GL_NEAREST)), denn Filterung ist bei ner LUT nicht erwünscht und führt zu unerwünschten Effekten...

PS: Das hat alles nixmehr mit Qt zu tun, also guck vllt auch obs nicht doch auch ohne openGL geht. Du musst mit openGL halt zig mal pro Sekunde eine Textur in den Grafikspeicher hochladen (die alte möglicht wieder freigeben) und mit glBindTexture binden, da kommst du nicht drum rum (soweit ich weiß gibts für Texturen noch keine Möglichkeit die direkt mit der CPU zu bearbeiten wie z.B. bei VBOs), und ich kann mir einfach nicht vorstellen, dass das sonderlich effizient geht... :/
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Mensch vielen dank für die Erklärung, bin für jeden Strohhalm dankbar. Ich sitze jetzt schon zwei Tage an dem Problem und ich bekomme halt mit den QT Eigenen Sachen immer eine hohe Prozessor Last.

Wollte schon versuchen aus den BIT Array an Grauwerten ein RGB zu machen aber das wird denke ich auchmal die CPU in die höhe schießen lassen.

Ich habe teilweise mit weit über 200 Bildern pro Sekunde und da zählt dann jede Operation. Ich weiß, ich weiß. Monitor 60 Hz und Augen und und... aber es ist nun mal so das dieses Daten aufkommen da ist. Selbst wenn ich nur 40 Bilder pro Sekunde habe dann habe ich schon eine Prozessor Last mit QT eigenen Mitteln von 30 %. Meine Methode über OpenGL die Sache anzugehen bringt mich da auf 2%. Und ich habe nun mal die Vorgabe QT in Verbindung mit OpenGL.

Du siehst der unterschied ist gewaltig, von daher werde ich mich mal an deine Lösung morgen heran wagen.

Gruß

Treehouse

Wenn du noch ein Code Snippet findest würde ich mich freuen.
Antworten