落穂拾い

Gleanings in my life

ImageMagickによる輪郭抽出

2007年11月22日 18時23分07秒 | Linux
画像 foo.png の輪郭を抽出するには、
convert -edge 0 foo.png bar.png

などとする。-edge の引数以外にカスタマイズ要素はないようだ。しかし、この引数がどんな意味を持つのか、そしてアルゴリズムがどんなものなのかはいまいち記述がない。

そこで、ソースを見てみる。
magick/effect.c にEdgeImageという関数があり、

EdgeImage() finds edges in an image. Radius defines the radius of the
convolution filter. Use a radius of 0 and EdgeImage() selects a suitable
radius for you.

と書いてある。これが輪郭抽出関数で間違いがない。
で、肝心の中身であるが、実際の計算は
edge_image=ConvolveImage(image,width,kernel,exception);

の一行で終わりである。説明にもあるように、convolutionしているだけ。かなり汎用的な書き方でエレガントである。では、convolutionのkernelはというと、
  for (i=0; i < (long) (width*width); i++)
kernel[i]=(-1.0); kernel[i/2]=(double) (width*width-1.0);

こんな形で作られている。ここでwidthというのは -edge オプションで指定する引数から決められる輪郭の厚みを意味しているようだ。kernelという一次元配列は、数学的には恐らくwidth*widthの二次元行列を表しており、そのほとんどの要素は -1 で、唯一、行列の真中の要素だけが width*width-1.0という値を取る。全要素を足し合わせると丁度0になる。行列の形状から、常識に考えてwidthは奇数でなければならないだろう。

で、このkernelが何かと思って調べてみると、どうやらラプラシアン(二次微分)を利用した輪郭抽出アルゴリズムらしい。というわけで、ImageMagickの -edge 引数で実行できる輪郭抽出アルゴリズムは、ラプラシアンを利用したものであるようだ。


コメントを投稿