PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schnelle/Effiziente Pixeloperationen



Mat
08-07-2006, 14:51
Hallo,

meine Anwendung kann bereits Bilder laden. Ich würde gern auf einzelne Pixel des Bildes zugreifen. Ich glaube/weiß dass dafür Zugriffe über QT gibt aber ich bin mir unsicher ob diese auch effizient/schnell sind? Gibt es sonst eine andere Möglichkeit überhaupt auf Pixel zuzugreifen (vielleicht auch was anderes als OpenGL?). Oder muss man da irgendwie auf os-funktionen zurückgreifen...wenn ja: ist diese Methodik überhaupt schneller als über QT ?

Ich weiß nicht ob sich jemand auskennt aber ich würde gerne Bilder "stören" also ein Blurring darauf anwenden...wenn jemand erfahrung hat...
Oder auch einfacher...wenn ich einen Gaußfilter implementieren wollen würde...im Grunde muss ich die neuen Pixeldaten nur über eine Gewichtung von Nachbarpixeln errechen....d.h. ich operiere doch mit den RGB-werten also nur den Farbwerten oder? Was anderes kann es doch nicht sein oder?
Oder wie soll ich Pixel sonst verrauschen lassen?

Danke für jede Info!

locus vivendi
08-07-2006, 16:47
Hallo,

meine Anwendung kann bereits Bilder laden. Ich würde gern auf einzelne Pixel des Bildes zugreifen. Ich glaube/weiß dass dafür Zugriffe über QT gibt aber ich bin mir unsicher ob diese auch effizient/schnell sind?
Wenn du QImage verwendest sollte das schnell sein.


Oder muss man da irgendwie auf os-funktionen zurückgreifen...wenn ja: ist diese Methodik überhaupt schneller als über QT ?
Nein und nein, für jede einigermaßen sinnvolle Definition von os-funktion.


Ich weiß nicht ob sich jemand auskennt aber ich würde gerne Bilder "stören" also ein Blurring darauf anwenden...wenn jemand erfahrung hat...
Oder auch einfacher...wenn ich einen Gaußfilter implementieren wollen würde...im Grunde muss ich die neuen Pixeldaten nur über eine Gewichtung von Nachbarpixeln errechen....d.h. ich operiere doch mit den RGB-werten also nur den Farbwerten oder? Was anderes kann es doch nicht sein oder?
Oder wie soll ich Pixel sonst verrauschen lassen?
Ich kenn mich mit Bildverarbeitung nicht aus. Aber ich kann dir diese beiden Links liefern. Das dürften die zwei modernsten und besten (neben ImageMagick) Bibliotheken für Bildverarbeitung sein, die es gibt, zumindest unter denjenigen, die Freie Software sind:
http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/
http://opensource.adobe.com/gil/

peschmae
08-07-2006, 17:17
Da wäre wohl auch noch http://cimg.sourceforge.net hinzuzufügen - zumindest benutzen das einige Filter die ich kenne. Insbesondere der hervorragende GREYCstoration Filter.

Was genau wie effizient und so ist weiss ich nicht da ich in dem Gebiet noch nichts programmiert habe.

MfG Peschmä

locus vivendi
08-07-2006, 19:51
Da wäre wohl auch noch http://cimg.sourceforge.net hinzuzufügen - zumindest benutzen das einige Filter die ich kenne. Insbesondere der hervorragende GREYCstoration Filter.
Jo, die kannte ich noch nicht.

Ich war auch zu vorschnell mit meiner Aussage, daß GIL und Vigra "die" beiden Besten sind. Es sind zwei der Besten, aber es gibt auch noch einige andere sehr gute. Es kommt natürlich auch darauf an was genau man macht (wie immer). GIL und besonders Vigra sind z.B. sehr stark was Bildtransformation angeht (davon redete Mat glaube ich). Für Rendering z.B. sieht Antigrain sehr gut aus (http://www.antigrain.com).

anda_skoa
09-07-2006, 11:43
Bei der Verwendung von QImage muß man bei häufigen Zugriffen nur darauf achten, daß man nicht pixel() und setPixel() benutzt, sondern direkt mit den Daten arbeitet, also scanLine() oder bits() benutzt.

Ciao,
_

Mat
12-07-2006, 14:31
danke für die antwort.
sehe ich das richtig das scanLine einfach die erste Zeile im Bild ist ? oder ist das einfach der Zugriff auf ein spezielles Pixel ? Aber warum ist der rückgabe-wert uchar * ? ein character ? Ich dachte eher sowas wie der rgb - wert oder ein int-wert oder so? Und was macht genau die funktion bits() ? Da komme ich nicht drauf - evtl. die stelle wo Pixel(0,0) abgelegt ist?

Danke euch für Hilfe!

locus vivendi
12-07-2006, 15:32
sehe ich das richtig das scanLine einfach die erste Zeile im Bild ist ? oder ist das einfach der Zugriff auf ein spezielles Pixel ? Aber warum ist der rückgabe-wert uchar * ? ein character ? Ich dachte eher sowas wie der rgb - wert oder ein int-wert oder so? Und was macht genau die funktion bits() ? Da komme ich nicht drauf - evtl. die stelle wo Pixel(0,0) abgelegt ist?
Hilft die die Qt-Doku denn da nicht weiter? bits ist äquivalent zu scanLine(0), steht da. Und uchar* wird zurückgegeben, weil man das als einen Pointer auf Bytes auffassen kann, was hier irgendwie Sinn macht. Das vermute ich nur, wissen tun das die Trolltech-Entwickler. Und wie du auf die Pixel zugreift, verrät die QImage Doku eigentlich auch.

Mat
12-07-2006, 15:46
Hilft die die Qt-Doku denn da nicht weiter?

hätte sie mir geholfen hätte ich nicht gepostet.



bits ist äquivalent zu scanLine(0), steht da.


das sehe ich auch danke...



Und uchar* wird zurückgegeben, weil man das als einen Pointer auf Bytes auffassen kann, was hier irgendwie Sinn macht. Das vermute ich nur, wissen tun das die Trolltech-Entwickler. Und wie du auf die Pixel zugreift, verrät die QImage Doku eigentlich auch.


ein Pointer auf Bytes? da häng ich eben. Mein wissen ist noch nicht so ausgereift das zu verstehen. Was ein Pointer ist weiß ich. Soll das heisen dass alle Pixel als Bytes hintereinander abgelegt sind und ich über den Index auf das jeweils nächste Byte anspringe wenn ich scanLine[idx] benutze ?
Wie man auf PIxel zugreift ist klar. Anda skoa meinte nur dass es effizienter ist wenn ich eben scanLine oder bits benutze...Nur leider werde ich aus der DOku nicht schlau...(wohl auch wegen meinem noch nicht ausgereiften wissen - aber wozu gibt es foren wie diese).

Danke

anda_skoa
12-07-2006, 17:30
Laut Doku (und nach meiner Erfahrung ist die in diesem Fall auch korrekt) ist das ein Pointer auf die internen Daten, bei einem 32 Bit Farbbild immer 4 Byte pro Pixel.
Und wie in der Doku ebenfalls beschreibt, kann man den pointer auf QRgb casten und mit den qRed, qGreen, qBlue, usw auf die einzelnen Farbwerte zugreifen

Ciao,
_

locus vivendi
12-07-2006, 17:56
ein Pointer auf Bytes? da häng ich eben. Mein wissen ist noch nicht so ausgereift das zu verstehen. Was ein Pointer ist weiß ich.
Ein Pointer auf unsigned char darf auf jedes Objekt zeigen, und ist auch geeignet um einen Großteil von Objekten anzusprechen. Das gilt für Zeiger auf andere Typen so nicht, die sind in der Regel eingeschränkter zu benutzen. Außerdem ist ein char (bzw. unsigned char) die kleinste Einheit, aus der sich Objekte zusammensetzen.


Soll das heisen dass alle Pixel als Bytes hintereinander abgelegt sind und ich über den Index auf das jeweils nächste Byte anspringe wenn ich scanLine[idx] benutze ?
Du kannst über den Zeiger den scanLine zurückliefert so viele Pixel lesen und schreiben wie das Bild Breit ist, aber nicht mehr. Mit anderen Worten dein idx darf nicht größer sein als die Breite. Wenn du eine Scanline weitergehen willst, dann mußt du in "scanLine(i)" den Index um eins erhögen. Also nocheinmal zusammengefaßt: Du kannst den Pixel an der Stelle (x, y) über "scanLine(y)[x]" ansprechen, wobei y nicht größer sein darf als die Höhe, und x nicht größer als die Breite (und auch nicht gleichgroß jeweils).

Aufgrund dieser Speichermethode, dass Zeiger auf Scanlines gespeichert werden, und nicht die gesamten Bilddaten als ein großer Datenblock könnte QImage übrigens tatsächlich langsamer sein als Alternativen. Aber das ist nur eine denkbare Möglichkeit, um sich da sicher zu sein, müsste man Messen oder den kompilierten Code angucken.

Ich hoffe damit kannst du jetzt etwas anfangen, ich wollte vorhin nicht sarkastisch sein, ich dachte nur, dass du in der Doku vielleicht etwas übersehen hast.

Mat
12-07-2006, 18:00
vielen dank für die Antworten...
sehr interessant mit dem uchar.
Höre das heute zum ersten mal - danke. Verstehe auch was scanLine nun ist.
Danke!

Mat
14-07-2006, 19:11
Hallo der folgende Versuch gibt mir leider nicht die RGB Werte des bildes aus...wie kann ihc das bewerkstelligen ?
oder habe ich nen saftigen denkfehler drin ?



QVector<QRgb> vec_img(image.height() * image.width());
int idx = 0;

for ( int y=0; y<image.height(); y++ )
{
//uchar *p = image.scanLine(y);
for ( int x=0; x<image.width(); x++ )
{
//*p++ = (x+y)%128;
std::cout << (QRgb*) image.scanLine(y)[x] << std::endl;
//vec_img[idx] = (QRgb) image.scanLine(y)[x];
idx++;
}
}


Danke euch

anda_skoa
14-07-2006, 19:16
In etwa so


QRgb* lineData = (QRgb*)image->scanLine(y);
cout << qRed(lineData[x]) << ", " << qGreen(lineData[x]) << ", " << qBlue(lineData[x]) << endl;


Ciao,
_

locus vivendi
14-07-2006, 19:51
Upps, da muss ich mich auch noch mal korrigieren: Ich schrieb image.scanLine(y)[x] würde den Pixel an der Stelle (x, y) ansprechen. Das gilt aber nur wenn das Bild 8-Bit Farbtiefe hat, weil scanLine ja ein Zeiger auf char, nicht auf QRrgb zurückgibt. An der Stelle bin ich durcheinander gekommen. Wenn das Bild 24+8 Bit Farbtiefe hat, funktioniert es jedenfalls so wie anda_skoa schreibt. Und für 1-Bit Farbtiefe muss es nochmal anders sein.

Mat
14-07-2006, 20:29
hmm danke...
gibt es eine Methode um alle Farbtiefen anzusprechen ? oder sollte ich da abfragen wievel farbtiefe und dann verzweigen um die werte auszulesen?
oder gibts ne andere Möglihckeit ?

Danke euch!

locus vivendi
14-07-2006, 21:16
gibt es eine Methode um alle Farbtiefen anzusprechen ? oder sollte ich da abfragen wievel farbtiefe und dann verzweigen um die werte auszulesen?
Ich vermute eine Fallunterscheidung ist der einzige Weg, wenn du nicht von vorneherein weißt, dass nur eine einzige Farbtiefe vorkommt.


oder gibts ne andere Möglihckeit ?
Du hast die Wahl, wo du die Fallunterscheidung(-en) unterbringst. Du könntest auch QImage typsicher wrappen, das heißt z. B. in eine Klasse packen die nur eine Farbtiefe zulässt, und nur Pointer und Werte die den zu der gewählten Farbtiefe passenden Typ haben herausgeben. Ich weiß aber nicht ob das Sinn macht, entscheide selber.

Es hängt an den Anforderungen: Stelle dir erstmal die Frage, ob überhaupt mehrere Farbtiefen vorkommen werden. Aufgrund der bisherigen Diskussion hatte ich den Eindruck bekommen, das du eh nur "Truecolor" hast.

Lin728
16-07-2006, 16:42
der einfachste weg wäre, wenn performance nicht allzu kritisch ist deine bilder zuerst in truecolor umzuwandeln.

Aktuelle Prozessoren schaffen das mit mehreren FPS für 1600x1200x32 bilder, mit sehr guten Compilern und eventuell MMX/SSE2 instrincs ist noch mehr drinnen wenn die Umwandlun komplexer ist - Auf meinem Duron800 war das ganze schlichtweg durch den Speicherdurchsatz beschränkt.

Mat
16-07-2006, 19:21
performance ist leider wichtig...
aber der vorschlag ist trotzdem gut danke...
denk drüber nach (evtl. wie wichtig die performance ist)
danke euch

Lin728
18-07-2006, 15:51
Ja ohne dass du irgendwas probiert hast, kannst du eh nicht entscheiden ob eine Lösung "schnell genug" ist oder nicht.