目次

エッジ抽出

 エッジ抽出は、画像中にある物体を認識するために
 利用することが多く、Machine Visionを考える上で
 必須の機能です。

 Machine Visionは、2値化情報を処理する方が単純で高速に
 なります。ここでは、元画像を2値化後、エッジ抽出します。

 次のように左から、元画像、2値化画像、エッジ抽出画像と
 処理してみます。



 元画像を2値化して表示し、2値化情報をラプラシアンフィルタ
 でフィルタリングしてエッジ抽出後、表示するシーケンスを説明
 します。


2値化

 元画像は、RGBの3成分をもっています。  RGBの3成分を取得し、移動平均の値を求めて  2値化します。求めた値を、後で使いたいので、  配列に保存しておきます。   gdat0(i+offset) = (r + g + b) / 3  変数offsetを利用して、2次元データを1次元データ  にまとめます。  プロシージャは、次のように記述します。 -------------------------------------------------  *proc_save_gdat   for j,0,ylast,1    ; calculate offset    offset = j * xlast    for i,0,xlast,1     ; get pixel information     pget i,j     ; get color components     r = ginfo(16)     g = ginfo(17)     b = ginfo(18)     ; store     gdat0(i+offset) = (r + g + b) / 3    next   next   return -------------------------------------------------  表示は、右にずらしてピクセルを出力することで実現します。 ------------------------------------------------- *proc_show  for j,0,ylast,1   ; calculate offset   offset = xlast * j   for i,0,xlast,1    ; get data    s = gdat0(i+offset)    if (shift = 2) {     s = gdat1(i+offset)    }    ; conversion    if (shift = 1) {     if (s > 128) {      s = 255     } else {      s = 0     }    }    ; set color    color s,s,s    ; set point    pset i + shift * xlast ,j   next  next  return -------------------------------------------------  表示データは、2つの配列に保存されているものとして  ピクセル値を決めています。また、2値化したときには  表示したとき、確実に判断できるように黒白を強調して  あります。

ラプラシアンフィルタリング

 ラプラシアンフィルタリングは、よくエッジ抽出に利用されます。  方式は2つあります。  注目点の4点近傍の値から算出する場合(下図の左)と8点近傍の  値から算出する場合(下図の左)です。  注目点を、逐次変更してフィルタリング値を求め、表示すると  エッジ抽出画像ができます。  上の画像を見てわかるように、0ラインと最終ラインはフィルタリング  による変換を受けません。また、0ピクセルと最終ピクセルも変換なし  になります。フィルタリングには、3ライン分のピクセルデータが必要  です。  ラプラシアンフィルタリングを実現して、エッジ抽出するためには  次の2処理を組合わせたシーケンスを利用します。  注目点の逐次変換は、一度配列に画像データを保存しておき  ピクセルデータをfor文で取り出しながら、フィルタを動かす仕様  とします。  ピクセルデータが配列変数srcに格納されているとして  処理のアウトラインを記述します。 ------------------------------------------------- *calc_lap  last = xlast-1  ; first and last pixel  fpga(0) = src(0)  fpga(last) = src(last)  ; filtering  for ii,1,xlast-1,1   ; ?????  next  return -------------------------------------------------  フィルタリングには、3ライン分のピクセルデータが必要です。  ここでは、次のように計算します。  注目点を含めた9点の値を加算し、注目点の値を減算します。  専用ICを開発しやすいように、9点の加算を3つの独立した  3点加算器で実現します。  9倍は、その値と8倍を求める回路の出力を加算します。  (8倍は、単純に左に3ビットシフトして実現できます。) --------------------------------------------------------------------- *calc_lap  last = xlast-1  ; first and last pixel  fpga(0) = src(0)  fpga(last) = src(last)  ; filtering  for ii,1,xlast-1,1   ; get target pixel   a = (src(ii+xlast) << 3) + src(ii+xlast)   ; get other point values   b = src(ii-1) + src(ii) + src(ii+1)   b += (src(ii+last) + src(ii+last+1) + src(ii+last+2))   b += (src(ii+2*last+1) + src(ii+2*last+2) + src(ii+2*last+3))   ; calculate   result = b - a   ; store   if result > 255 : result = 255   if result < 0 : result = 0   fgpa(ii) = result  next  return ---------------------------------------------------------------------  エッジが、より強調されるように、計算結果を  0〜255の範囲になるよう操作します。  プロシージャcalc_lapを使い回すには、配列srcにピクセルデータを  入れなければなりません。毎回、3ライン分のピクセルデータを転送  するのは、無駄なので、一度フィルタリングが終われば、3ラインの  ピクセルデータをシフトで2ラインにします。シフトで空いた1ライン  分のピクセルデータ領域に、新たなピクセルデータを転送します。  そのための専用プロシージャを用意します。 ---------------------------------------- *put_gdat  ; calculate index  index = xlast + xlast  ; calculate offset  offset = xlast * gpoint  ; transfer  for ii,0,xlast,1   ; shift   src(ii) = src(ii+xlast)   ; shift   src(ii+xlast) = src(ii+index)   ; transfer last area   src(ii+index) = gdat0(ii+offset)  next  return ----------------------------------------  最初の3ライン分のピクセルデータは、次のシーケンスで  予め設定します。   gpoint = 0 : gosub *put_gdat   gpoint = 1 : gosub *put_gdat   gpoint = 2 : gosub *put_gdat

ソースコード

 ソースコードは、これまで説明したプロシージャに  画像データの入力と表示を加えると出来上がりです。 -------------------------------------------------  #include "hspext.as"  screen 0,160*3,120  dim gdat0,19200  dim gdat1,19200  dim src,480  dim fgpa,160  ssize = 160  ylast = 120  xlast = 160  picload "cross.bmp",1  gosub *proc_save_gdat  shift = 1 : gosub *proc_show  gosub *proc_edge  shift = 2 : gosub *proc_show  stop *proc_save_gdat  for j,0,ylast,1   ; calculate offset   offset = j * xlast   for i,0,xlast,1    ; get pixel informations    pget i,j    ; get color components    r = ginfo(16)    g = ginfo(17)    b = ginfo(18)    ; store    gdat0(i+offset) = (r + g + b) / 3   next  next  return *proc_show  for j,0,ylast,1   ; calculate offset   offset = xlast * j   for i,0,xlast,1    ; get data    s = gdat0(i+offset)    if (shift = 2) {     s = gdat1(i+offset)    }    ; conversion    if (shift = 1) {     if (s > 128) {      s = 255     } else {      s = 0     }    }    ; set color    color s,s,s    ; set point    pset i + shift * xlast ,j   next  next  return ;=========== ; filtering ;=========== *proc_edge  ; transfer first and line  last = xlast * (ylast-1)  for i,0,xlast,1   gdat1(i) = gdat0(i)   gdat1(i+last) = gdat0(i+last)  next  ; transfer data  gpoint = 0 : gosub *put_gdat  gpoint = 1 : gosub *put_gdat  gpoint = 2 : gosub *put_gdat  ; filtering  for i,1,ylast-2,1   ; laplacian filtering   gosub *calc_lap   ; transfer result   gpoint = i : gosub *get_gdat   ; transfer data   gpoint = i+2 : gosub *put_gdat  next  return ;===================================================== ; transfer line data from gdat0 to internal registers ; input parameters ; gpoint : block entry offset ;===================================================== *put_gdat  ; calculate index  index = xlast + xlast  ; calculate offset  offset = xlast * gpoint  ; transfer  for ii,0,xlast,1   ; shift   src(ii) = src(ii+xlast)   ; shift   src(ii+xlast) = src(ii+index)   ; transfer last area   src(ii+index) = gdat0(ii+offset)  next  return ;====================== ; Laplacian filtering ;====================== *calc_lap  last = xlast-1  ; first and last pixel  fpga(0) = src(0)  fpga(last) = src(last)  ; filtering  for ii,1,xlast-1,1   ; get target pixel   a = (src(ii+xlast) << 3) + src(ii+xlast)   ; get other point values   b = src(ii-1) + src(ii) + src(ii+1)   b += (src(ii+last) + src(ii+last+1) + src(ii+last+2))   b += (src(ii+2*last+1) + src(ii+2*last+2) + src(ii+2*last+3))   ; calculate   result = b - a   ; store   if result > 255 : result = 255   if result < 0 : result = 0   fgpa(ii) = result  next  return ;========================================================= ; transfer computed data from internal registers to gdat1 ; input parameters ; gpoint : block entry offset ;========================================================= *get_gdat  ; calculate destination offset  offset = xlast * gpoint  ; transfer  for ii,0,xlast,1   gdat1(ii+offset) = fgpa(ii)  next  return -------------------------------------------------

目次

inserted by FC2 system