aki17 @Wiki

細線化処理プログラムサンプル

最終更新:

匿名ユーザー

- view
管理者のみ編集可

私は Hilditch の細線化手法を用いて2値画像を細線化するプログラムを作成したのですが、アルゴリズムは次のような感じです。

// 無限ループ
while(1){
// 画像をラスタスキャン
for(y=0 ; y < ymax ; y++){
for(x=0 ; x < xmax ; x++){
// 注目画素が対象領域なら
if( data[y][x] == 1 ){
背景画素にできる画素か判定する・・・①
}
}
}

// 背景にできる画素を背景画素にする
count = 0;// 背景にできる画素の個数カウント
for(y=0 ; y < ymax ; y++){
for(x=0 ; x < xmax ; x++){
if( data[y][x] == -1 ){
data[y][x] = 0;
count++;
}
}
}
// 背景にできる画素がなかったので細線化処理の終了
if( count == 0 ){
break;
}
}


①の部分は関数化する
注目画素が以下の6つの条件をみたす場合削除してもいい画素
として、値を -1 にしておく

条件1:対象領域の画素である
条件2:境界画素である
条件3:端点を削除しない
条件4:孤立点を保存する
条件5:連結性を保存する
条件6:線幅が2の線分に対して、その片側のみを削除する

あんまり詳しい説明になりませんでしたが、このような感じです。条件の部分についてはソースを載せたらいいんでしょうが、私のプログラムはきたないので今回は載せませんでした。
それでもよければ載せますが(^^;)


[259] ありがとうございます。 返信 削除
▽ 2003/12/18 (木) 13:48:53 ▽ murakami
p2005-ipbffx01daianji.nara.ocn.ne.jp / Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

いっくんさんレスありがとうございます。
数日頭を悩ませていますので。
ソースをのせていただければ参考にしたいと思っています。
お願いします。


[260] ソースです(^^;) 返信 削除
▽ 2003/12/18 (木) 14:08:12 ▽ いっくん
ufproxy.osakac.ac.jp / Mozilla/5.0 (Windows; U; Win98; ja-JP; rv:1.0.1) Gecko/20020823 Netscape/7.0

/****************************************************************************
* ThinLineJudge()
* [ 処理概要 ]
* 対象画素に対して消してもいい画素かどうか判断する
* [ 引数の説明 ]
* char **data // 2値データ(0,1)が格納された2次元配列
* int x    // x座標
* int y    // y座標
* [ 戻り値 ]
* -1 // 削除してもいい画素
* data[y][x] // 削除してはダメな画素(元の値)
****************************************************************************/
char ThinLineJudge(char **data, int x, int y)
{
// px,py配列は注目画素と8近傍画素との位置関係を示す
int px[8] = { 1, 1, 0,-1,-1,-1, 0, 1};
int py[8] = { 0,-1,-1,-1, 0, 1, 1, 1};
int sum,sum2,c1,c2,c3;
char sub[3][3] = {{0}};

// 条件2 - 境界画素である条件
sum = 0;
for(int n=0; n < 8 ; n+=2){
sum += !( data[ y+py[n] ][ x+px[n] ] );
}
if( !( sum >= 1 ) ){
  return( data[y][x] );
}

// 条件3 - 端点を削除しない条件
sum = 0;
for(int n=0; n < 8 ; n++){
  sum += abs( data[ y+py[n] ][ x+px[n] ] );
}
if( !( sum >= 2 ) ){
  return( data[y][x] );
}

// 条件4 - 孤立点を保存する条件
sum = 0;
for(int n=0; n < 8 ; n++){
  if( data[ y+py[n] ][ x+px[n] ] == 1 ){
    sum++;
  }
}
if( !( sum>=1 ) ){
  return( data[y][x] );
}

// 条件5 - 連結性を保存する条件
sum = 0;
for(int n=0; n < 8 ; n+=2){
  c1 = ( abs( data[ y+py[n] ][ x+px[n] ] ) == 1 )? 1 : 0;
  c2 = ( abs( data[ y+py[n+1] ][ x+px[n+1] ] ) == 1 )? 1 : 0;
  c3 = ( abs( data[ y+py[(n+2)%8] ][ x+px[(n+2)%8] ] ) == 1 )? 1 : 0;
  sum += !(c1) - !(c1) * !(c2) * !(c3);
}
if( !( sum == 1 ) ){
  return( data[y][x] );
}

// 条件6 - 線幅が2の線分に対して、その片側のみを削除する条件
sum2 = 0;
for(int i=0 ; i < 8 ; i++){
  if( data[ y+py[i] ][ x+px[i] ] != -1 ){
    sum2++;
    continue;
  }
  // subに対象画素の8近傍を格納
  for(int n=0 ; n < 8 ; n++){
    sub[ 1+py[n] ][ 1+px[n] ] = data[ y+py[n] ][ x+px[n] ];
  }
  sub[ 1+py[i] ][ 1+px[i] ] = 0;

  sum = 0;
  for(int n=0; n < 8 ; n+=2){
    c1 = ( abs( sub[ 1+py[n] ][ 1+px[n] ] ) == 1 )? 1 : 0;
    c2 = ( abs( sub[ 1+py[n+1] ][ 1+px[n+1] ] ) == 1 )? 1 : 0;
    c3 = ( abs( sub[ 1+py[(n+2)%8] ][ 1+px[(n+2)%8] ] ) == 1 )? 1 : 0;
    sum += !(c1) - !(c1) * !(c2) * !(c3);
  }
  if( !(sum == 1) ){
    break;
  }
  sum2++;
}
return( (sum2 == 8)? (char)-1 : data[y][x] );
}

記事メニュー
目安箱バナー