人間の視覚性を視覚化する顕著性マップを実装してみたんご

4 min読了の目安(約3600字TECH技術記事

個人的に未来を感じている顕著性マップ(saliency map)を久しぶりに実装してみた

アルゴリズムはうろ覚えだが()

今回紹介するのは、ディープラーニングではなく、教師なしでのsaliency mapの作り方。
今回もみんなの好きなイモリで紹介していく

これの元論文知ってる人はぜひ教えてくださいmm

実装はそのうちまとめてgitとpythonライブラリで公開するつもり

アルゴリズム

  1. 画像をグレースケールにして、1/2, 1/4, 1/8,....とリサイズする(これはGaussian pyramidと呼ばれる)
  2. それぞれの画像を1/1に拡大する (この時は線形補完で行う)
  3. 各画像のピクセル差分をとる
  4. 3のピクセル差分を全て足し合わせる(これが顕著性マップ)

pythonで実装してみる

improt numpy as np
import cv2
import matplotlib.pyplot as plt

今回はいつものイモリ画像でやってみる

img1 = cv2.imread("../images/train/sample_00.jpg")

画像をグレースケールにして、256にリサイズする

img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

size = 256
img1 = cv2.resize(img1, (size, size))

小さくして、大きくリサイズする関数を定義

def down_up(img, down_size, up_size):
    img = cv2.resize(img, (down_size, down_size), interpolation = cv2.INTER_LINEAR)
    img = cv2.resize(img, (up_size, up_size), interpolation = cv2.INTER_LINEAR)
    return img.astype(np.float32)

画像を1/2にしてから、元サイズにする

img1_2 = down_up(img1, size//2, size)
gray scale 1/2にして元サイズにした画像

若干解像度が下がっている(リサイズの方法が線形補完なのでこれでいい)

この2つの画像の差分をとる

diff1_2 = np.abs(img1_2 - img1)

なんとなくエッジ部分がとれている

次は1/4で見てみる

img1_4 = down_up(img1, size//4, size)
gray scale 1/2にして元サイズにした画像 1/4にして元サイズにした画像

1/4だとさらに解像度が下がっている

これで元画像と1/4の画像の差分をとると

diff1_4 = np.abs(img1_4 - img1)

ってことで、画像のピラミッドを作成する

img_pyramids = []

for i in range(6):
    scale = 2 ** i 
    img1_dog = down_up(img1, size // scale, size)
    img_pyramids.append(img1_dog)

これの組み合わせの差分を足し合わせる

img = np.zeros((size, size), dtype=np.float32)
diff_count = 0

pyramid_num = len(img_pyramids)

for i in range(pyramid_num):
    for j in range(i + 1, pyramid_num):
            
        diff = np.abs(img_pyramids[i] - img_pyramids[j])
        img += diff
        diff_count += 1
        
img /= diff_count

この画像をヒートマップにしてみると、こんな感じ

plt.imshow(cv2.applyColorMap(img.astype(np.uint8), cv2.COLORMAP_HOT)[..., ::-1])

これだと視認性がちょっと悪いので、0 <= pixel <= 255に正規化する

img -= img.min()
img /= img.max()
img *= 255
plt.imshow(cv2.applyColorMap(img.astype(np.uint8), cv2.COLORMAP_HOT)[..., ::-1])

顕著性マップの結果

元画像 saliency map

どうやら輝度の変化が大きいところが顕著になっている。境界や砂利の光っているところなど。

たしかに目がいきやすいところではある

今はDeep Learningの方法が主流だが、教師なしで使えるこれはわりと強みだと思う。

他にもいろいろあるので、実装をまじえながら続けたいんご

(おまけ)他の画像