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;icolorpix=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;iif(bins[i]){//黒の時
if(!bins[i-1]){
labels[i]=++label;//新しいラベルを付ける
}
else{
labels[i]=labels[i-1];//ラベルのコピー
}
}
}
//2列目以降を処理
for(inty=1;yfor(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(xif(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;iif(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()関数を効率化しなければ。