調べて分かる道具箱

ソーベルフィルタで輪郭を取り出す

写真のファイルを選ぶ

まだえらんでいません

この枠の中に写真を落としても読みます。

選んだ写真はどこにも送りません。読み込みも計算も保存も、ぜんぶこのブラウザの中で終わります。20,971,520バイト(20MiB)までのファイルを受け取ります。

写真を選ぶと、輪郭だけの白黒の絵になります。 その前に、下の見本でぼかしを 0 にするとどうなるかを見てください。 このページでいちばん大事なところです。

⭐ ぼかしを 0 にすると、どうなるか

写真を選ばなくても確かめられるように、ざらつきを入れた見本の絵をこちらで作りました。まんなかに、まるが1つあるだけの絵です。 しきい値は30で固定して、ぼかしの回数だけを変えています。

見本の絵(ざらつきあり)

ぼかし0回のあとの輪郭

輪郭とみなした画素 2,287個(6,144個のうち 37.2%)

ぼかし2回のあとの輪郭

輪郭とみなした画素 570個(6,144個のうち 9.28%)

絵の色だけでなく、数でも同じことが出ています── ぼかさないと輪郭とみなした画素がずっと多く、そのほとんどはまるの縁ではなく、ただのざらつきです。

よくある質問

どうして先にぼかすのですか?

輪郭を見つける計算は「となり合う画素の明るさの差」を見ています。ところが写真には細かいざらつきがあって、それも差なので、そのまま計算すると輪郭として拾ってしまいます。先にぼかすと、となり合う画素の値が混ざって、ばらばらの小さな差が消えます。ものの境目のような大きな差はぼかしても残るので、輪郭だけが生き残ります。このページはぼかしの回数を0にできるので、ざらざらになる様子をその場で確かめられます。

ぼかしは強いほどよいのですか?

いいえ。ぼかすと本物の輪郭も弱くなります。まつげや細い枝のような細かいものは、ざらつきと一緒に消えてしまいます。ぼかしを増やすと線がだんだん太く、丸くなっていくのも同じ理由です。ちょうどよい回数は写真によって違うので、このページではつまみにして、自分で決められるようにしています。

ソーベルフィルタとは何ですか?

3×3のマス目に並んだ9個の数のことです。1968年にアーウィン・ソーベルとゲイリー・フェルドマンがスタンフォード大学の人工知能研究所で発表しました。この9個を写真の全部の画素に順番に重ねて、掛けて足すだけで、明るさの変わり目の強さが出ます。数は横向きと縦向きの2組あり、このページはその9個をそのまま画面に出しています。

しきい値はどう決めればいいですか?

強さがいくつ以上のところを線にするか、という数です。小さくすると線が増え、ざらつきも混ざります。大きくすると、はっきりした境目だけが残ります。強さは0から約360.62までの数で、白と黒がとなり合うまっすぐな境目でちょうど255になります。このページは決め打ちにせず、いま使っている数と、その数で何画素が輪郭になったかを画面に出します。既定は30です。

写真のいちばん外側の画素はどう計算していますか?

3×3の表を当てるには、まわり8方向の画素が要ります。ところが写真のふちには外側がありません。このページは「いちばん外側の画素と同じ明るさが、外にも続いている」ものとして計算しています。もし外側を真っ黒だとみなすと、明るい写真では外側との差が大きくなり、写真のふちにぐるりと1本、そこに無いはずの輪郭が出ます。どちらにするかは決めるしかないので、決めたことを画面に書いています。

選んだ写真はどこかに送られますか?

送りません。ファイルを読むのも、ぼかすのも、輪郭を計算するのも、保存する絵を作るのも、すべてこのブラウザの中だけで終わります。通信をする命令(fetchやXMLHttpRequest)は1つも使っていません。ただし、長い辺が512ピクセルを超える写真は、計算のために縮めてから使います。縮めたかどうかと実際の大きさは画面に出します。

写真を選ぶと、輪郭だけの白黒の絵になります。 やっているのは3×3のマス目に並んだ9個の数を、 全部の画素に順番に当てているだけです。その9個も画面に出します。選んだ写真はどこにも送りません。

⭐ 先にぼかさないと、ざらつきが全部「輪郭」になります

輪郭を見つける計算が見ているのは、となり合う画素の明るさの差だけです。 黒い服と白い壁の境目では、となりどうしの明るさが大きく違います。だから差が大きくなり、 「ここが境目だ」と分かります。

ところが困ったことに、写真には細かいざらつきがあります。 暗いところで撮った写真をよく見ると、まっ平らな壁なのに、 ぽつぽつと明るさがばらついているのが分かります。これも、となりとの「差」です。だから何もしないで計算すると、この計算はざらつきもまじめに輪郭として拾ってしまいます。

だから先にぼかします。ぼかすというのは、自分とまわりの画素の明るさを混ぜることです。ばらばらに散らばった 小さな差は、混ぜると打ち消し合って消えます。 いっぽうものの境目のような大きな差は、混ぜても残ります。この差が、ぼかしの前と後で生き残るかどうかを分けています。

上の道具の「ぼかしの強さ」を0にして、 見本の絵がどうなるか見てください。 まるの輪郭よりも、ざらつきのほうがずっと多く白くなります。 数でも同じで、ぼかし0回では37.2%の画素が輪郭とみなされるのに対し、2回ぼかすと9.28%まで減ります。 減ったぶんは、まるの縁ではなくざらつきだったということです。

ぼかせばぼかすほどよい、ということではありません。ぼかすと本物の輪郭も弱くなります。まつげや細い枝のような細かいものは、ざらつきと一緒に消えます。 だからこのページは、 ぼかしを0回から8回まで自分で決められるようにしてあります。

やっていることは、3×3の表を全部の画素に当てているだけです

むずかしそうな名前がついていますが、中身はかけ算とたし算だけです。 1つの画素を選び、その画素とまわり8つの合わせて9つに、 下の表の9個の数をそれぞれ掛けて、全部足します。 それを写真の全部の画素でくり返すだけです。

まずぼかしの表です。自分を4、上下左右を2、 ななめを1の割合で混ぜて、合計の16で割ります。足して割るだけなので、全体の明るさは変わりません。

ぼかしの表(合計の16で割る)
\左まん中右
上121
まん中242
下121

つぎがソーベルの表です。1968年にアーウィン・ソーベルとゲイリー・フェルドマンが スタンフォード大学の人工知能研究所で発表したものです。横向きと縦向きの2組あります。

よこ向きの表(たての線を見つける)
\左まん中右
上-10+1
まん中-20+2
下-10+1
たて向きの表(よこの線を見つける)
\左まん中右
上-1-2-1
まん中000
下+1+2+1

よこ向きの表をよく見ると、左側がマイナス・右側がプラスで、 まん中の列は0です。つまり「右の明るさから左の明るさを引く」ということをしています。 平らなところでは左と右が同じなので、引き算の答えは0。9個を全部足すと0になるのは、そのためです。

9個の数は、「ぼかし」と「差」のかけ算でできています

ここが面白いところです。よこ向きの表の9個は、たての [1, 2, 1]とよこの [-1, 0, 1]を掛け合わせると、そのまま出てきます。

1 × -1 0 1 = -1 0 +1 2 × -1 0 1 = -2 0 +2 1 × -1 0 1 = -1 0 +1

前半の [1, 2, 1] は、さっきのぼかしとまったく同じ数です。 つまりソーベルの表の中には、すでに小さなぼかしが1つ入っています。差を取るだけの [-1, 0, 1] より、ソーベルがざらつきに強いのはこのためです。 それでも足りないので、このページはさらにその前でぼかしています。

1, 2, 1 という並びはパスカルの三角形の3段目です。 このぼかしを何回も重ねると、重みの形はだんだん釣鐘の形(正規分布)に近づいていきます。 「ぼかしの強さ」のつまみは、この重ねる回数のことです。

よこ向きとたて向き、2枚を計算して合わせています

よこ向きの表だけでは、たての線しか見つかりません。よこに走る線は、左と右の明るさが同じなので差が0になってしまうからです。 だから2枚を別々に計算して、あとで合わせます。

合わせ方は三平方の定理です。よこ向きの値を横の辺、たて向きの値を縦の辺 とする直角三角形をつくって、その斜辺の長さを強さにします。 こうすると、ななめの線もちゃんと出ます── ななめの境目は、よこにもたてにも明るさが変わっているので、 どちらの枚にも値が立つからです。 写真を選ぶと、この2枚を実際に見ることができます。

4で割ると、値がそのまま「明るさの差」になります

表のプラス側を足すと 4(1 + 2 + 1)です。 この4で割ると、出てくる値がちょうど明るさの差そのものになります。たとえば、 左2列が10・右1列が200の3×3を計算すると、こうなります。

よこ向き = 760 760 ÷ 4 = 190 200 − 10 = 190(同じ) たて向き = 0

上下の明るさは同じなので、たて向きは0です。 だから合わせた強さも190になります。 この決め方のおかげで、しきい値の数を「明るさがいくつ変われば線とみなすか」として読むことができます。

強さがいちばん大きくなるのは、よこにもたてにもめいっぱい(どちらも255)変わったときで、約360.6です。 真っ白と真っ黒がとなり合うだけのまっすぐな境目なら、 ちょうど255になります。

いちばん外側の画素は「外へ伸ばす」ことにしました

3×3の表を当てるには、まわり8方向の画素が要ります。 ところが写真のふちには、その外側がありません。無いものは計算できないので、何かを決めるしかありません。

このページは「いちばん外側の画素と同じ明るさが、その外にも続いている」ものとして計算しています。よくあるもう1つの決め方は「外側は真っ黒(0)だとみなす」ですが、これを選ぶと困ったことが起きます。

明るさがどこも同じ200の、のっぺりした灰色の絵を考えてください。 差はどこにもないので、輪郭は1本も出ないはずです。 ところが端の画素だけは、外側との差が出てしまいます。

外へ伸ばす = 0 外側を黒とみなす = 200 (どちらも、明るさ200の一様な絵のふち)

200という強い値が、写真のふちにぐるりと1周出ます。 そこには何も無いのに、白い枠が1本描かれてしまうわけです。 だからこのページは「外へ伸ばす」ほうを選びました。黙って決めずに、決めたことをここに書いておきます。

大きな写真は縮めてから計算しています

つまみを1つ動かすたびに、ぼかしとソーベルを写真の画素ぜんぶにかけ直しています。 ぼかしは最大8回、しかも縦と横で2回ずつなので、 大きいままだとつまみが重くなって、動かしても絵がついてこなくなります。

そこで、長い辺が512ピクセルを超える写真は、 縦横の比を保ったまま512ピクセルまで縮めてから計算しています。縮めたかどうかと、実際に計算している大きさは画面に出します。保存される絵もその大きさです。

縮めること自体が、すでに少しぼかしています。縮めるときはとなり合う画素が混ざるので、ぼかしのつまみを0にしても、 元の写真そのままの粗さにはなりません。細かい模様は、縮めた時点で輪郭ごと消えていることがあります。

出どころ: ソーベルの表はIrwin Sobel と Gary Feldman が1968年にスタンフォード人工知能研究所で発表した 「A 3×3 Isotropic Gradient Operator for Image Processing」(新しいタブで開きます)から。明るさの重み(0.2126・0.7152・0.0722)はITU-R BT.709-6 の item 3.2(新しいタブで開きます)です。同じことをする道具(mogamoga1024.github.io/kirie)を実際に開いて、 何が書かれていて何が書かれていないかを確かめたうえで、このページの中身を決めました。 画面に出ている数は、すべてcore/edge.tsの関数を その場で呼んで作っています(本文の数と、動いている計算がずれないようにするため)。