Dateisortierung - nur etwas umständlicher

push?


Ja, sorry, ich hab auch noch Schule :D
Das andere Programm, was ich da geschrieben habe, zu den Datei-Zeiten, ist ja nicht sooo viel, aber das hier ist da schon etwas komplizierter.
Ich danke mal, ich setz mich am Wochenende noch mal ran. ^^
Vielleicht auch heute, mal schauen, vielleicht auch heute, hängt davon ab, wie lange ich wach bleiben kann :D
 
Ok, ich hab mich jetzt nochmal ran gesetzt und das kleine Tool geschrieben, mit dem ich hoffe, die passenden Vergleichswerte zu "erforschen".

Dazu brauche ich dann aber Hilfe von möglichst vielen Leuten, denn der Grenzwert, ab dem zwei Bilder nicht mehr ähnlich sind, der muss durch Tests bestimmt werden.


verborgener Text:
PHP:
        static void Main(string[] args)
        {
            List<string> left = new List<string>();
            List<string> right = new List<string>();

            var list = File.ReadAllLines("BilderListe.txt");
            for (int i = 0; i < list.Count(); i++)
            {
                if (i == File.ReadAllLines("BilderListe.txt").Count() - 1 && (i / 2) * 2 == i) break;
                if (i == 0) { left.Add(list[i]); continue; }
                if ((i / 2) * 2 == i) left.Add(list[i]);
                else right.Add(list[i]);
            }

            double ergebnis = 0;
            for (int i = 0; i < left.Count; i++)
                ergebnis += IstÄhnlich((Bitmap)Image.FromFile(left[i]), (Bitmap)Image.FromFile(right[i]));
            if (ergebnis == 0)
            {
                Console.WriteLine("Keine Dateien angegeben.");
                Console.Read();
                return;
            }
            else
            {
                ergebnis /= left.Count;
                Console.WriteLine(ergebnis);
                Console.Read();
            }
        }
        static int IstÄhnlich(Bitmap _img1, Bitmap _img2)
        {
            int width = 25;
            int hight = 25;

            Bitmap img1 = verkleinern(_img1, width, hight);
            Bitmap img2 = verkleinern(_img2, width, hight);

            int sum = 0;
            for (int y = 0; y < hight; y++)
                for (int x = 0; x < width; x++)
                    sum += (int)(Math.Pow(img1.GetPixel(x, y).R - img2.GetPixel(x, y).R, 2) +
                        Math.Pow(img1.GetPixel(x, y).G - img2.GetPixel(x, y).G, 2) +
                        Math.Pow(img1.GetPixel(x, y).B - img2.GetPixel(x, y).B, 2));
            return sum;
        }
        static Bitmap verkleinern(Bitmap image, int width = 25, int hight = 25)
        {
            Bitmap bmpOutput = new Bitmap(width, hight, PixelFormat.Format24bppRgb);
            Graphics gOutput = Graphics.FromImage(bmpOutput);
            Rectangle rectOutput = new Rectangle(0, 0, bmpOutput.Width, bmpOutput.Height);

            ImageAttributes ia = new ImageAttributes();
            ia.SetWrapMode(WrapMode.TileFlipXY);

            gOutput.InterpolationMode = InterpolationMode.HighQualityBilinear;
            gOutput.PixelOffsetMode = PixelOffsetMode.Half;
            gOutput.CompositingMode = CompositingMode.SourceCopy;

            gOutput.DrawImage(image, rectOutput, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, ia);
            bmpOutput.Save("output.bmp", ImageFormat.Bmp);

            return bmpOutput;
        }


Das kleine Programm tut folgendes:

Es liest aus einer Datei zeilenweise Pfade heraus und teilt sie dann wechselseitig in Listen auf, aus denen die Bilder dann verglichen werden sollen. In der Datei "BilderListe.txt" müssen also vollständige Pfade zu Bildern sein. Es wird das Erste mit dem Zweiten verglichen, dann das Dritte mit dem Vierten, und so weiter.
Der Vergleich arbeitet wie folgt:
Die zu vergleichenden Bilder werden auf die Größe 25x25 gebracht. Dann wird diese Formel für die RGB-Werte von jedem Pixel berechnet: (R1-R2)^2 + (G1-G2)^2 + (B1-B2)^2.
Die Ergebnisse kommen dann auf eine Summe, ein Wert, der sozusagen die Gleichheit beider Bilder beschreibt.

Nun muss ich wissen, wie groß dieser Wert werden darf (je größer, um so verschiedener die Farbwerte), damit die Bilder noch als ähnlich anerkannt werden.
Dafür das Programm hier, es rechnet die Werte aus, berechnet den Querschnitt und gibt diesen dann aus und den brauche ich.



Am besten wäre es, wenn die Tester dann unterschiedliche Testreihen durch führen, wo die Bilder aufsteigend verschieden sind.
So kann ich dann die Konstanten zusammen stellen, womit dann der Grad der Ähnlichkeit einfach geändert werden kann.

Also ich denke, 5 Testreihen mit Bildern, die kaum ähnlich, ein bisschen ähnlich, ähnlich, etwas mehr ähnlich, sehr ähnlich sind :D
Oder irgendwie so, würde mich da auch über einen geeigneten Vorschlag für die Konstanten freuen ^^


Gruß
 

Anhänge

  • Tools.rar
    4,2 KB · Aufrufe: 104
Bei mir kommt folgender Fehler:

Unbenannt.png
 
Achso, ja, du hast also die exe-Datei in dem Ordner "C:\Skyrim-Wallpaper" oder so gestartet.

Du musst dem aber noch sagen, welche Bilder deiner Meinung nach ähnlich sind und dazu musst du die BilderListe.txt im selben Ordner erstellen.
Und da kopierst du die Pfade deiner Bilder rein, die müssten aber eigentlich auch relative Pfade sein, also nur die Dateinamen und die Endung der Bilder, die im selben Ordner liegen, sicher bin ich mir aber nicht.

Es geht halt darum, dass das Programm die Liste auf teilt und dann immer ein Bild mit dem Folgenden vergleicht, also so:

Bild11
Bild12
Bild21
Bild22
Bild31
Bild32
.
.
.

Dann vergleicht er Bil11 mit Bild12, Bild21 mit Bild22, Bild31 mit Bild32, und so weiter.
 
Nicht für alle 800 Bilder.

Ich brauche nur einen Wert, der ungefähr die "Gleichheit" einiger Bilder dar stellt.

Suche dir also Bilder raus, deren "Gleichheit" ungefähr gleich ist. Den errechneten Wert werde ich dann nutzen, vielleicht ein bisschen höher.
Aber damit werden dann die von dir genutzten Bilder als ähnlich anerkannt, wenn du sie testen lässt. Und andere Bilder, deren "Gleichheit" ähnlich ist, werden auch als ähnlich erkannt.


Das liegt an dem Algorithmus, der das berechnet.
Ich vergleiche immer Pixel1 von beiden Bildern, also nehme immer ein Pixel von dem einen Bild und ein Pixel von dem anderen Bild, aber auf den genau selben Koordinaten.
Dann nehme ich die RGB-Werte. Der R-Wert vom 2. Bild minus dem vom 1. Bild, das gleiche auf für die G- und B-Werte. Die Differenzen werden dann zum Quadrat und zusammen gerechnet. Das passiert dann mit jedem Pixel und dem Gegenstück im anderen Bild.
Logisch dabei ist: Wenn ein Pixel mit dem anderen exakt gleich ist, dann müssen auch die RGB-Werte exakt gleich sein. Da sich die Differenz so dann aber auflöst, ist das Ergebnis 0. Wenn das nun mit jedem Pixel passiert, ist das Gesamt-Ergebnis auch 0, also sind beide Bilder gleich. Wenn nun aber nicht alle Pixel gleich sind, wenn also ein Pixel anderen Farb-Werte haben, dann unterschieden sich die RGB-Werte, die Differenz ist nicht gleich 0, also auch das Ergebnis. Das spiegelt sich dann im Endergebnis wieder.
Je größer das Endergebnis also ist, desto mehr Unterschiede gibt es in den Farb-Werten der Bilder.

Dann wird nur noch das Endergebnis genommen und mit fixen Vorgaben verglichen. Wenn es kleiner ist, als die Vorgabe für "Sehr ähnlich", dann werden die Bilder als "sehr ähnlich" angegeben.


Aber diese fixen Werte brauche ich, möglichst zu unterschiedlichen Stufen, dass man Bilder, die nur unterschiedlicher Größe sind, suchen kann, oder Bilder, die nur grobe Ähnlichkeit auf weisen.
Wie viele Bilder du da nun testest, ist deine Sache, ich kenne sie nicht. ^^
 
Ok, hier scheint ja nix mehr zu kommen, daher hab ich die Methode wegen der Ähnlichkeit von Bildern mal so umgeschrieben, dass sie auch richtig genutzt werden kann:

PHP:
        static bool IstÄhnlich(Bitmap _img1, Bitmap _img2, int grenzwert)
        {
            // größere Kantenlängen bewirken eine genauere Rechnung, da mit jedem Pixel kleinere Bildbereiche abgetastet werden
            // Allerdings ist das sehr Performancelastig und größere Kantenlängen verlangsamen die Methode
            int width = 25;
            int hight = 25;

            Bitmap img1 = verkleinern(_img1, width, hight);
            Bitmap img2 = verkleinern(_img2, width, hight);

            int sum = 0;
            for (int y = 0; y < hight; y++)
                for (int x = 0; x < width; x++)
                    sum += (int)(Math.Pow(img1.GetPixel(x, y).R - img2.GetPixel(x, y).R, 2) +
                        Math.Pow(img1.GetPixel(x, y).G - img2.GetPixel(x, y).G, 2) +
                        Math.Pow(img1.GetPixel(x, y).B - img2.GetPixel(x, y).B, 2));

            return sum < grenzwert || grenzwert == 0;
        }

        // Diese Methode verkleinert die Bilder auf eine gleiche Größe, sodass Kanten verwischen und
        // die Bilder auch Abweichungen aufweisen können.
        static Bitmap verkleinern(Bitmap image, int width = 25, int hight = 25)
        {
            Bitmap bmpOutput = new Bitmap(width, hight, PixelFormat.Format24bppRgb);
            Graphics gOutput = Graphics.FromImage(bmpOutput);
            Rectangle rectOutput = new Rectangle(0, 0, bmpOutput.Width, bmpOutput.Height);

            ImageAttributes ia = new ImageAttributes();
            ia.SetWrapMode(WrapMode.TileFlipXY);

            gOutput.InterpolationMode = InterpolationMode.HighQualityBilinear;
            gOutput.PixelOffsetMode = PixelOffsetMode.Half;
            gOutput.CompositingMode = CompositingMode.SourceCopy;

            gOutput.DrawImage(image, rectOutput, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, ia);
            bmpOutput.Save("output.bmp", ImageFormat.Bmp);

            return bmpOutput;
        }

"grenzwert" ist der Parameter, dem dann der Wert übergeben muss, der aus der Rechnung ausgehend nicht überschritten werden darf.
Wie der genutzt wird ist ganz simpel, nämlich in der letzten Zeile der Methode: return sum < grenzwert;
 
Zuletzt bearbeitet:
Also wenn du irgendwann Zeit findest und du das brauchen wolltest, dann sag Bescheid. Mit der Methode sollte es eigentlich kein Problem sein, daraus ein kleines Vergleich-Programm zu schreiben, erst recht nicht, wenn es nur eine Konsole ist.
 
Anderer Lösungsansatz: Bilder alle gleich bennnen, MD5/SHA1... -Summe prüfen, doppelte löschen... :)
Das könnte ein selbsterstelltes Programm ziemlich gut machen.
 
Wozu alle gleich benennen? o_O


Aber naja, schau doch mal etwas weiter oben. ;)
Die Methode, die einen Hash-Wert berechnet und die Bilder darüber vergleicht, hab ich gleich als erstes erstellt ^^
 
Oh sorry, habe mir die drei Seiten nicht durchgelesen :rolleyes:...
Aber den Dateinamen muss man ändern, weil der in die Berechnung der Checksumme ja einbezogen wird ;)
 
Oben