目次
前
次
エッジ抽出
エッジ抽出は、画像中にある物体を認識するために
利用することが多く、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
-------------------------------------------------
目次
前
次