Bilder vergleichen

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Hi
    [Allgemein] Zwei Bilder am schnellsten/besten Vergleichen?

    Hier habe ich schon mal was gepostet. Du gehst aber prinzipiell erst mal nach der Größengleichheit und anschließend über die Gleichheit aller Pixel. Dabei arbeitest du entweder mit Bitmap.LockBits() Marshal.ReadInt32 (z.B. für ARGBs und XRGBs) o.Ä., wie halt im Code oder weniger effizient mit Bitmap.GetPixel.

    Edit: Schau dir den Beitrag aber auch an!! Nicht einfach Copy&Paste, sondern EIGENINITIATIVE!

    Gruß
    ~blaze~
    Irgendwie glaub ich dir das nicht ganz ;) Erster Link bei Google:

    VB.NET-Quellcode

    1. Dim p1 As System.Drawing.Image = System.Drawing.Image.FromFile(\"C:\\\\b1.bmp\")
    2. Dim p2 As System.Drawing.Image = System.Drawing.Image.FromFile(\"C:\\\\b2.bmp\")
    3. Dim b1 As New System.Drawing.Bitmap(p1, p1.Size)
    4. Dim b2 As New System.Drawing.Bitmap(p2, p2.Size)
    5. Dim h, w, c As Integer
    6. For h = 1 To b1.Height - 1
    7. For w = 1 To b1.Width - 1
    8. If b1.GetPixel(w, h) <> b2.GetPixel(w, h) Then
    9. c += 1
    10. End If
    11. Next
    12. Next
    13. MsgBox(c & \" Pixel sind unterschiedlich\")



    Grüße

    ~blaze~ schrieb:

    [Allgemein] Zwei Bilder am schnellsten/besten Vergleichen?

    Wenn du für jeweils 4 Pixel marshallst, dürfte das ggfs auch auf die Performance gehen, oder? Bei "normal" großen Bildern würde ich bei in nen Byte-Buffer einlesen und dann vergleichen. Wenn sehr groß, dann halt häppchenweise (Häppchen >= 16 MB o.ä.)
    Nachtrag:
    Hab mal was "gezaubert" ;)
    [Allgemein] Zwei Bilder am schnellsten/besten Vergleichen?
    Eigentlich sinds ja nicht vier Pixel, sondern 4 Kanäle. Da der Prozessor eh mit Integern rechnen kann, machts denk ich mal keinen Unterschied. Ein Pixel hat 4 Kanäle, ein Kanal hat 1 Byte. Deswegen die Step 4 oder was meinst du?
    Einlesen in einen Puffer verlangsamt die ganze Geschichte, denk ich mal, da Lesen und Schreiben sehr lange (relativ) dauert. Die Library kenne ich zwar von einem Kumpel, aber die ist dann doch etwas Overkill für das Vergleichen zweier Bilder, denke ich ;).

    Gruß
    ~blaze~

    ~blaze~ schrieb:

    Ein Pixel hat 4 Kanäle, ein Kanal hat 1 Byte

    Das mein ich nicht. Da ist dein Ansatz komplett falsch ;)
    Du brauchst nicht zu unterscheiden, ob das Bild 16 bit ist, 24, 32 oder was auch immer. Du hast zwei Speicherbereich die du auf Gleichheit prüft. Gleich sind sie, egal ob du bytes, Ints oder int64 einliest. Auf aktuellen Systemen (64 bit) dürfte deswegen das einlesen von int64 das günstigste sein. afaik sind bitmaps sowieso immer 4 bzw 8 byte alligned.

    Nein, ich meine - wobei ich es nicht weiß - dass bei jedem "Marshal" zugriff auf unmanaged Speicher die "Grenze" übertreten werden muss, was kostspielig ist. Es macht also ggf mehr Sinn, die Grenze nur EINMAL zu übertreten -> Marshal.Copy in ein managed Array(of int64). Müsste man halt mal ausprobieren.
    Eine weitere Leistungssteigerung wäre ggf mit einer "5 Feld Messung" (wie bei ner DigiCam) möglich, indem man zuerst den Mittelpunkt und 4 Eckpunkte (Abstand vom Rand 10-30 px um "Rahmen" auszuschließen) prüft. Damit dürften viele Bilder schon gut aussortiert werden.


    aber die ist dann doch etwas Overkill für das Vergleichen zweier Bilder, denke ich

    Hängt davon ab, wie schnell es sein soll. Wie gesagt: Zwei 24 MB Bilder werden in rund 50 Millisekunden verglichen. "Beinahe" Echtzeit (na ja). Das dürfte für einige Anwendungen wichtig sein. Und 400kB für die Signal.DLL sind ja nun wirklich nix, worüber sich irgendjemand Gedanken machen würde, oder?

    Hast du deine Funktion mal gebänscht?
    Einfach mit ner dummy Bitmap (new Bitmap(2500,3000, usw). Braucht ja kein "reales" Bild zu sein.

    EDIT: Habs selbst mal probiert (C&P von deinem Code war ja einfacher). 1032 Millis für die gleichen Bilder wie beim Framewave Code. Bei einem Faktor von 20 "lohnen" sich 400 kB imho schon, oder?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „picoflop“ ()

    Gut, dürfte dann wohl ein kleiner Leistungsunterschied vorhanden sein. Mit den per-Byte-Vergleichen hast du recht, allerdings wollte ich die Möglichkeit noch implementieren, dass auch Vergleiche zwischen verschiedenen Formaten statt finden können, was ich dann aber wegen unnützem Aufwand weggelassen hatte. Das mit der Blockade ist mir letztens wohl auch schon mal über den Weg gelaufen, als ich eigene Pixelpuffer und Tiefenpuffer verwendet habe und da Marshal extrem schlecht abgeschnitten hat. Naja, man lernt immer was neues.
    Zu den 400 KBs: Gerade für sehr kleine Anwendungen achte ich immer darauf, dass möglichst wenig Speicherbedarf vorherrscht. Da kommts halt auf den Fall drauf an. Wenn man jetzt hunderte Bilder hat, muss man da schon eine effiziente Lösung finden. Wenn man nur 2 Bilder vergleicht, kann man schon mal solche Zeiten erlauben.

    Übrigens: Um deinen Vorschlag zu ergänzen kann man auch rekursiv vorgehen und die zu vergleichenden Bitmaps in vier gleich große Rechtecke zerlegen und den Vorgang für jedes Rechteck auffrufen, bis die Größe der Rechtecke 1x1 Pixel beträgt. Nach jedem Zerlegen kann man die Mittelpunkte miteinander vergleichen. Eventuell sollte man bei der 1. Messung aber auch die Randpunkte mit einbeziehen, da diese sonst ganz am Schluss gemessen werden (bzw. gar nicht). Restliche Randpuntke sind dann natürlich das Zentrum bzw. die Randpunkte des letzten Rechtecks.

    Gruß
    ~blaze~

    ~blaze~ schrieb:

    Gerade für sehr kleine Anwendungen achte ich immer darauf, dass möglichst wenig Speicherbedarf vorherrscht.

    Ich nicht ;) Speicher hat man. Wenn nicht, kann man ihn kaufen. Sogar billig.

    Aber wie gesagt. Ne kleine C# DLL (weil man da ja unsafe verwenden kann) ist in diesem Spezialbereich fast genauso schnell. Irgendwann probier ich das aber noch mal mit Intels OpenCV.
    Hi
    Nein, geht es nicht und außerdem gibts dann zwei gleiche Hash-Werte für zwei verschiedene Bitmaps. Da ein Hash eine fest vorgegebene Länge n in Bytes hat, gibt es pro Hash maximal 256^n verschiedene Möglichkeiten. Wenn Du jetzt aber 256^n +1 Bitmaps vergleichst, ist mit Sicherheit mindestens eine Überschneidung der Hashes dabei.

    Gruß
    ~blaze~