Bilder vergleichen & Motiondetection realisieren (Update!)

    • VB.NET

    Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

      Bilder vergleichen & Motiondetection realisieren (Update!)

      Hallo,

      mit dieser Klasse ist es möglich, zwei Bilder extrem schnell zu vergleichen. Genutzt wird die Bitmap.LockBits-Methode, anschließend werden die RGB-Werte per Marshal.Copy in ein Bytearray kopiert. Dasselbe passiert mit der zweiten Bitmap und die Arrays werden verglichen.

      (Source wurde am 22.12. überarbeitet und nutzt nun nicht mehr GetPixel -> beste Performance)

      VB.NET-Quellcode

      1. Public Class FastPixelCompare
      2. Public Structure FastPixelCompareResult
      3. Dim TotalValuesCompared As Int32
      4. Dim TotalDifference As Int32
      5. Dim DifferenceInPercent As Double
      6. End Structure
      7. Public Shared Function Compare(ByVal bmp1 As Bitmap, ByVal bmp2 As Bitmap, ByVal faktor As Integer) As FastPixelCompareResult
      8. Dim bmpdata1 As Imaging.BitmapData = bmp1.LockBits(New Rectangle(0, 0, bmp1.Width, bmp1.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
      9. Dim bmpdata2 As Imaging.BitmapData = bmp2.LockBits(New Rectangle(0, 0, bmp2.Width, bmp2.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
      10. Dim p1 As IntPtr = bmpdata1.Scan0
      11. Dim p2 As IntPtr = bmpdata2.Scan0
      12. Dim buffer1(bmp1.Height * bmpdata1.Width) As Byte
      13. Dim buffer2(bmp2.Height * bmpdata2.Width) As Byte
      14. System.Runtime.InteropServices.Marshal.Copy(p1, buffer1, 0, buffer1.Length)
      15. System.Runtime.InteropServices.Marshal.Copy(p2, buffer2, 0, buffer2.Length)
      16. bmp1.UnlockBits(bmpdata1)
      17. bmp2.UnlockBits(bmpdata2)
      18. Dim result As New FastPixelCompareResult With {.TotalValuesCompared = buffer1.Length + buffer2.Length}
      19. Dim diff As Int32 = 0
      20. For i As Integer = 0 To If(buffer1.Length > buffer2.Length, buffer2.Length - 1, buffer1.Length - 1)
      21. diff += If(buffer1(i) > buffer2(i) - faktor And buffer1(i) < buffer2(i) + faktor, 0, 1)
      22. Next
      23. result.TotalDifference = diff
      24. Dim pxs As Integer= If(bmp1.Width > bmp2.Width, bmp2.Width, bmp1.Width) * If(bmp1.Height > bmp2.Height, bmp2.Height, bmp1.Height)
      25. result.DifferenceInPercent = (100 / pxs) * (diff / 3)
      26. Return result
      27. End Function
      28. End Class


      LG

      Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von „kevin89“ ()

      Dauert ziemlich lang, noch dazu:

      VB.NET-Quellcode

      1. If img1.GetPixel(i, l) = img2.GetPixel(i, l) Then
      2. Else
      3. differenz = differenz + 1
      4. End If

      Das schreibt man normal so:

      VB.NET-Quellcode

      1.   If not img1.GetPixel(i, l) = img2.GetPixel(i, l) Then
      2.  differenz = differenz + 1
      3. End If

      oder

      VB.NET-Quellcode

      1.   If img1.GetPixel(i, l) <> img2.GetPixel(i, l) Then
      2. differenz = differenz + 1
      3. End If

      so.

      VB.NET-Quellcode

      1. differenz = differenz + 1

      lässt sich auch kürzer schreiben:

      VB.NET-Quellcode

      1. differenz += 1

      Würde noch eine Variable anlegen namens "Stärke", welche den Step der ForSchleife bestimmt, ist sie auf 1 schaut er 1:1 im bild nach unterschieden, ist sie z.b. auf 3 schaut die schleife 1:3 nach unterschieden da es nur 3er schritte macht dabei is zu beachten das die ForSchleife im 3 schritt das to INT erreichen kann, also durch 3 teilbar ist ;)
      -aspire
      Hey, ich bekomme bei dem Code den Fehler: "Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist."
      Und zwar bei dem Code: System.Runtime.InteropServices.Marshal.Copy(p1, buffer1, 0, buffer1.Length)


      aufgerufen wird so:

      VB.NET-Quellcode

      1. If FastPixelCompare.Compare(Bitmap.FromFile(pa), Bitmap.FromFile(pa2), 1).TotalDifference < 1 Then
      2. File.Delete(pa2)
      3. End If


      Warum?

      Grüße

      Tsuyo schrieb:

      Hey, ich bekomme bei dem Code den Fehler: "Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist."
      Und zwar bei dem Code: System.Runtime.InteropServices.Marshal.Copy(p1, buffer1, 0, buffer1.Length)
      Den selben Fehler bekomme ich auch.
      Hallo ich bekomme auch die besagte Fehlermeldung: "Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben"
      wie sieht denn nun die Lösung dafür aus`?

      VB.NET-Quellcode

      1. Dim img1 As New Bitmap(Me.PictureBox2.Image)
      2. Dim img2 As New Bitmap(Me.PictureBox2.Image)
      3. If FastPixelCompare.Compare(img1, img2, 1).DifferenceInPercent > 50 Then
      4. TextBox1.Text = "Ungleich"
      5. End If


      Ist zum testen das gleiche Bild was ich von einer Webcam in die PictureBox kopiere.
      Bilder
      • test.jpg

        34,9 kB, 640×480, 258 mal angesehen

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „kevin89“ ()

      Hallo,

      gerade den Fehler entdeckt: Habe ausversehen Stride anstatt Width genutzt.

      VB.NET-Quellcode

      1. Dim buffer1(bmp1.Height * bmpdata1.Width) As Byte
      2. Dim buffer2(bmp2.Height * bmpdata2.Width) As Byte

      müsste es korrekt heißen.

      Ist jetzt auch oben korrigiert.

      Gruß
      Ich verstehe das einfach nicht...
      Ich benutze diesen Code:

      If FastPixelCompare.Compare(PictureBox2.Image, My.Resources.c11, 1).DifferenceInPercent >= 50 Then
      MsgBox("UNGleich")
      Else
      MsgBox("gleich")
      End If

      Aber es kommt IMMER "gleich"...
      Stimmt irgendwas mit den Code nicht oder kannst du - Vincent - einen Beispielcode geben?