« 【Processing】色識別 | トップページ | 【Processing】設定ファイルの読み込みと書き込み »

2014/02/09

【Processing】二値化した画像のラべリング

 本日東京は大雪でございます。

 道産子からするとなんでもないんですけど、周りの人が動けなくなるのです。雪はどうにかなりますが、人はどうにもなりません。
 ということで、本日はプログラミング。     

 webカメラの起動がいちいち遅いので、とりあえず静止画から加工するラべリングプログラムを作ります。

▼元画像
Pc142

◇test044  
  実行環境:Processing 2.1.1   

  
//test044

int imgWidth = 320;     
int imgHeight = 240;      

boolean bins[];    //二値化に使う変数

int tolerance=15;    //色許容値用の変数
float blurLevel = 1;  //ぼかし具合の設定
color targetColor=color(255,0,0);    //ターゲットとする色用の変数

boolean detection=false;    //物体検知のフラグ 

PImage binImage; 

PImage cam; 

PrintWriter writer01;
PrintWriter writer02;

void setup(){ 
size(imgWidth*2, imgHeight*2);  

writer01 = createWriter("test01.CSV");
writer02 = createWriter("test02.CSV");

  binImage = new PImage(imgWidth, imgHeight);
  bins = new boolean[imgWidth*imgHeight];

   cam = loadImage("t37_img02.JPG");

    set(imgWidth,0,cam);  //入力画面を右上に表示
    cam.filter(BLUR,blurLevel);
    cam.filter (POSTERIZE, 4);
    set(0, 0,cam);    //加工済み画面を左上に表示

   detection=false;//物体検知のフラグをfalse(検知なし)にしておく

    for(int i=0 ; i< w_img*h_img ; i++)  //画面全体のピクセル数だけ繰り返し処理
    {

      //物体の色と各ピクセルの色の差を求める(RGB3色分)
      float difRed=abs(red(targetColor)-red(cam.pixels[i]));
      float difGreen=abs(green(targetColor)-green(cam.pixels[i]));
      float difBlue=abs(blue(targetColor)-blue(cam.pixels[i]));


      if (difRed < tolerance && difGreen < tolerance && difBlue < tolerance){
        detection=true;
        bins[i] = true;
        binImage.pixels[i] = color(targetColor);    //ターゲットーをセット

      }else{
        bins[i] = false;    //ターゲット色がなければ偽
        binImage.pixels[i] = color(0);    //blackをセット
      }      
    }

  set(0,imgHeight,binImage);


  ///////////////////////////////////////////
  //4近傍(きんぼう)ラベリング処理
  ///////////////////////////////////////////
  int label = 0;
  int labelNumber[][];    //ラベル番号を格納する変数
  int dst[];  //ルックアップテーブル用
  boolean vic;

  labelNumber = new int[imgWidth][imgHeight];    //Label/配列の準備
  dst = new int[imgWidth*imgHeight];
  dst[0] = 0;

  if(bins[0]) labelNumber[0][0] = label; //画像の左上の処理

  for(int i = 1; i < imgWidth; i++){ // 1番上の列を処理
    if(bins[i]){ //ターゲット色にの時
      if(!bins[i-1]){    //左隣りが黒の時
        labelNumber[i][0] = ++label; // 新しいラベルを付ける
      }
      else{
        labelNumber[i][0] = labelNumber[i-1][0]; // ラベルのコピー
      }
    }
  }
  //2段目以降の処理(作成中)  
  for(int y = 1; y < imgHeight; y++){
    for(int x = 0; x < imgWidth; x++){
      int i = x+y*imgWidth;
      int j =0;
      if(bins[i]){ // 黒の時
        if(!bins[i-1] && !bins[i-imgWidth] && !bins[i-imgWidth+1] && !bins[i-imgWidth-1]){
          labelNumber[x][y] = ++label; // 新しいラベル
          dst[label]=label;    //ルックアップテーブルの生成
        }
        else{
          vic = false;    //4近傍に値があるかどうかを格納しておく          
          if(bins[i-1]){    //左のピクセルがラべリングされている場合
           labelNumber[x][y] = labelNumber[x-1][y]; //同じ番号を割り振る
           vic = true;
          }
          if(bins[i-imgWidth]){    //上のピクセルがラべリングされていた場合
            if(!vic){    //ラべリングの有無の確認
              labelNumber[x][y] = labelNumber[x][y-1];    //上のラベル番号を割り振る
              vic = true;
            }
            else{
              j=min(labelNumber[x][y-1],labelNumber[x][y]);    //より小さい値を抽出
              dst[max(labelNumber[x][y-1],labelNumber[x][y])]=j;  //ルックアップテーブルを小さい方で書き換え
              labelNumber[x][y]=j;    //ラベルに小さい方の番号を割り振る
            }
          }            
          if(bins[i-imgWidth+1]){    //右上のピクセルがラべリングされていた場合
           if(!vic){
            labelNumber[x][y] = labelNumber[x+1][y-1]; // 右上のラベル番号を割り振る
            vic = true;
           }
           else{
             j=min(labelNumber[x+1][y-1],labelNumber[x][y]); //より小さい値を抽出
             dst[max(labelNumber[x+1][y-1],labelNumber[x][y])]=j;    //ルックアップテーブルを小さい方で書き換え
             labelNumber[x][y]=j;   //ラベルに小さい方の番号を割り振る
           }
          }           
          if(bins[i-imgWidth-1]){
            if(!vic){
              labelNumber[x][y] = labelNumber[x-1][y-1]; // 左上
              vic = true;
            }
            else{
              j=min(labelNumber[x-1][y-1],labelNumber[x][y]);
              dst[max(labelNumber[x-1][y-1],labelNumber[x][y])]=j;    //ルックアップテーブルを小さい方で書き換え
              labelNumber[x][y]=j;   //ラベルに小さい方の番号を割り振る
            }
          }
        }
      }
    }
  }

    println("label: "+label);
  for(int i = 1; i<=label; i++){
    println("変換前dst:"+dst[i]);
  }


  ////////////////////////////////////////////
  //ルックアップテーブルの詰め 
  ////////////////////////////////////////////
  int tmp;    //番号用変数
  tmp = 0;
  for(int i = 1; i <=label ; i++){ 
    if(tmp < dst[i]){  //変数よりラベルが大きい場合
      if(tmp+1 == dst[i])tmp = dst[i];   
      else{    //それ以外の場合(2つ以上大きい値)
        tmp++;   
        dst[i] = tmp;  
      }
    }
  }

  //書き換え前のラベルのファイル出力
  for(int y = 0 ; y < imgHeight ; y++){
    for(int x = 0; x< imgWidth  ; x++){
      writer01.print(labelNumber[x][y]+",");
    }
    writer01.println();
    writer01.flush();
  }  

  ////////////////////////
  //ラベルの書き換え
  ////////////////////////
  for(int y = 0 ;  y < imgHeight; y++){
    for(int x = 0;  x < imgWidth ; x++){
      labelNumber[x][y] = dst[labelNumber[x][y]];
    }
  }

  ////////////////////////
  //ラベルの情報格納
  ////////////////////////
  int labelElements[][];  //各ラベルの情報を格納する変数(lnum、xmin、ymin、xmax、ymax、pnum)
  boolean fLabel[];
  int lnum = 0;
  int xmin = 1;
  int ymin = 2;
  int xmax = 3;
  int ymax = 4;
  int pnum = 5;

  //tmpの中にラベルの最大値は入っている
  labelElements = new int[tmp+1][6];
  fLabel = new boolean[tmp+1];

  println("tmp;"+tmp);

    for(int i = 0 ;i<=tmp;i++){
    labelElements[i][lnum]=i;    //ラベル番号を入れる
    }    

  for(int y = 0 ;  y < imgHeight; y++){
    for(int x = 0;  x < imgWidth ; x++){
      if(labelNumber[x][y]>0){
          for(int i=1;i<=tmp;i++){
            if(labelNumber[x][y]==i){    //iのナンバーのラベルがあった時
              if(!fLabel[i]){
                fLabel[i]=true;
                labelElements[i][xmin]=x;
                labelElements[i][ymin]=y;
                labelElements[i][xmax]=x;
                labelElements[i][ymax]=y;
                labelElements[i][pnum]=++labelElements[i][pnum];                  
              }else{
                labelElements[i][xmin]=min(x,labelElements[i][xmin]);
                labelElements[i][ymin]=min(y,labelElements[i][ymin]);
                labelElements[i][xmax]=max(x,labelElements[i][xmax]);
                labelElements[i][ymax]=max(y,labelElements[i][ymax]);
                labelElements[i][pnum]=++labelElements[i][pnum];
              }          
          }
        }
      }
    }
  }

  //ターゲットを枠で囲む
  int margin =3;

  for(int i = 1 ;i<=tmp;i++){
    noFill();
    stroke(255);
    text(i,labelElements[i][xmin]-margin*3,labelElements[i][ymin]+imgHeight-margin);
    rect(labelElements[i][xmin]-margin,
    labelElements[i][ymin]+imgHeight-margin,
    labelElements[i][xmax]-labelElements[i][xmin]+margin*2,
    labelElements[i][ymax]-labelElements[i][ymin]+margin*2);
  }

 //デバッグ用
  println("label: "+label);
  for(int i = 1; i<=label; i++){
    println("変換後dst:"+dst[i]);
  }

 //ファイル出力
  for(int y = 0 ;  y < imgHeight; y++){
    for(int x = 0;  x < imgWidth ; x++){
      writer02.print(labelNumber[x][y]+",");
    }
    writer02.println();
    writer02.flush();
  }         
}

▼実行結果

Pc141

 動きを確認するためにCSVへ出力しているのですが、当初すべてのピクセルが出力されず困りました。
 原因は"flush()"を使っていなかったためなんですけどね。
 320×240の画像を格納するにはバッファが足りなったようなので、1行毎に書き出してます。

 ラベル3はすごく小さな塊なのですが、カラートラッキングをするに当たりどうしていくかはおいおい考えようと思います。

 ラべリングについてはこちらを参考にさせていただきました。   

 

 長いプログラムを載せる気はなかったのだが・・・

メモ:< img>に注意

|

« 【Processing】色識別 | トップページ | 【Processing】設定ファイルの読み込みと書き込み »

コメント

ブランド 激安、安心、安全大特価
【新品】バッグ、財布、靴、帽子、アパレル、ベルト、その他小物 シャネル グッチ エルメス ロレックス ROLEX VUITTON
シャネル グッチ エルメス ROLEX S級 シャネル S グッチ S級 エルメス S級 ROLEX
AAA級 VUITTON AAA級 シャネル AAA級 グッチ AAA級 エルメス AAA級品 N級品ルイ ヴィトンS級品
シャネルS級品 グッチS級品 エルメスS級品 ロレックスS級品 ルイ ヴィトンAAA級品 シャネルAAA級品 グッチAAA級品 エルメスAAA級品
■スタイルが多い、品質がよい、価格が低い!
■ 送料無料(日本全国) ご注文を期待しています!
■信用第一、良い品質、低価格は
■当社の商品は絶対の自信が御座います
激安、安心、安全にお届けします.品数豊富な商
商品数も大幅に増え、品質も大自信です
100%品質保証!満足保障!リピーター率100%!

投稿: プロのカルティエ 時計 | 2018/01/08 10:35

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/29844/59091852

この記事へのトラックバック一覧です: 【Processing】二値化した画像のラべリング:

« 【Processing】色識別 | トップページ | 【Processing】設定ファイルの読み込みと書き込み »