"Bewegungssensor" mit Webcam

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von picoflop.

    "Bewegungssensor" mit Webcam

    Hallo,
    Ich spiele des öfteren Dart und habe mir gedacht, warum nicht eine Webcam so positionieren, dass sie genau auf die Scheibe gerichtet ist und dann ein Programm das Spiel verfolgen lassen.
    Hierzu wollte ich euch nun fragen, was ihr denkt, wie man das am besten und saubersten löst.
    Ich habe irgendwo mal eine Anleitung gesehen, womit man einen Bewegungssensor gut simulieren kann (sich bewegende Objekte wurden grün umrandet).
    Aber das war sehr langsam und hakte des öfteren.
    Ich habe mir nun gedacht, ich mache jede Sekunde oder jede 1/2 ein Foto und gucke dann, was sich verändert hat.

    Mich würde wirklich sehr interessieren, wie ihr an dieses Projekt rangehen würdet und was eurer Meinung nach der sauberste Lösungsweg wäre.
    einfachste Lösung:
    2 Bilder vergleichen:
    - Annahme: keine Veränderung.
    2 Mittelwerte bilden, haben die Werte eine Abweichung größer als nn, Veränderung.
    Summe der Beträge der Pixeldifferenz, Wert größer als nn2, Veränderung.
    Bestätigung: keine Veränderung.
    fertig.
    ------------------
    Veränderung:
    Differenz der Bilder berechnen (Achtung, es können negative Werte herauskommen)
    alle Beträge von Pixeldifferenzen kleiner als nn3: keine Veränderung -> schwarz
    übrig bleiben die Gebiete, die sich verändert haben.

    Die Werte nn, nn2, nn3 durch Erfahrung bestimmen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nun - ich habe gar keine Web-Cam, über Code mache ich mir keine Gedanken.
    Nur über den Algorithmus.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Naja, aber da du ja schon erklärt hast, wie man soetwas realisieren könnte, müsstest du ja auch Ahnung haben, wie man sowas in Code Realisiert.
    Es geht ja nur um die Bewegungserkennung, wie man das Webcam, Livestream, oder sonstwas Video in eine Picturebox bekommt, sollte eigentlich jeder für sich wissen.
    Es würde ja eigentlich nur eine Funktion reichen, die ausliest, wie viele horizontale Pixel sich zwischen zwei Bildern verändert haben.
    Aber dazu finde ich weder was Brauchbares in Google, noch in diesem Forum. Der TE anscheinend auch nicht.
    Bei sowas sollte man aber auch wissen, wie gut die Webcam ist. Denn JPG-Artefakte werden schließlich auch als Unterschied gewertet. Somit unterscheidet sich jedes Bild vom vorherigen, auch wenn sich in Wahrheit nichts getan hat.

    Wie Rod schon gesagt hat, dass läuft wirklich über einen Mittelwert am sinnvollsten.
    „Was daraus gefolgert werden kann ist, dass jeder intelligentere User sein Geld lieber für Bier ausgibt, um einen schönen Rausch zu haben, und nicht dieses Ranzprodukt.“

    -Auszug aus einer Unterhaltung über das iPhone und dessen Vermarktung.
    @m9898: Fang doch einfach mal an.
    Nimm Dir irgend zwei Bilder und gieße den Code.
    Allerdings solltest Du auch von Bildverarbeitung ein wenig Ahnung haben.
    @VBLukas: Ich hab schon einige Vorstellung davon, da ich aber weiß, das das ausufern würde, lasse ich die Finger hier davon.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    http://www.aforgenet.com/framework/docs/
    Und dann im Namespace AForge.Vision.Motion rumspielen.


    Ich könnte hier jetzt einen Beitrag mit 2000 Schimpfwörtern auf diesen Internetfilter hier schreiben :cursing:

    Könnte jemand die dll(?) Hier mal als Anhang hochladen? Wäre nett :)
    So. Tut mir leid für meine lange Abwesenheit. Ich saß 2 Wochen in Frankreich - ohne jede Verbindung zur Außenwelt - auf 'nem Campingplatz.
    Nja back to topic:

    Ich habe ein wenig recherchiert und das Anzeigen der Cam ist wirklich überhaupt kein Problem. Genauso wenig das Verarbeiten eines "Fotos" (eines Bildes der Webcam).
    Da ich nun aber keine lib/dll gefunden habe, die mir die zwei Bilder vergleicht, wollte ich mir mal selbst so eine Funktion schreiben.
    Ich möchte halt auch die Koordinaten jedes Punktes finden.
    Daher habe ich damit angefangen, beide Bilder mit zwei verschachtelten Schleifen zu durchlaufen und jeweils die Farben zu vergleichen (Beispielsweise darf hier maximal eine Abweichung von 10 pro RGB-Farbe vorhanden sein) :

    VB.NET-Quellcode

    1. ' img1 und img2 (As Bitmap) sind gleichgroß. gleicher winkel der kamera etc.
    2. ' es sollen nur änderungen festgestellt werden.
    3. Dim l As New List(Of Point) 'hier werden alle geänderten Punkte gespeichert
    4. Dim c1, c2 As Color
    5. For x As Integer = 1 to img1.Width-1
    6. For y As Integer = 1 to img1.Height-1
    7. c1 = img1.GetPixel(x, y)
    8. c2 = img2.GetPixel(x, y)
    9. if (Math.Abs(c1.R - c2.R) > 10) Or (Math.Abs(c1.G - c2.G) > 10) Or (Math.Abs(c1.B - c2.B) > 10) Then
    10. l.Add(New Point(x, y))
    11. End If
    12. Next
    13. Next


    1. Problem: Jetzt ist aber die Funktion GetPixel sehr langsam und der Vergleich dauert mehrere Sekunden.
    2. Problem: Lass ich das nun laufen kommt folgende Fehlermeldung an der If-Abfrage: "Die arithmetische Operation hat einen Überlauf verursacht."
    "Hinweise zur Fehlerbehebung: Dividieren Sie nicht durch 0" -> Tu ich nicht?

    Ich hab diesen Prozess auch schon in einem anderen Thread ausgeführt. Aber das verhindert ja nur das "Stehenbleiben" des Programms und verkürzt nicht die Laufzeit.

    Habt ihr da eine bessere Lösung? Oder muss ich das mit der langsamen Funktion GetPixel machen?
    Woran liegt dieser Überlauf?
    ja ok. ich will ja eh eine dartscheibe "auslesen", da brauch ich ja nur die scheibe und nicht das ganze bild. ebenfalls ist das bild nicht ganz so groß, wie das was ich zum testen nehme ;)
    bleibt immernoch das problem mit dem überlauf. woran liegts?
    und es gibt keine schnellere alternative zu getpixel?
    Das Problem mit dem Überlauf: Byte - Byte ergibt Byte. Byte kann aber keine negativen Werte darstellen. Darum bei "Math.Abs(c1.R - c2.R)" die .R, .G und .B Werte zuerst in Integer konvertieren: "Math.Abs(CInt(c1.R) - CInt(c2.R))".
    Das Problem hatte ich mal bei C#. Ob es hier anders gehandhabt wird weiß ich nicht aber ich denke das sollte das Problem beheben.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Du solltest das gesamte Bild in einen Arbeitsspeicher kopieren, wo Du freien Zugriff hast.
    FastPixel
    Außerdem:

    VB.NET-Quellcode

    1. Dim bmpData As System.Drawing.Imaging.BitmapData
    2. bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
    3. IntPtr ptr = bmpData.Scan0
    4. ' mit dem Speicher was tun
    5. bmp.UnlockBits(bmpData)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!