Flash AS3 – ColorBlobDetector / Color-Tracking

August 27th, 2010

Da ich einen “Color-Tracker” brauchte hab ich gedacht, wenn dann könnt ich ja auch eine Demo-Applikation machen und diese online stellen. Außerdem möchte ich hier den Werdegang meines “ColorBlobDetector” darstellen.

Color-Tracking / Blob-Detection, was ist das?

Zuerst mal für diejenigen die sich unter dem Begriff  “Color-Tracking” nichts vorstellen können eine kurze Einleitung.

Beim Color-Tracking geht es darum zusammengehörende Bereiche gleicher Farbe in Bildern aufzufinden (Farbbildsegmentierung) und diese zu verfolgen. Zum Beispiel könnte die gesuchte Region ein roter Ball in einem Bild eines Gartens sein, wobei der Ball von einem Kind herumgerollt wird. Das Auffinden allein (worum es auch in diesem Beitrag geht) wird allgemein als “Detection” (Erkennung) bezeichnet. Daher auch der Klassenname “ColorBlobDetector”.

Das Tracking, also die Verfolgung des Balls über mehrere Bilder, benötigt wieder eine eigene Verarbeitung (meist Tracker genannt). Hier verschwimmen die Grenzen zwischen Color-Tracking und Motion-Tracking etwas da beides darauf abzielt eine Bewegung in einer Abfolge von Bildern zu erkennen.

Color-Tracking in der (Flash) Vergangenheit

Am Anfang stand natürlich die Suche nach bereits existierenden Lösungen. Also hier mal ein Auszug meiner Funde. Über Hinweise auf weitere Beispiele in Form von Kommentaren würd ich mich übrigens sehr freuen ;) .

  • Flash Color Tracking – 2005

    Grant Skinner veröffentlichte 2005 in einer seiner Präsentationen einige Ansätze zum „Color Tracking“ in AS2. Diese wurden vermutlich mit Hilfe der damals neuen BitmapData-API des Flash Player 8 erstellt.

  • Flash Color Tracking – 2008

    Im Jahr 2008 publizierte Benjamin Bojko einen „Mean Shift Tracker“ welcher im CIEL*a*b* Farbraum und unter Verwendung des Mean-Shift-Verfahrens arbeitet.

    Benjamin Bojko´s Mean Shift Tracker

  • Flash Color Tracking – 2009

    Im November 2009 veröffentlichte Jonathan Cipriano ein „Color Tracking“ Verfahren welches auf einer Transformation in den HSV-Farbraum und einem Schwellwertverfahren aufbaut. Zur Detektion der einzelnen Flächen wurde nach dem Schwellwertverfahren die getColorBoundsRect() Methode der BitmapData Klasse der Flash API genutzt. Insbesondere wenn mehrere nicht zusammenhängende Regionen die selbe Farbe aufweisen hat dieses Verfahren jedoch noch schwächen. Wie im Bild ersichtlich werden gleichfarbige Gegenstände als eine Region erkannt.

    Jonathan Cipriano AS3 HSV Color Tracker

Aufbau des “Color-Trackers”

Um das Problem des Color-Tracking etwas in den Griff zu bekommen habe ich es zuerst in Teilprobleme zerlegt:

  • - Farbbildsegmentierung: farbige Pixel aus dem Bild extrahieren (“color segmentation”).
  • - Säuberung: unerwünschte Pixel entfernen ( z.B. Rauschen).
  • - Labeling: zuammenhängende Regionen finden (“blobdetection /labeling”)

Farbbildsegmentierung

Um nur die Pixel zu extrahieren, die der gesuchten Farbe entsprechen, wurde ganz einfach ein Filter auf das Bild angewandt welcher die Farbwerte jedes einzelnen Pixel in den Vergleichsfarbraum (ich habe den HSV-Farbraum gewählt) konvertiert und dann bewertet, ob dieses der gesuchten Farbe entspricht oder nicht. Wenn ja wird das Pixel mit Weiß, anderfalls mit Schwarz gefüllt.

links: das original Bild, rechts: das resultat des HSV-Filters

links: das original Bild, rechts: das resultat des HSV-Filters

Säuberung

Nach der Extraktion liegen die Pixel nun als Schwarz-Weiß-Bild vor aus welchem nun “nurmehr” die einzelnen Region herausgefiltert werden müssen. Um das schnell zu erledigen empfiehlt es sich zuerst noch die Pixel, welche ohnehin uninteressant sind, auszusortieren und Löcher in großen Regionen zu schließen. Das Schließen der Löcher passiert über einen sogenannten “Closing“-Filter. Das Entfernen von zu kleinen Regionen wird dadurch erledigt, dass das gesamte Bild geblurrt wird und dann nur die Pixel ausgewählt werden welche noch völlig weiß sind.

links: Das bild nach dem HSV-Filter, rechts: das bereinigte Bild

links: Das bild nach dem HSV-Filter, rechts: das bereinigte Bild

Labeling

Für die “schnelle” Erkennung von zusammenhängenden Regionen gibts es zum Glück schon ganz passable Lösungen die auch hier zum Einsatz kommen. Grundsätzlich basieren sie auf der floodFill() und der getColorBoundsRect() Methode der BitmapData Klasse.

links: bereinigtes S/W-Bild, rechts: grün dargestellt die Regionen

links: bereinigtes S/W-Bild, rechts: grün dargestellt die Regionen

So und damit is der “ColorBlobDetector” fertig.

rot markiert die gefundenen Regionen

rot markiert die gefundenen Regionen


Mini Demo

Hier nun ein kurzes Code-Beispiel wie der ColorBlobDetector zu verwenden ist:

package
{
	import at.geoathome.cv.blob.ColorBlobDetector;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	/**
	 * @author Georg Kamptner
	 *
	 * License: Do as you wish, but don`t be evil
	 */
	public class Main extends Sprite
	{
		// image
		[Embed(source="image.png", mimeType="image/png")]
		protected var Img:Class;
		protected var _img:Bitmap;
		protected var _imgContainer:Sprite;
		protected var _graphicsContainer:Sprite;

		// color blob detector
		protected var _colorBlobDetector:ColorBlobDetector;
		private var _roi:Rectangle;

		public function Main():void
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		protected function init(e:Event = null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);

			// create image
			_img = new Img() as Bitmap;

			// Since Bitmap is not interactive we need a Sprite
			// to handle mouse events.
			_imgContainer = new Sprite();
			_imgContainer.addChild(_img);
			addChild(_imgContainer);

			// draw the found regions into this sprite
			_graphicsContainer = new Sprite();
			addChild(_graphicsContainer);

			// add mouse events
			_imgContainer.addEventListener(MouseEvent.CLICK, detectColorUnterMouse);

			// detector (this is it) - debug version needs a sprite to draw into
			_colorBlobDetector = new ColorBlobDetector( 2, 2000, 2, 2000);
			_colorBlobDetector.setConfig(2.0, 6.0, 9.0);
			_colorBlobDetector.setThresholds(8.0, 0.20, 0.0, 0.0);
			_roi = new Rectangle(0, 0, _img.width, _img.height);
		}

		protected function detectColorUnterMouse(e:MouseEvent):void
		{
			// get color unter mousecursor
			var rgb:uint = _img.bitmapData.getPixel(_img.mouseX, _img.mouseY);
			var r:uint = rgb >> 16;
			var g:uint = rgb >> 8 & 0xff;
			var b:uint = rgb & 0xff;

			// detect blobs
			_colorBlobDetector.detectRGB(_img.bitmapData, r, g, b, _roi);

			// draw regions
			_graphicsContainer.graphics.clear();
			for (var i:uint = 0; i < _colorBlobDetector.numOfBlobs; ++i)
			{
				_graphicsContainer.graphics.lineStyle(2, 0xff0000);
				_graphicsContainer.graphics.drawRect(_colorBlobDetector.blobs[i].x,
												_colorBlobDetector.blobs[i].y,
												_colorBlobDetector.blobs[i].width,
												_colorBlobDetector.blobs[i].height);
			}

			// debug trace
			trace("Blobs found: " + _colorBlobDetector.numOfBlobs + ", Duration in MS: " +_colorBlobDetector.detectionDuration + " in FPS: " + int(1000 / _colorBlobDetector.detectionDuration));
		}

	}

}

30€ Flash Multitouch (MTmini remake) in AS3

Juli 2nd, 2010

Hier mein Versuch ein low-cost remake eines multitouch “boards” in Flash umzusetzen.

Inspiriert dazu hat mich dieses Youtube Video von Seth Sandler:

Es funktioniert ganz gut und basiert “rein” auf AS3 (mit etwas Hilfe von Pixel Bender). Es wird also keine touchlib, CCV oder sonstiger c/c++ Code benötigt. Zum Auffinden der Regionen habe ich den von Tomek Augustyn (aka Og2t) beschriebenen Algorithmus (Detecting blobs at speed of light) verwendet.

Genug geredet, so siehts aus:

Hier gibts den Code zum Download (als FlashDevelop Projekt). Allerdings ist dieser noch nicht aufgeräumt und noch sehr “alpha” ;) . Als nächstes werde ich wohl eine Hintergrund-Modellierung ähnlich der im CCV implementieren, bin mal gespannt was sich daraus noch entwickelt.

Im Youtube Video werden die aktuellen Links zur c++ Software leider nicht wirklich genannt, hab sie hier mal zusammengesucht:
- CCV 1.3
- TUIOMouse

“Playstation Move” Controller

Juni 20th, 2010

Da nun Sony mit “Playstation Move” und Mircrosoft mit “Kincet” (Project Natal) der “Nintendo Wii” den Kampf ansagen hab ich mich mal auf die Suche gemacht um herauszufinden wie denn dieses “Playstation Move” genau funktionieren.

Playstation Move Controller, Playstation Eye, Technical Information

Für alle die gerne genau wissen wollen wie denn nun der neue Playstation Move Controller funktioniert. Hier gibt es ein einteressantes Interview dazu, viel Spaß.

Paint with Tomatoes and Lemons

Mai 15th, 2010

Paint bzw. Whiteboard mit zwei “Markern” (vorzugsweise Tomate und Zitrone ;) ). Hier gehts lang

Nachtrag: Eventuell ließe sich der Tracking-Algorithmus noch robuster machen wenn man Labeling (aka Blob Detection) einsetzt um die einzelnen Regionen voneinander zu unterscheiden. Ein höchst interessanter Link dazu: Fast Blob Detection .

Playing pong with tomatoes and lemons.

Mai 12th, 2010

Ein kleines Experiment um meine AS3 Farberkennung auch mal sinnvoll einzusetzen ;)
Vorerst nur als Video, aber das fertige Game kommt bald. Fertig: hier geht zum Spiel.

PHP Array Inhalte trimmen, trim()

April 21st, 2010

Nur eine ganz schnelle Notiz zum Ausführen von trim() auf jedes Element eines Arrays ohne eine Schleife benutzen zu müssen.

<?php
$arr = Array(' Test ', 'Test ', ' Test');
$arr = array_map('trim', $arr); // trim all
var_dump($arr);
?>

Online Eieruhr

April 12th, 2010

Oft is es so dass man schnell mal eine Erinnerung braucht, sei es um jemanden in 20 Minuten vom Bahnhof abzuholen oder einfach nur ein paar Eier zu kochen. Da ich viel Zeit vor dem Pc verbringe und ich eigentlich ständig mein Handy irgendwo liegenlasse, ist der Wecker am Handy eher zwecklos für mich.
Außerdem ist dieser oft viel zu umständlich einzustellen, Sony Ericsson Handy Besitzer wissen wovon ich spreche ;) .
Aber es gibt Abhilfe, vorallem wenn man sowieso so gut wie immer den Browser offen hat. Sie heisst e.ggtimer.com.

Eieruhren gibt es ja viele im Internet, aber das schönes an e.ggtimer ist dass sie wunderbar einfach zu bedienen ist. Einfach http://e.ggtimer.com/30min in den Browser eingeben und fertig, schon läuft der Timer.

Mein Tipp, legt euch im Browser e.ggtimer.com als Schlüsselwort an, damit lässt sich der gesamte Aufruf auf z.B.: “t 30min” verkürzen. Ist doch 1.000 mal einfacher und schneller als sich den Handywecker zu stellen, oder?

Flame Painter

April 2nd, 2010


Bilder dieser Art zu erstellen ist normalerweise doch mit relativ viel Aufwand verbunden. Nicht jedoch wenn man Peter Blaskovic`s geniales “Flame Painter” Tools kennt. Damit lassen sich tolle Effekte erzielen und auch seine anderen Experiment sind durchaus sehenswert.

Einziger Nachteil, zum Bestaunen seiner Arbeiten benötigt man ein installiertes Java Plugin.

Peter Blaskovic´s Flame Painter

Flash 9-scale und sein gewöhnungsbedürftiges Verhalten

März 21st, 2010

Manches mal hat Flash so seine Tücken, besonders wenn es um das Zusammenarbeiten von AS3 Code mit der Flash IDE erstellten Inhalten geht.

Hier gibt es insbesondere dann Probleme wenn versucht wird ein Element, welches aus einer Füllung und einer “Outline” besteht, in ein 9-scale Element umzuwandeln und dann mit ActionScript zu skalieren (ob nun mit .width/.height oder .scaleX/.scaleY macht hier keinen Unterschied).

Hier eine Schritt für Schritt Anleitung wie dieser Fehler reproduziert und behoben werden kann. Schon mal vorweg die Lösung heißt “Convert Lines to Fills”.

 

Schritt 1: Einen Movieclip mit Füllung und Rand erstellen und als 9-scale modifizieren.

Nachdem der MovieClip erstellt wurde kann man den Rand modifizieren, je größer der Rand desto auffälliger der Fehler. Zur demonstration habe ich ihn hier auf 5 erhöht.

 

Schritt 2: Nachdem der Movieclip erstellt wurde wird er auf die Bühne gezogen und mit AS positioniert.

X-Position 25 Pixel und Breite 350 Pixel, damit sollte der MovieClip genau bei 375 Pixel enden.

Leider kommt Flash hier ziemlich durcheinander und brechnet die Breite und Höhe völlig falsch.

 

Schritt 3: Beheben des Fehlers durch die Konvertierung von Linien in Füllungen.

Durch die Konvertierung der Linien zu Füllungen kann der Fehler behoben werden.

Allerdings sollte man darauf achten dass der Inhalt des MovieClips nach der Konvertierung wieder korrekt positioniert wird.

 

Schritt 4: Fertig

Geschafft, somit wurde Flash ausgetrickst und die Skalierung funktioniert auch mit ActionScript einwandfrei.

Fünf Wege wie dich Computerspiele süchtig machen

März 13th, 2010

In einem Artikel auf cracked.com legt David Wong dar wie es “World of WarCraft” oder “Farmville” schaffen Spieler über sehr lange Zeiten vor den Bildschirmen zu halten.

Spaß scheint dabei selten die treibende Kraft zu sein.

5ways_wow

What the hell? Look, I’m not saying video games are heroin. I totally get that the victims had other shit going on in their lives. But, half of you reading this know a World of Warcraft addict and experts say video game addiction is a thing. So here’s the big question: Are some games intentionally designed to keep you compulsively playing, even when you’re not enjoying it?

Oh, hell yes. And their methods are downright creepy.

[...]

Gaming has changed. It used to be that once they sold us a $50 game, they didn’t particularly care how long we played. The big thing was making sure we liked it enough to buy the next one. But the industry is moving toward subscription-based games like MMO’s that need the subject to keep playing–and paying–until the sun goes supernova.

Mehr dazu gibt es hier:
Cracked – 5 creepy ways video games are trying to get you addicted