火曜に、imglのうっちーとあらためてラベリング処理ってどうやんのよという話をしていて、あらためてAS3で書き直した。
ただし、ラベルの衝突処理はまだやっていない。
ラベリング処理について→s.h.log: Proce55ing – 2値化画像を4近傍ラベリング処理してパーツ抜き出し
今まで、ラベルそのものを2次元のint配列で管理してたけど、今回はBitmapDataオブジェクトとして保存する様にしてみた。BitmapDataならx,y座標で要素にアクセスできるし、ピクセルはuint型なので都合がいい。
■できたもの
download => fla, as, swf (FlashDevelop3.0.0 Beta5 + FlashCS3)
年末年始作ったカメラから画像処理のサンプルを元に改造した。
webcamから撮影してBitmapDataにして、1ピクセルずつ走査して真っ白(0x00FFFFFF)のピクセルを検出。
さらにラベリング処理をして、「ピクセルのかたまり」毎に番号をつける。
今回はノイズを飛ばしたりしていないので、右の本棚の小さな白にも反応してしまって28個とか検出される
ラベルの衝突時の処理もしていないので、左上が空いた弧の様な形の時に割れてしまう
この辺はまたの機会に。
■動きます(USBカメラが必要)
■コード
ColorPicker.as
package{
importfl.controls.Button;
importfl.controls.NumericStepper;
importflash.events.*;
importflash.media.*;
importflash.geom.Point;
importflash.utils.*;
importflash.display.*;
importflash.filters.*;
publicclassColorPickerextendsSprite{
privatevarcam:Camera;//カメラ
privatevarvideo:Video;//カメラからの画像を表示
privatevarbmp:Bitmap;//表示
privatevarbmd:BitmapData;//中身のデータ
privatevarlabels:BitmapData;//bmdと同サイズのラベル
privatevarcolor:int=0x00ffffff;//選択する色(白)
privatevar_numericStepperLabelNum:NumericStepper;
privatevar_buttonSnapshot:Button;
/*IDEが生成したオブジェクトを関連づけ*/
publicfunctionlink_ide_obj(){
this._numericStepperLabelNum=numericStepperLabelNum;
this._buttonSnapshot=buttonSnapshot;
}
publicfunctionColorPicker(){
stage.scaleMode=StageScaleMode.EXACT_FIT;//伸縮する
//stage.scaleMode=StageScaleMode.NO_SCALE;//伸縮しない
stage.align=StageAlign.TOP_LEFT;//左上から
link_ide_obj();//IDEが生成したオブジェクトを関連づけ
cam=Camera.getCamera();
cam.setMode(800,600,24,true);//24FPS
cam.setQuality(0,100);
video=newVideo(200,150);//bitmap計算用の小さいビデオ
video.attachCamera(cam);
this.addChild(video);//videoを表示
_buttonSnapshot.addEventListener(MouseEvent.CLICK,snapShot);//撮影の関数登録
bmd=newBitmapData(video.width,video.height);
bmp=newBitmap(bmd);//BitmapDataをBitampに登録
this.addChild(bmp);//Bitmapを表示
bmp.x=video.width+10;
//ラベル番号の選択GUI
_numericStepperLabelNum.enabled=false;
_numericStepperLabelNum.addEventListener(Event.CHANGE,function(){
showSelectedLabel(_numericStepperLabelNum.value);
});
}
/*撮影*/
publicfunctionsnapShot(e:Event){
bmd.draw(video);//カメラから制止画をキャプチャ
labeling();
showSelectedLabel(_numericStepperLabelNum.value);
_numericStepperLabelNum.enabled=true;
}
/*4近傍ラベリング処理*/
publicfunctionlabeling(){
labels=newBitmapData(bmd.width,bmd.height,false,0);//transparent=false
varlabel:int=0;
varx:int,y:int;
bmd.lock();//表示の更新を止める。これやらないとえらい事になる
for(y=0;y
for(x=0;x
if(bmd.getPixel(x,y)==color){//選択した色の時(今回は白)
if(x>0&&labels.getPixel(x-1,y)>0){//左チェック
labels.setPixel(x,y,labels.getPixel(x-1,y));//ラベルをコピー
}
elseif(x>0&&y>0&&labels.getPixel(x-1,y-1)>0){//左上
labels.setPixel(x,y,labels.getPixel(x-1,y-1));
}
elseif(y>0&&labels.getPixel(x,y-1)>0){//上
labels.setPixel(x,y,labels.getPixel(x,y-1));
}
elseif(y>0&&x0){//右上
labels.setPixel(x,y,labels.getPixel(x+1,y-1));
}
else{//4方向いずれも隣接していない時
labels.setPixel(x,y,++label);//新しいラベル
}
}
//else{
//labels.setPixel(x,y,0);//ラベル無し
//}
}
}
bmd.unlock();//表示を更新する
_numericStepperLabelNum.maximum=label;
_numericStepperLabelNum.minimum=1;
_numericStepperLabelNum.value=1;
}
/*選択したラベルの箇所を青く塗る。他は赤くする*/
publicfunctionshowSelectedLabel(labelNum:int){
bmd.lock();
varx:int,y:int;
for(y=0;y
for(x=0;x
varcurrentLabel:int=labels.getPixel(x,y);
if(currentLabel==labelNum){
bmd.setPixel(x,y,0x000000FF);//青
}
elseif(currentLabel>0){
bmd.setPixel(x,y,0x00FF0000);//赤
}
}
}
bmd.unlock();
}
}
}