PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++ GetPixel / SetPixel und 2D-Vectoren


Gast
2013-09-17, 13:17:07
Hi,

ich hab vor kurzem mit C++ (vorher mal ein klein wenig C gemacht) angefangen und will ein kleines Programm schreiben was Pixelweise Bilder ändern soll, bin aber auf Probleme gestoßen:

2D-Vector:

Ich habe eine Matrix erzeugt mit

vector< vector<double> > matrix;

Jetzt bin ich mir nicht sicher ob ich das richtig verstehe. Heisst das, dass ich für die einzelnen Plätze der Matrix immer erst einen Vector "ansteuern" muss, quasi für die erste waagerechte Zeile, und dann über den Platz im Vector erst an die senkrechten Plätze komme?
Muss ich dem Unter-Vector im 2D-Vector dann auch eine Bezeichnung geben?
Und zum Befüllen des 2D-Vectors erst immer den Unter-Vector(UV) füllen ( UV.push_back(x); ) und dann irgendwie per matrix.push_back(UV); die Unter-Vectoren an den Ober-Vector hängen?


GetPixel:

Wenn das mit dem 3D-Vector klappt würde ich gerne die Farbwerte aus einem Bild in den Vector schreiben. Ich denke mal eigentlich bräuchte ich einen 3D-Vector für RGB aber erst mal nur 2D ^^
Ich hab schon ordentlich gegooglet versteh aber aber nicht wie das jetzt konkret aussehen muss wenn ich ein jpg Bild einlesen will und dann mit GetPixel einen Farbwert aus einer bestimmten Koordinate ziehen will.
Kann mir da jemand einen Beispiel Code schreiben? ^^

SetPixel:

kommt wenn andere Probleme gelöst sind :D

Marscel
2013-09-17, 13:38:21
Jetzt bin ich mir nicht sicher ob ich das richtig verstehe. Heisst das, dass ich für die einzelnen Plätze der Matrix immer erst einen Vector "ansteuern" muss, quasi für die erste waagerechte Zeile, und dann über den Platz im Vector erst an die senkrechten Plätze komme?

Das wäre die offensichtlichste Möglichkeit, ja.

Muss ich dem Unter-Vector im 2D-Vector dann auch eine Bezeichnung geben?

Bezeichnung?

Und zum Befüllen des 2D-Vectors erst immer den Unter-Vector(UV) füllen ( UV.push_back(x); ) und dann irgendwie per matrix.push_back(UV); die Unter-Vectoren an den Ober-Vector hängen?

Ja, matrix ist anfänglich ja leer. Die gilt es also mit vector<double> aufzufüllen.


Wenn das mit dem 3D-Vector klappt würde ich gerne die Farbwerte aus einem Bild in den Vector schreiben. Ich denke mal eigentlich bräuchte ich einen 3D-Vector für RGB aber erst mal nur 2D ^^
Ich hab schon ordentlich gegooglet versteh aber aber nicht wie das jetzt konkret aussehen muss wenn ich ein jpg Bild einlesen will und dann mit GetPixel einen Farbwert aus einer bestimmten Koordinate ziehen will.
Kann mir da jemand einen Beispiel Code schreiben? ^^

Dir ist hoffentlich bewusst, dass JPG ein komprimiertes Format ist, mit dem das sicher nicht mal eben gemacht ist?

Guck dir für mehr Infos den Wiki-Artikel dazu (http://de.wikipedia.org/wiki/JPEG#Die_JPEG-Dekodierung) und vielleicht libjpeg (http://www.ijg.org)im Quellcode an.

Gast
2013-09-17, 14:03:08
Thx für die Antwort.


Bezeichnung?


Ich meine mit, ob ich mit vector< vector<double> > matrix; nur einen Vector erzeuge, oder quasi den Unter-Vektor gleich mit.
Oder muss ich den "UV" danach noch einzeln erzeugen und die obere Zeile erzeugt nur einen Vector, der Vectoren enthalten kann.



Dir ist hoffentlich bewusst, dass JPG ein komprimiertes Format ist, mit dem das sicher nicht mal eben gemacht ist?

Guck dir für mehr Infos den Wiki-Artikel dazu (http://de.wikipedia.org/wiki/JPEG#Die_JPEG-Dekodierung) und vielleicht libjpeg (http://www.ijg.org)im Quellcode an.

Jap ist mir bewusst. Ich hatte aber gelesen, dass die Datei automatisch dekodiert wird und alle Dateien jpg/tiff/png nach dem einlesen direkt unkomprimiert als Bitmap im Speicher liegen.

Gelesen hab ich das hier: http://social.msdn.microsoft.com/Forums/vstudio/en-US/43822cd5-7d0a-4d9b-bbf8-6fd0a92566d9/getpixel-for-jpeg

http://msdn.microsoft.com/de-de/library/system.drawing.bitmap.getpixel.aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1

Da ist auch ein kleines Beispiel, ich kann das aber nicht nachvollziehen ohne Erklärungen.

del_4901
2013-09-17, 14:08:20
Nimm einen vector und mach dein index mapping selber (row major, colum major, morton code, etc.) Jeh nachdem wie cachefreundlich dein Zugriffsmuster sein soll. Ein vector in einem vector ist mit an Sicherheit grenzender Warscheinlichkeit sehr cache unfreundlich.

Marscel
2013-09-17, 14:17:07
Ich meine mit, ob ich mit vector< vector<double> > matrix; nur einen Vector erzeuge, oder quasi den Unter-Vektor gleich mit.
Oder muss ich den "UV" danach noch einzeln erzeugen und die obere Zeile erzeugt nur einen Vector, der Vectoren enthalten kann.

Ja, wie erwähnt, matrix ist anfänglich leer. Das Auffüllen musst du selber machen.




Jap ist mir bewusst. Ich hatte aber gelesen, dass die Datei automatisch dekodiert wird und alle Dateien jpg/tiff/png nach dem einlesen direkt unkomprimiert als Bitmap im Speicher liegen.

Gelesen hab ich das hier: http://social.msdn.microsoft.com/Forums/vstudio/en-US/43822cd5-7d0a-4d9b-bbf8-6fd0a92566d9/getpixel-for-jpeg

http://msdn.microsoft.com/de-de/library/system.drawing.bitmap.getpixel.aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1

Da ist auch ein kleines Beispiel, ich kann das aber nicht nachvollziehen ohne Erklärungen.

Halt: da gehts aber um .NET. Du hast hier mit einem STL-Datentypen angefangen. Wenn du irgendwas mit .NET machen willst, brauchst du doch keinen weiteren Aufwand machen. Wenn du sowas selbst implementieren willst, dann natürlich.

Lightning
2013-09-17, 14:23:42
Nimm einen vector und mach dein index mapping selber (row major, colum major, morton code, etc.) Jeh nachdem wie cachefreundlich dein Zugriffsmuster sein soll. Ein vector in einem vector ist mit an Sicherheit grenzender Warscheinlichkeit sehr cache unfreundlich.

Wer sagt denn, dass es um Performance gehen soll? So wie ich das sehe ist er Anfänger, dem es um Grundlagen geht. Da würde ich mir über sowas erstmal überhaupt keine Gedanken machen.

del_4901
2013-09-17, 14:44:46
Wer sagt denn, dass es um Performance gehen soll? So wie ich das sehe ist er Anfänger, dem es um Grundlagen geht. Da würde ich mir über sowas erstmal überhaupt keine Gedanken machen.
Falsche Herrangehensweise. Warum es erst falsch lernen, wenn man dann spaeter es wieder umlernen muss. Gerade in C++ macht es keinen Sinn den Leuten Herangehensweisen anzutrainieren, mit denen Sie spaeter eh nichts anfangen koennen. Zumal selber den Index auszurechnen kein Hexenwerk ist. Audderdem ist C++ gemacht um Hardware nah zu programmieren. Grundkenntnisse ueber die Hardware sind absolut erforderlich, sonst kann man es gleich sein lassen und Java programmieren.

Gast
2013-09-17, 14:48:27
Nimm einen vector und mach dein index mapping selber (row major, colum major, morton code, etc.) Jeh nachdem wie cachefreundlich dein Zugriffsmuster sein soll. Ein vector in einem vector ist mit an Sicherheit grenzender Warscheinlichkeit sehr cache unfreundlich.

:conf2:

Versteh ich dich richtig, dass ich dann einen normalen vector hätte und ihn einfach nacheinander mit Zeug fülle dann aber selber gucken muss ab welchem Index welche Information anfängt?
Bei 3x3 Pixeln: (R,R,R,R,R,R,R,R,R,G,....)


Ja, wie erwähnt, matrix ist anfänglich leer. Das Auffüllen musst du selber machen.


OK, dann ist mir zumindest das schon mal klar.


Halt: da gehts aber um .NET. Du hast hier mit einem STL-Datentypen angefangen. Wenn du irgendwas mit .NET machen willst, brauchst du doch keinen weiteren Aufwand machen. Wenn du sowas selbst implementieren willst, dann natürlich.

Okay jetzt hab ich den Faden verloren.
getpixel gibt's nur in .NET? Und wenn ich das benutze und wingdi.h einbinde arbeite ich automatisch mit .net?

Ich will da keine Hausarbeit oder sonst was schreiben das ist nur für mich und soll am Ende einfach erst mal funktionieren.^^
Alles was man dann noch besser machen könnte kommt danach, wenn ich mich weiter damit beschäftigt habe.


Vielleicht sollte ich mal schreiben was das überhaupt werden soll.

Am Ende soll das Programm kleine Bilder einlesen, die einfach nur weiß sind und ein schwarzes Quadrat irgendwo haben.
Dann soll es die Position des Quadrats im zweiten Bild mit dem im ersten vergleichen und den kompletten Inhalt des zweiten Bildes so verschieben, dass die beiden Quadrate auf der selben Position liegen.

Dazu hab ich zu Anfang erst mal ein Programm geschrieben, dass 2 einfache Vectoren erzeugt, die mit irgendwas befüllt dann den ersten Vector nach einem Wert > x absucht, sich die Stelle merkt, das bei Vector 2 auch macht und den Inhalt von Vector 2 dann so verschiebt, dass die beiden Positionen gleich sind. Die entstehenden Lücken am Ende oder Anfang des Vectors werden mit 0 gefüllt.

Jetzt wollte ich das quasi auf einen 2D-Vector übertragen und am Ende soll der Inhalt vom Vector halt der Farbwert sein, so dass das Quadrat gefunden wird.


Ich finde meinen Gedanken gut :D
Aber aus Erfahrung wahrscheinlich wieder viel zu kompliziert?

Und ich denke halt auch, dass ein 1D-Vector mit index mapping (wenn ich richtig verstanden hab) beim Verschieben mich dann doch zu sehr verwirren würde. Zeilen und Spalten sind mir erst mal lieber - hat das Bild ja schließlich auch ^^

del_4901
2013-09-17, 14:58:56
:conf2:

Versteh ich dich richtig, dass ich dann einen normalen vector hätte und ihn einfach nacheinander mit Zeug fülle dann aber selber gucken muss ab welchem Index welche Information anfängt?
Bei 3x3 Pixeln: (R,R,R,R,R,R,R,R,R,G,....)

(R,R,R,R,R,R,R,R,R,G,G,...,B,B,B) kann man machen wenn man z.B parallel mit 3 Threads auf R,G,B parallel arbeiten moechte ohne Cache contention zwischen den Cores zu bekommen.

Bei kleinen matrizen wuerde ich aber (R(00), G(00), B(00), (01), (02), (10), (11), ..., (22)) vorschlagen. -> row major: i = (y * width) + x;
colum major: i = (x * height) + y;

Wenn du mit Nachbarpixeln arbeitest (blurfilter) dann ist Morton Order (http://en.wikipedia.org/wiki/Z-order_curve) effizienter. (http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN)

Ectoplasma
2013-09-17, 15:22:55
Hier mal ein kleiner Pseudocode-Ausschnitt (C/C++).
Soweit ich weiss, bekommst man nach dem Laden eines JPEGs eine gefüllte BITMAPINFO Struktur. Damit geht man jetzt wie folgt um.



BITMAPINFO bitmapInfo ... // <- after loading a JPEG

HDC hdc = GetDC(0);

if (hdc) {
void *pBits;
HIBITMAP dibSection, oldBitmap;
BITMAPINFOHEADER *pInfo = (BITMAPINFOHEADER *)&bitmapInfo;

dibSection = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &pBits, 0, 0);

if (dibSection) {
dc = CreateCompatibleDC(hdc);
if (dc) {
oldBitmap = SelectObject(dc, (HGDIOBJ)dibSection);

// begin - code of interest
COLORREF color = GetPixel(dc, 0, 0);
// end - code of interest

} else {
DeleteObject((HGDIOBJ)dibSection);
}
}
ReleaseDC(0, hdc);
}


Näheres entnimmst du der Microsoft - Doku. Wichtig ist nur, dass du mit "CreateDIBSection" arbeitest, weil es die einzige Funktion im Win32 - API ist, bei der du die exakte Farbinformation beibehälst, unabhängig von den Einstellungen im Desktop. Viel Spass.

Edit:

GetPixel/SetPixel sind arschlangsam. Du kannst dich auch damit beschäftigen, wie man direkten Zugriff auf die Bitmap-Bits erhält. Ist im obigen Beispiel auch enthalten.

Lightning
2013-09-17, 15:24:27
Falsche Herrangehensweise. Warum es erst falsch lernen, wenn man dann spaeter es wieder umlernen muss. Gerade in C++ macht es keinen Sinn den Leuten Herangehensweisen anzutrainieren, mit denen Sie spaeter eh nichts anfangen koennen. Zumal selber den Index auszurechnen kein Hexenwerk ist. Audderdem ist C++ gemacht um Hardware nah zu programmieren. Grundkenntnisse ueber die Hardware sind absolut erforderlich, sonst kann man es gleich sein lassen und Java programmieren.

Ich verstehe die Sichtweise, aber er hat jetzt nunmal mit C(++) angefangen, aus welchen Gründen auch immer. Da finde ich es trotzdem erstmal wichtiger die Grundlagen der Sprache zu verstehen, bevor man sich über Performance Gedanken macht (und die Ausnutzung von Cache-Effekten ist ja nicht mehr die Sprachebene). Dass man Sachen später nochmal umlernen muss bzw. einfach aus anderen Augen betrachtet, empfinde ich als Lernprozess, der auch hilfreich sein kann.
Naja, nur meine Meinung. Das Zeug dürfte jedenfalls eher abschreckend wirken (was du vermutlich auch beabsichtigst..).

del_4901
2013-09-17, 15:28:44
Ich verstehe die Sichtweise, aber er hat jetzt nunmal mit C(++) angefangen, aus welchen Gründen auch immer. Da finde ich es trotzdem erstmal wichtiger die Grundlagen der Sprache zu verstehen, bevor man sich über Performance Gedanken macht (und die Ausnutzung von Cache-Effekten ist ja nicht mehr die Sprachebene). Dass man Sachen später nochmal umlernen muss bzw. einfach aus anderen Augen betrachtet, empfinde ich als Lernprozess, der auch hilfreich sein kann.
Naja, nur meine Meinung. Das Zeug dürfte jedenfalls eher abschreckend wirken (was du vermutlich auch beabsichtigst..).
Nein es soll nicht abschecken, ich denke es ist einfacher bottom up die Sachen zu erlernen. Und es ist vielleicht auch interessant gleich zu verstehen wie die Hardware sich verhaelt? Mit der 'Sprachebene' bei C++ hat man eh die naechsten 10+ Jahre zu kaempfen.

Coda
2013-09-17, 15:31:54
Wer vector<vector<>> benutzt hat's nicht verstanden. Das ist einfach bescheuert auf so vielen Ebenen.