mercoledì 19 agosto 2009

Motion Detection in Flash CS3

Cerando un po' in rete si trovano articoli sparsi sul rilevamento del movimento attraverso una webcam istallata sul nostro pc. In Flash con AS3 ci sono delle comode classi che semplificano un po' il lavoro.
Ho fatto qualche esperimento provando a individuare e seguire un oggetto in movimento davanti alla webcam.
Vediamo la classe:

package {
import flash.display.*;
import flash.utils.*;
import flash.media.*;
import flash.geom.*;
import flash.filters.BlurFilter;
import flash.events.Event;
import flash.events.StatusEvent;

public class cam extends MovieClip {
private var bitData:BitmapData = new BitmapData(160,120,false);
private var bitMap:Bitmap;
private var sbitData:BitmapData = new BitmapData(160,120,false);
private var sbitMap:Bitmap;
private var video:Video = new Video(160,120);
var mRect:Rectangle = new Rectangle(0,0,0,0);
var mShape:Shape = new Shape();
var mMirror:Matrix = new Matrix();

finora niente di speciale se non le dichiarazioni delle variabili; in particolare gli oggetti BitmapData che ci aiuteranno a manipolare l'immagine della nostra web cam
public function cam() {
mMirror.translate(-160,0);
mMirror.scale(1,-1)
mMirror.rotate(180 * Math.PI / 180);

var cam:Camera = Camera.getCamera();
cam.addEventListener(StatusEvent.STATUS, oncomplete);
video.attachCamera(cam);
mShape.x = 180;

addChild(video);
}
nel costruttore imposto una matrice che mi servira a riflettere a specchio le immagini della webcam e tutte le funzioni delle classi Cam e Video per catturare il flusso video.
private function oncomplete(e:StatusEvent) {
trace(e.code);
if (e.code == "Camera.Unmuted") {
addEventListener(Event.ENTER_FRAME, onFrame);

bitData.draw(video, mMirror);
bitMap = new Bitmap(bitData);
bitMap.x = 180;

addChild(bitMap);
}
}
l'evento oncomplete mi indica che la webcam è stata catturata e trasmette regolarmente in tal caso scatta l'evento onFrame.
private function onFrame(e:Event) {
bitData.draw(video,mMirror);
bitData.draw(sbitData,mMirror,null,"difference");
sbitData.draw(video);
bitData.applyFilter(bitData,new Rectangle(0,0,160,120),new Point(0,0),new BlurFilter(8,8));
bitData.threshold(bitData,new Rectangle(0,0,sbitData.width,sbitData.height), new Point(0,0), ">", 0xFF111111, 0xFFFF0000);
//
mRect = bitData.getColorBoundsRect(0x00FF0000, 0xFFFF0000, true);
mShape.graphics.clear();
if (mRect.right > 0) {
mShape.graphics.lineStyle(1,0x0000FF,1);
mShape.graphics.drawRect(mRect.left,mRect.top,mRect.right-mRect.left,mRect.bottom-mRect.top);
addChild(mShape);
}
}
}// class
}//Package
Ok. questa è la parte del codice più importante:
disegno su bitData il flusso video, sovrappongo sempre su bitData il flusso video disegnato in sbitData ma con un opzione di blending: difference. Questa serve a colorare di nero tutti pixel simili delle due immagini, in sostanza se non cambia nulla davanti alla camera i pixel saranno simili e quindi vederemo uno schermo nero. Da notare che utilizzo anche la matrice mMirror per capovolgere a specchio l'immagine così se muoviamo la mano verso destra non la vedremo muoversi nel video verso sinistra!
Applico poi un filtro di sfocatua, per eliminare i disturbi.
La funzione threshold colora di rosso tutti i pixel che superano una certa soglia di colore, cioè quelli che non sono neri. serve a circoscrivere gli oggetti in movimento.
Infine ricavo le misure di un rettangolo (bitData.getColorBoundsRect) che circoscrive le aree in rosso dell'immagine e lo disegno in una shape sul video.
Vedremo come questo rettangolo blu segua e circoscriva qualsiasi cosa si muova davanti alla nostra webcam.
Ciao

Nessun commento:

Posta un commento