ソーベルフィルタで輪郭を取り出す
写真のファイルを選ぶ
この枠の中に写真を落としても読みます。
選んだ写真はどこにも送りません。読み込みも計算も保存も、ぜんぶこのブラウザの中で終わります。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で割ります。足して割るだけなので、全体の明るさは変わりません。
| \ | 左 | まん中 | 右 |
|---|---|---|---|
| 上 | 1 | 2 | 1 |
| まん中 | 2 | 4 | 2 |
| 下 | 1 | 2 | 1 |
つぎがソーベルの表です。1968年にアーウィン・ソーベルとゲイリー・フェルドマンが スタンフォード大学の人工知能研究所で発表したものです。横向きと縦向きの2組あります。
| \ | 左 | まん中 | 右 |
|---|---|---|---|
| 上 | -1 | 0 | +1 |
| まん中 | -2 | 0 | +2 |
| 下 | -1 | 0 | +1 |
| \ | 左 | まん中 | 右 |
|---|---|---|---|
| 上 | -1 | -2 | -1 |
| まん中 | 0 | 0 | 0 |
| 下 | +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の関数を その場で呼んで作っています(本文の数と、動いている計算がずれないようにするため)。