たくのろじぃのメモ部屋

プログラミング関係や数学、物理学などの内容を備忘録として残すブログ。

画像処理 -微分法(差分法)と二値化によるエッジ検出-

前回のおはなし

前の記事では画像を3次元データとして扱う話をしました。今回はそれも絡めて座標から輝度(色濃度のことを指しますが、便宜上輝度とします。)を求め、輝度の変化を数学的に解析します。

数学的解析から工学的解析へ

数学分野には「解析学」というのがあります。この解析学がどんな内容なのかというのが分かりにくいと思いますが、一言でいえば「微分積分の応用」です。応用といっても本記事では工学的に応用するという意味で扱います。工学的というのはもちろん画像処理です。(ちなみに制御系でも解析学を使いますが私は専門外なので説明はしません)

関係ない話ですが、数学的な応用は計算自体はもちろんのこと関数解析や関数で囲まれた体積をそれぞれ微分積分を使って求めることや、ベクトル自体を解析することを指します。関係ないと言いつつもベクトル解析を使うとエッジ検出する方向が分かったりするのですが...。という話もどこかでしたいと思います。

このセクションで言いたいことをまとめると、

  • 数学の知識を使って画像処理を解析する
  • 解析するために解析学(微分積分)を使う

の二点です。まぁ積分よりも微分を使うので微分が分かっていれば面白いと思います。まずはスライドをざっと見てみてください。

 

連続データと離散データ

 連続データ(アナログデータ)は時間分測定した連続的なデータです。細かくデータを扱えるので精度がいいという特徴があります。

離散データは一定時間ごとに測定したとびとびのデータです。とびとびのデータなので精度があまりよくないです。

分解能(どれだけ細かく値を測定できるか)でいうならば

連続データ > 離散データ

となります。画像を扱うならばアナログを使うべきでしょうが、ディジタルに比べて膨大なデータ量なので処理に時間がかかってしまいます。

コンピュータが離散データ(ディジタルデータ)を使う理由

コンピュータでは主に離散データが用いられます。これはハードウェアの性質というか素子自体の影響も関係してきます。コンピュータは半導体部品を多く使用しています。半導体はある条件(熱や光などの外部エネルギー)で導体になり、普段は絶縁体としてふるまいます。アナログで処理すれば細かい値で制御できますが、温度変化によって多少半導体の抵抗が変化しただけで値がくるってしまいます。

例えば0.05[V]のときに画像を表示するとしましょう。問題なければ0.05[V]のバイアスを与えれば画像が表示されます。しかし熱によって半導体の性質が変化して抵抗値が大きくなった場合、果たして画像が表示されるでしょうか?抵抗が大きくなれば電圧降下によって0.04[V]になってしまう可能性があります。そうなれば画像が表示されません。

このような問題を回避するためにディジタルを扱います。0[V]をOFFの状態、これを超える場合はONの状態。というようにすれば電源を入れただけで画像が表示されます。つまり0と1で動くような構造にすれば安定して制御することができるということです。

ただし、0と1の2値しか扱えないので複雑な処理をさせるにはより多くの素子が必要になります。なのでコンピュータ部品にはICチップ素子がたくさん載っています。これ以上深い話はコンピュータアーキテクチャや電子工学などを勉強すると分かると思います。(ここでは説明しません。いや、説明しきれません。)

エッジ検出の考え方

エッジ検出=境界線を検出するという認識でいいです。厳密な定義があるのでしょうが、私はそこまで頭良くないので分かりません。

考え方としては、2つの要素を比較して輝度が異なればそこが境界線でいいと思います。むしろこれ以外に境界線を出す方法ってあるんですかね...?

なので必要な情報は画素データ(全体の解像度)画素(要素)ごとの輝度となり合う画素の輝度の差次の要素(N+1番目)の4つです。

画素データ(全体の解像度)

読み込んだ画素のデータが何ピクセルで構成されているかを読み込みます。もし全体の画素データが分かれば、プログラムにてこれで初期化すれば必要な計算回数Nが分かります。隣り合う画素は最初と最後だけ存在しないので必要な計算回数はN - 2で良いと思います。

画素(要素)ごとの輝度

 画素データ(以降、要素とします)がそれぞれ持つ輝度をデータとして保持しておきます。後は座標と結びつけることで座標からその画素を読み出すような(ハッシュて的な)構造にします。

となり合う画素の輝度の差

これが一番重要です。各要素の輝度が黒ならば0, 白ならば1とします。となり合う画素で差をとって差がでる(変化がある)ならばそこが境界線、差が出ない(変化がない)ならば境界線でないと判定をします。

この判定方法を差分法といいます(連続データでは微分法)。次の要素と比較する差分法を前進差分、前の要素と比較する差分法を後退差分といいます。が、ここでは前進差分をつかいます。正直後退差分はややこしいです。

前進、後退に関しては画像の走査方向によって決まります。走査方向と同じ方向で解析するなら前進差分、逆方向ならば後退差分です。

 読み込む要素は走査方向が決まっているので変更できませんが、解析方向は変えられます。キューを使えばデータが入ってきた順番に取り出すのでそのまま前進差分になり、スタックを使えば入ってきたデータの末尾から取り出すので逆の後退差分になります。方向自体は一方方向ですが、プログラム上では逆から解析していることになります。

微分法と差分法

スライドに説明を参考にしてほしいです。いわゆる微分は変化量を見るために使う数学的手法です。変化量を解析することによって違いを出すことができます。文字通りわずかな区間での変化をみるにはもってこいの手法なのですが、コンピュータでは扱えません。ディジタルはとびとびなので極限(限りなく近づけること)ができません。

ディジタルデータの最小区間はビットにして1です。なので区間を1とすれば、もともとの微分公式の分母部分に1が代入されて分子部分のみが残ります。ここで注目してください。極限が無効となり、分母もなくなる。つまり分子部分の引き算しか残りません。なので差分法というわけですね。

排他的論理和(XOR)

排他的論理和は論理式の一つで、入力A, Bのどちらかが真(true)である、もしくは偽(false)であるならば出力Yが真(true)になります。スライドの表のような関係です。言い換えれば「異なる入力があれば真, 同じ入力なら偽」となるわけですね。

差分をとるときには次の要素と比較すればいいので、いったんコピーして現在の要素を次の要素として扱うことで次の要素とします。次の要素は1ビット進んでいるので右シフトします。あとはXOR演算すれば結果がでるので要素を並べれば解析完了です。

二値化

しきい値Tを用意し、Tより大きいもしくは小さいの2通りにすることで表現を0か1の2値に分けることです。仮にTを10とした場合、入力値が20ならば1, 入力値が5ならば0とみなすことができます。

二値化のメリットはノイズ除去です。輝度がわずかに高いと境界線として判定しにくい場合があるため、はっきり分けたほうが精度が高くなります。

おわりに

ちょっとはりきりすぎて説明が長すぎました。これ、もしかしたら本にできるかもしれないので検討してみたいと思います。

XORをつかった差分法ですが、電子回路ではあるようですがプログラムに関する論文などが見つからなかったので実際にコーディングして確かめてみようと思いました。(もしかしたら新発見の可能性があります<たぶんない...)

エッジ検出はやってみると奥が深いです。まあエンジニアの皆様は使い方を知るだけで十分なのですが、私みたいに沼にはまった人はもう病気といってもいいと思います。ただ、原理が分かるととても面白いので理解力が深まります。

コーディングする際にぜひ意識してみてはいかがでしょうか?

またスライドができ次第アップしたいと思います。