昨日Flash CS3を買ったので、さっそくAS3でやってみた。
自分で1からBitmapDataクラスを使うのは初めてだったけどprocessingやってたお陰ですぐわかった。
一旦カメラの前からどいて、Save Backgroundボタンを押してみてください
1フレーム目。左の大きなビデオ(camDebug)とは別に、画面に表示していない200×150の小さなVideoオブジェクト(camVideo)がある。そこからBitmapDataを作って、背景差分法で処理する。処理した結果を画面右のBitmapオブジェクトに表示して、ついでにぼかしフィルタ(blur)をかけた。
背景差分法は、単純に1度保存しておいたBitmapData(bgBmd)と現在の表示(nowBmd)を1ピクセルずつ比較して、差がある所だけ黒くしている。大体Processingの時と同じ。
varthreshold:int=30;//影化のしきい値
labelThreshold.text=”threshold:”+threshold.toString();varcam:Camera=Camera.getCamera();
cam.setMode(640,480,24,true);//24fps
cam.setQuality(0,100);varcamVideo:Video=newVideo(200,150);//bitmap計算用
camVideo.attachCamera(cam);
camDebug.attachCamera(cam);//デバッグ用の表示varbgBmd:BitmapData=newBitmapData(camVideo.width,camVideo.height);
varnowBmd:BitmapData=newBitmapData(camVideo.width,camVideo.height);
varshadowBmd:BitmapData=newBitmapData(camVideo.width,camVideo.height);//結果表示用
varshadowBmp:Bitmap=newBitmap(shadowBmd);//bmdを操作すると逐次bmpに反映される
shadowBmp.x=400;
shadowBmp.width=400;
shadowBmp.height=300;
this.addChild(shadowBmp);varblur:BlurFilter=newBlurFilter();//ぼかしフィルタ
blur.blurX=5;
blur.blurY=5;
blur.quality=BitmapFilterQuality.MEDIUM;
shadowBmp.filters=[blur];buttonSaveBg.addEventListener(MouseEvent.CLICK,saveBg);
functionsaveBg(e:Event){
trace(“saveBg()”);
bgBmd.draw(camVideo);//背景再取得
}functioncomparePixels(a:int,b:int,threshold:int):Boolean{
vara_red:int=a>>16&0xFF;
varb_red:int=b>>16&0xFF;
vara_green:int=a>>8&0xFF;
varb_green:int=b>>8&0xFF;
vara_blue:int=a&0xFF;
varb_blue:int=b&0xFF;
if((a_red>b_red&&a_red-b_red>threshold)||(a_redthreshold)||
(a_green>b_green&&a_green-b_green>threshold)||(a_greenthreshold)||
(a_blue>b_blue&&a_blue-b_blue>threshold)||(a_bluethreshold)
)returntrue;//色に差がある時
elsereturnfalse;//色に差が無い時
}this.addEventListener(Event.ENTER_FRAME,reload);//毎フレーム実行イベント
functionreload(e:Event){
//背景差分法で変化のあったピクセルを検出、黒く塗りつぶす
nowBmd.draw(camVideo);
shadowBmd.lock();//bitmap操作中は表示に反映させない
for(vary:int=0;y
for(varx:int=0;x
if(comparePixels(bgBmd.getPixel(x,y),nowBmd.getPixel(x,y),threshold)){
shadowBmd.setPixel(x,y,0xFF000000);
}
else{
shadowBmd.setPixel(x,y,0xFFFFFF90);
}
}
}
shadowBmd.unlock();
}buttonInc.addEventListener(MouseEvent.CLICK,
function(){
if(threshold<128)labelThreshold.text="threshold:"+(++threshold).toString();
});
buttonDec.addEventListener(MouseEvent.CLICK,
function(){
if(threshold>0)labelThreshold.text=”threshold:”+(–threshold).toString();
});
あとMath.abs()の動作がおかしくて、comparePixels()の所で使えなかったので長いif文になってしまった。
■参考
・ActionScript3.0で動体検知 01 (Unknown Quality)
・flashrod – AS3で画像処理入門(1)
・flashrod – 2006-11-17
・s.h.log: Proce55ingで背景差分法