Proce55ing – 2値化画像を4近傍ラベリング処理してパーツ抜き出しで未完成だったラベリング処理部分が完成したので、クラス化してみた。

こんな感じで使う。

PImageimg;

Image_SilhouetteExtractise;

img=loadImage(“room.jpg”);//300x200picture

ise=newImage_SilhouetteExtract();

booleanbins[]=ise.img2bin(img,120,true);//2値化 閾値120 白黒反転しない

PImageimg_bin=ise.bin2img(bins,300,200);//2値化画像をbitmapに変換

intlabels[]=ise.bin2label(bins,300,200);//2値化画像のラベリング処理



Image_SilhouetteExtractクラス

classImage_SilhouetteExtract{

floatr_ratio=0.299;//RGB比合計して1

floatg_ratio=0.587;

floatb_ratio=0.114;



Image_SilhouetteExtract(){

println(“create:Image_SilhouetteExtract”);

}



///画像から2値化データを作る

boolean[]img2bin(PImageimg,intthreshold,booleaninvert){

PImageimg_bin=newPImage(img.width,img.height);

bins=newboolean[img.width*img.height];

//2値化

for(inti=0;i colorpix=img.pixels[i];

floatmed=(int)(r_ratio*red(pix)+g_ratio*green(pix)+b_ratio*blue(pix));

//floatmed=(int)(red(pix)+green(pix)+blue(pix));//RGB比を考慮しない

if(med>threshold){

bins[i]=!invert;//白

}

else{

bins[i]=invert;//黒

}

}

returnbins;

}



///2値化画像データを4近傍ラベリング処理する

int[]bin2label(boolean[]bins,intimg_width,intimg_height){

intlabel=1;

labels=newint[img_width*img_height];

if(bins[0])labels[0]=label;//左上



//まず1番上の列だけを処理

for(inti=1;i if(bins[i]){//黒の時

if(!bins[i-1]){

labels[i]=++label;//新しいラベルを付ける

}

else{

labels[i]=labels[i-1];//ラベルのコピー

}

}

}



//2列目以降を処理

for(inty=1;y for(intx=0;x inti=x+y*img_width;

if(bins[i]){//黒の時

//左上、上、右上、左が空白の時、新しいラベルを作成

if((x==0||!bins[i-1])&&//左

!bins[i-img_width]&&//上

(x==img_width-1||!bins[i-img_width+1])&&//右上

(x==0||!bins[i-img_width-1])){//左上

labels[i]=++label;//新しいラベルを作成

}

else{//どこかで隣接している場合

intcollision_count=0;

intlabel_buf[]=newint[4];

//左上、上、右上、左のラベルをチェック&コピー

if(x>0&&bins[i-img_width-1])label_buf[collision_count++]=labels[i]=labels[i-img_width-1];//左上

if(bins[i-img_width])label_buf[collision_count++]=labels[i]=labels[i-img_width];//上

if(x if(x>0&&bins[i-1])label_buf[collision_count++]=labels[i]=labels[i-1];//左

if(collision_count>1){//ラベルが衝突した時

for(intj=0;j
label_replace(labels,i,label_buf[j+1],label_buf[j]);//これ重いのでなんとかする

}

}

}

}

}

}

returnlabels;

}



///label1をlabel2に置き換える

int[]label_replace(int[]labels,intlimit,intlabel1,intlabel2){

if(limit>labels.length)limit=labels.length;

for(inti=0;i if(labels[i]==label1)labels[i]=label2;

}

returnlabels;

}



///2値化画像データを画像に変換

PImagebin2img(boolean[]bins,intimg_width,intimg_height){

PImageimg=newPImage(img_width,img_height);

for(inti=0;i
if(bins[i])img.pixels[i]=color(0);

elseimg.pixels[i]=color(255);

}

returnimg;

}

}

動かしてみると、衝突時のラベル書き換えが多発すると処理に時間がかかってしまう事がわかった。

processingにはhashや特別便利なデータ構造が無いので、まあ何か適当なmap構造を考えてlabel_replace()関数を効率化しなければ。