Laden...

Zwei Bilder Pixel für Pixel vergleichen, und gleiche ersetzen

Erstellt von slayerofyourmind vor 8 Jahren Letzter Beitrag vor 8 Jahren 4.375 Views
S
slayerofyourmind Themenstarter:in
10 Beiträge seit 2014
vor 8 Jahren
Zwei Bilder Pixel für Pixel vergleichen, und gleiche ersetzen

Hallo Community,

ich möchte mir ein Programm schreiben, mit dem prüfen kann ob mein zweites Bild den gleichen Hintergrund hat, wie das erste Bild.

Wenn dann z.B. ein Pixel des Hintergrundes mit dem des ersten Bildes übereinstimmt, soll dieser Pixel transparent werden.

Ich habe schon ein bisschen versucht, bin allerdings nicht zu dem gewünschten Ergebnis gekommen.

Bei Bilder mit 150 x 150 Pixel funktioniert alles.
Wenn ich allerdings ein Bild mit einer Größe von 1080 x 1920 Pixel vergleichen möchte, reagiert das Programm nicht mehr.

Hier ist meine momentane Methode dazu:

        /// <summary>
        /// Vergleicht die zwei Bilder und ersetzt die gleichen Pixel
        /// </summary>
        /// <param name="firstpath">Pfad des ersten Bild</param>
        /// <param name="secondpath">Pfad des zweiten Bild</param>
        private void Compare(string firstpath, string secondpath)
        {
            // Erstes Bild
            Bitmap src = new Bitmap(firstpath);

            // Zweites Bild
            Bitmap comp = new Bitmap(secondpath);

            // Prüfen ob beide Bilder sie gleiche Größe haben
            if (src.Width == comp.Width && src.Height == comp.Height)
            {
                for (int y = 0; y < src.Width; y++)
                {
                    for (int x = 0; x < src.Height; x++)
                    {
                        try
                        {
                            if (src.GetPixel(x, y) == comp.GetPixel(x, y))
                            {
                                comp.SetPixel(x, y, Color.Transparent);
                            }
                        }
                        catch (Exception ex)
                        {
                                MessageBox.Show(ex.Message);
                        }
                    }
                }

                pictureBox1.Image = src;
            }
            else
            {
                MessageBox.Show("Die Bilder haben nicht die gleiche Größe!");
            }
        }

Ich weis, das die "Bitmap.GetPixel()"-Methode sehr langsam ist, dennoch wollte ich es erst so probieren.

Ich hoffe, Ihr könnt mir bei meinem Problem weiterhelfen.

Mit freundlichen Grüßen
Slayerofyourmind

S
slayerofyourmind Themenstarter:in
10 Beiträge seit 2014
vor 8 Jahren

Hallo,

es hilft nicht unbedingt.

Ich möchte damit solche Bilder, wie das im Anhang, machen können.

C
2.121 Beiträge seit 2010
vor 8 Jahren

GetPixel und SetPixel sind unheimlich langsam. Müsste eigentlich auch in der Doku stehen.
Nutze die Lock... Methode.

Die Pixel sind meistens nicht zu 100% identisch wenn die Aufnahmen hintereinander gemacht wurden.
Ein Pixel auf transparent setzen bringt nichts. Du müsstest die Pixel aus dem Vergleichsbild in das bestehende einfügen dort die Person zu sehen ist die im bestehenden noch nicht ist.
Dabei hast du das Problem dass nicht nur dann Unterschiede sind wenn die Person eingefügt werden soll, sondern auch an Stellen wo sie bisher war und jetzt nicht mehr ist. An dieser Stelle würdest du also die Person wieder löschen.

Als Lösungsansatz könntest du mehrere Bilder miteinander vergleichen. Wenn eine Stelle in zwei Bildern annähernd gleich ist und im dritten sehr unterschiedlich, wird das die Person sein. Diese Stelle setzt du dann in dein Zielbild ein.

5.658 Beiträge seit 2006
vor 8 Jahren

Hallo allerseits,

die Performance-Tips helfen aber nicht viel, wenn schon der eigentliche Algorithmus ungeeignet ist, weil er auf einer falschen Annahme basiert. Diese Aufgabenstellung läßt sich nicht mit einem einfachen Pixel-Vergleich lösen. Aber es gibt bereits Lösungen, die man nachbauen kann, Stichwort: Luminanz-Keying bzw. Color-Keying oder ganz allgemein: Compositing.

Christian

Weeks of programming can save you hours of planning

S
slayerofyourmind Themenstarter:in
10 Beiträge seit 2014
vor 8 Jahren

Hallo,

vielen Dank für die Antworten.
Ich habe mir noch mal alles überlegt, und möchte es nun anderst machen.

Ich habe eine Methode, mit der der Benutzer selbst den Bereich, in dem die Person oder das Objekt ist, festlegen kann.

Jeder Mausklick fügt den Punkt zu einer Liste hinzu. Am Ende, wird über ein "Refresh", das Paint-Event aufgerufen, um mit:

Pen pen = new Pen(Color.Black, 3);
Graphics g = e.Graphics;
g.DrawPolygon(pen, _points.ToArray()); //_points ist die Liste mit den Punkten

die Punkte in der Liste zu einem Polygon zu verbinden.

Ist es nun möglich, die Linie und alles außerhalb des Polygons transparent zu machen ?

Mit freundlichen Grüßen
Slayerofyourmind

5.658 Beiträge seit 2006
vor 8 Jahren

Ist es nun möglich, die Linie und alles außerhalb des Polygons transparent zu machen ?

Ja, natürlich. Du hast alle Funktionen der Graphics-Klasse zur Verfügung: Graphics Overview (Windows Forms).

Abgesehen davon ist es allerdings wenig zielführend, hier irgendwelche Ideen zu posten, die einem gerade einfallen, und dann zu warten, bis dir jemand einen Lösungsweg vorgibt. Du solltest lieber erstmal im PhotoShop (oder in Paint.NET) ausprobieren, wie man solche Bilder zusammenfügt, welche Funktionen man dafür benötigt und wie man diese Funktionen anwendet. Dann kannst du deine Anforderungen definieren, und das ganze mit C# umsetzen.

Christian

Weeks of programming can save you hours of planning