2012-04-02[n年前へ]
■「ウォーリーを探し出す」Mathematicaコードが「してること」
「Mathematicaでウォーリーを探せ!」("How do I find Waldo with Mathematica?")が面白かったので、Mathematicaのコードが何をしているかを眺めてみました。
まずは、Mathematicaコードに簡単な注釈を書き加えてみました。それが下のラクガキです(エッジ検出のテンプレートを間違って4x5で描いてしまいました。正しくは4x4です)。
このMathematicaコードは、次のような処理を行います。ウォーリーを見つけるために用いられているのは、「(赤色に対する)横エッジ検出」です。
- 所定のURLから現画像(waldo)を読み込む(Import)
- 現画像(waldo)をRGBそれぞれの画像として分解
- RGB画像から(R-G-B)という演算を行い、赤色の量を示す赤画像(マトリクス)を作成
- 横(水平)エッジ検出用テンプレート(4x4)を作成。テンプレートは上半分=1、下半分=0
- 赤画像の各領域と横(水平)エッジ検出用テンプレート間で”相関”(実際にはベクトル間距離)を算出
- ”相関”画像を閾値をもとに2値化
- ”相関”画像は実際には”距離”を使っているので、「値が小さい方がマッチしている」ので、値を反転(ColorNegate)
- 膨張処理用に円形のカーネルを作成(DiskMatrix)
- 2値化された(マッチするほど値が大きい)”相関”画像を円形カーネルを使って膨張処理(Dilation)
- 非マッチ部は0.5・マッチ部は1.0にサチらせたマスク画像作成(ImageAdd部)
- 原画像(waldo)とマスク画像を乗算し、完成!
ウォーリーを見つけ出すために使われた③④⑤あたりの「(赤色に対する)横エッジ検出」処理が、シンプルだけれどもなかなか上手く動いているようで、とても面白く感じられます。エッジ検出用のテンプレートのサイズも、4x4という大きさは「必要十分」で上手い…と感心させられます。
ところで、このMathematicaコードでは、「赤白の横線部があると、ウォリーでなくともマッチしてしまう」でしょう。もしも、より確実にウォーリーだけを見つけ出そうとしたら、一体どんなコードを書けば良いのでしょうか?(この続きが『「ウォーリーを探す出す」多重解像度解析コードを書いてみる!?』です)