Algorithmus für "dirty rectangles"/"motion detection"

Hi,

für meine Idee mit dem VNC artigen Server basierend auf Java, brauch ich einen Algo der mir sagen kann, welche Bereiche im Bild sich zwischen Bild A und Bild B geändert haben.

Das hier --> http://www.codeproject.com/KB/audio-video/Motion_Detection.aspx <-- beschreibt das ganze schon recht gut für C#. Aber da wird auf teilweise fertige Filter/Funktionen gesetzt die einem Bildunterschiede ausspucken.

Wie/Wo gibts sowas in Java? Am liebsten wär mir’s wenn ich keine externe Lib dafür bräuchte…

Any ideas?

  • Alex

Hiho,

fürs erste kann ich dir die Stichworte Kantenerkennung und Sobel geben.

Damit lassen sich auf einem Bild Kanten erkennen. Also zum Beispiel wenn sich Fenster auf dem Desktop befinden. Gibt es nun (grobe) Unterschiede der Kanten zwischen Bild A und B, hat sich an den Fesnsterpositionen etwas geändert.

In wie weit das dir nun hilft ist fraglich, da deine Formulierung so klingt, als könnten sich auch Bereiche die Farbe ändern.

Man könnte in diesem Fall vielleicht damit experimentieren, die Bilder in Graustufen umzuwandeln - würde ich schon für die Kantenerkennung empfehlen - und nach dieser Grauumwandlung die Farbsignatur des gesamten Bildes miteinander vergleichen.

Mit dem Sobeloperator erzeugte Bilder lassen sich auch einfach über ihren Farbmittelwert vergleichen.

Noch eine Idee SobelBilder XOR verknüpfen - je weiter weg das Ergebnis von 0 ist, umso größer ist der Unterschied.

Noch ein Stichwort: KettenCode für die Freistellung andersfarbiger Objekte inenrhalb eines Bildes. Wird zum Beispiel zum computergestützten Auszählen von Blutkörperchen eine Mikroskopbildes verwendet.

bye Saxony

Hiho,

ich möchte aber bezweifeln, das diese Algorithmen deiner FPS-Rate von 15 dienlich sein werden. :wink:
Selbst große Grafikprogramme (bspw.PS) brauchen schon Zeiten im Milli-Sekundenbereich um Bilder der Größe 1024x768 mit solchen Filtern zu bearbeiten.

[edit]
Mein Gimp braucht bei einem DesktopScreen von 1280x1024 etwa 0,5-1s, je nach Algo! Und das ist erst einmal nur die Anwendung des Filters und noch keine Vergleiche ob sich überhaupt etwas geändert hat.
[/edit]

bye Saxony

Hmm, irgendwie muss es aber noch schneller gehen, denn VNC hat sowas schon eingebaut. Im Lokalen Netzwerk geht das selbst bei 2x 1920*1200 (also dual-head) nahezu im echtzeitbereich. Dass ich das mit Java nicht hinkrieg ist klar. Die Hauptbremse wird da das capturen des Screens mit dem Robot sein.

Was mir aber noch eingefallen ist (leider ein etwas naiver Ansatz):

Ich unterteile das Image in ein Raster aus Blöcken. Sowohl beim letzten Bild, als auch beim nachfolgebild. Und dann vergleiche ich Block1 aus Bild 1 mit Block 1 aus Bild 2.

Gibt es eine Differenz, so muss dieser Block übertragen werden. Die Grnularität lässt sich das dann mittels Blockgröße/Rastergröße einstellen, jenach gewünschter Netzwerklast. Muss nur noch irgendwie möglichst performant solche Blöcke vergleichen können.

Oder aber einen der tollen Algos finden die unter anderem VNC benutzt (afaik kann VNC auch noch über einen “speziellen” Displaytreiber das direkt auf der Grafikkarte im Grafikspeicher analysieren, hab ich gelesen. Aber da komm ich mit nativem Java nicht so einfach hin.).

  • Alex

Ich wollte gerade schreiben das VNC keinesfalls mit Java arbeitet oder auf irgendeiner VM(und damit Systemtechnisch „abgeschirmt“) läuft.
Ich denke Du wirst da wirklich nur erfolgreich/schnell sein wenn Du auf nativer(maschinen) Ebene arbeitest. Soll heißen, das analysieren der Pixel oder Blöcke auf C(wenn nicht sogar ASM)-Ebene wirst Du Performancetechnisch besser kommen. Denke ich.

Gut Schuß
VuuRWerK :wink:

Will mich keiner verstehen? Dass ich hardwarenahe Dinge mit nativem Code besser hinbekomme … Dazu muss ich wohl nicht nochmal was sagen.

Aber es geht gerade drum unabhängig von nativem Code zu sein, auch wenns etwas langsamer ist.

Wenn man keine allzu mörderhaften Auflösungen scrapen will, könnte das sogar performant genug sein. Aber da hilft alles mutmaßen nicht, das muss man ausprobieren.

Wenn doch noch jemand einen Algorithmus hat mit dem ich nicht jedes einzelne Pixel anschauen muss: Her damit.

Da fällt mir ein:

Da es recht unwahrscheinlich ist, dass sich auf einem Bildschirm etwas an einer Stelle ändert was kleiner ist als 2 Pixel, würde es sogar reichen wenn ich nur jeden zeiten Pixel in einem Block mit dem des anderen Blocks vergleiche. Damit würde sich der Aufwand etwa halbieren…

Evtl kann ich sogar nur jeden dritten oder sogar 4. pixel prüfen…Woebei dann klar ist: Je mehr Pixel ich auslasse, desto ungenauer die erkennung. Aber jeder zweite Pixel in einer Pixelzeile, wobei in der nächsten Pixelzeile das ganze dann verschoben um eins stattfindet (also ein Karo-Muster), sollte funktionieren und genau genug sein.

  • Alex

Ja sry, wollte nur mal meinen Gedanken dazu äußern als ich Deinen Post gelesen habe … Du wirst das sicher wissen aber na und, ich hab auch was dazu gesagt :o)

Soweit ich weiß arbeitet der MPEG-Codec bei Filmen so, es werden Frame für Frame nur die Pixel ausgetauscht die sich gegenüber dem vorherigen verändert haben. Ob dies jetzt pixelgenau passiert oder ob es ebenfalls mit pixelblöcken geschiet weiß ich nicht.

Gut Schuß
VuuRWerK :wink:

Da schau her: http://www.ra.cs.uni-tuebingen.de/lehre/ss00/pro_internet_ausarbeitung/proseminar_guerbey_ss2000.pdf

Gut Schuß
VuuRWerK :wink:

Ich weiß nicht ob es dir was hilft, aber du kann von realvnc.com den Quellcode der FreeEdition runterladen. Der ist bestimmt in C/C++ geschrieben aber vielleicht bringts dir was.

Das Programm hat bei mir bisher immer zu 98% problemlos funktioniert, ohne dass das komplette Bild übertragen wurde

@Vuurwerk

Dass MPEG es ähnlich macht ist klar. AFAIK auch Blockweise. Und wenn ich mich recht entsinne, dann kann man im Codec sogar irgendwo einstellen, wie groß die Blöcke sein sollen. Zusätzlich kommt dann noch die Sache mit dem Verschiebungsvektor dazu. bei MPEG gehts ja dran dass sich was von A nach B bewegt und dann ein Block einfach woanders angezeigt wird.

Bei einem gescrapten Screen funktioniert das glaub ich nicht so gut, da sich meist nicht einzelne Objekte bewegen sonden ganze Flächen (jmd. verschiebt ein Fenster oder ein vorher nicht vorhandenes Fenster geht nun auf).

Aber dennoch könnte man hier das Bild in Blöcke einteilen und dann das vorher Bild mit dem Nachherbild Block für Block vergleicheh und nur die Blöcke mit einem inhaltlichen Unterschied verschieben.

Wenn ich’s richtig weiß (ohne nachgesehen zu haben), komm ich an einzelne Teile des Bildes, also so ein Block, in Form eines Arrays dran. Wenn ich richtig weiß sogar ein eindimensionales Array.

Wie vergleiche ich nun möglichst effizient zwei Arrays miteinander?! Pixel für Pixel ist sicht nicht gut (und jeder zweite Pixel wäre wohl auch noch recht schlecht). Es gibt ja genug Sortieralgorithmen. Gibts auch “Vergleichsalgorithmen”?! Vielleicht einen Hash (welcher?) bilden und den Vergleichen?

Zur Sache mit dem VNC Source:

Hab da Beruflich ein wenig mit der Thematik zu tun. AFAIK captured VNC nicht einfach den ganzen Screen und holt sich die Unterschiede zum letzten Screen und überträgt nur diese, sondern es hängt sich in die Window-Message-Queue und wird somit vom OS benachrichtig: “Window ABC hat sich von Koordinate A nach B bewegt”. Damit ist es ein leichtes “zu erkennen” was sich ändert. Das heisst abschauen wird da nicht viel helfen. Leider.

Naja, mal schauen wie performant mein naiver Ansatz mit dem Blöcken und der Idee, nur jeden zweiten Pixel zu vergleichen, ist.

Hab mal ein Bild angehängt wie ich mir das vorstelle mit dem “jeden zweiten Pixel” in einem Block. Nur eben die “Pixel” stark vergrößert.

Gruß
Alex

Achso ja das kann sein, weil ab und zu muss man das Fenster bewegen damit es neu gemalt wird.

Aber wie wäre es wenn du in dem Fall nativ wirst und so für jedes OS dir etwas baust? Und halt für den Notfall greifst du auf den Robot zurück.

Das wäre eine überlegung. Wäre dann aber einiges mehr an Arbeit. Schließlich will ich wirklich Windows, Linux und MAC unterstützen.

Erste tests zeigen dass die Performance durchaus okay ist. Und 10fps reichen für eine recht flüssige Bedienung aus (auch wenn mans Anhand der Zahl nicht so ganz glauben mag, aber ich habs eben schon in einer Beispielanwendung probiert).

– Alex