低次視覚野の計算モデル

今まで、(低次)視覚神経系のモデルについて、見聞きした雑多な話題として、

(1)カブトガニの眼で側方抑制がどうたら...(1950年代後半〜1960年代初頭、Hartline & Ratliff)
(2)ネコの一次視覚野(V1野)に、特定方向の線分に反応する細胞があるとか何とか(1959,Hubel & Wiesel)→1981年のノーベル医学・生理学賞
(3)V1野の方位選択性の機能は、Gaborフィルターでモデル化できる(Jones & Palmer 1987)
(4)infomax原理がどうとか

くらいがあったけど、それぞれの話の繋がりがどうなってるのか、よく分かってなくて、理解しようと思った。


(1)は、生理学とか生物学の結果で、画像処理的には、エッジ強調/画像鮮鋭化に対応する処理が行われているとされる。論文としては
Inhibitory interaction of receptor units in the eye of Limulus.
https://www.ncbi.nlm.nih.gov/pubmed/13398569

など。元々の話は、カブトガニを使ったものだったけど、マッハバンドとかハーマン格子のような古くから知られる錯視を説明でき、人間の網膜にも存在するよう。いずれにせよ、基本的には、網膜で処理されるレベルの話のよう。

マッハバンドは、Wikipediaには「微妙に濃淡の異なるグレーの領域が接触している場合に、暗い方の領域の境界付近はより暗く、明るい方の領域の境界付近はより明るく強調されて見える、錯視の一種である」と説明されている。実際の処理は、一種のhigh-passフィルタでモデル化できると考えられ、このようなhigh-passフィルタは、比較的単純な神経回路で作ることができるということが、基本的には(1)で解明されたらしい。



網膜にある視細胞で受けた情報は、次に、LGN(外側膝状体)という領域に送られる。視細胞には、rod cellとcone cellの二種類があるけど、基本的には、視細胞→双極細胞→網膜神経節細胞(RGC)→(視神経)→LGN→一次視覚野(V1)と伝わっていくらしい。rod cellは、明暗にのみ反応し、cone cellは色情報を担当するとされ、前者は、片目で一億個くらいあるのに対して、後者は500〜700万個くらいらしい。

cone cellも一様に分布してるわけじゃなく、外縁部は低密度らしいけど、平均的には10000x10000くらいの解像度があるということで、8Kモニターより上。cone cellは、大多数の人類が、三色認識するので、一色あたり200万くらいと考えると、色情報についてはフルHD程度の解像度(?)。

視細胞〜網膜神経節細胞には、水平細胞とアマクリン細胞というのもいて、沢山種類があるけど、機能の全容が解明されているわけではないらしい

視覚系の神経細胞は、それぞれが、視野の中の一部の領域からの入力にのみ反応するようになっていて、この領域を受容野と呼んでいる。画像処理で、Gaussian blurとかのフィルター処理をかける際には、サイズが3x3とか5x5の領域の情報から、一ピクセルの色情報を計算するのと同じような話。一般に、受容野は、低次視覚野の神経細胞では狭く、高次視覚野では、広くなっていくらしい。

RGC細胞数が約100万個とか書かれてたりするので、rod cellの数との比は1:100くらい。単純に考えると、10x10くらいのrod cellからの入力が一つにまとめられている計算になる(?)。この比率は、網膜位置によって、かなり異なるらしいので、目安程度にしかならない。

低次視覚野は、局所的な幾何学的特徴に反応するのに対して、高次視覚野では、顔や、特定の物体に反応する細胞とかがあるとされている。


で、神経細胞は、受容野に入ってきた入力をまとめて、ある大きさの応答を起こす。RGCやLGNの応答は、DoGフィルタとしてモデル化でき、一次視覚野の単純細胞の応答は、Gaborフィルタでモデル化できるとされている。というのが、(2)や(3)の話。DoGフィルタによるモデル化は、誰が言い出したのか分からないけど、よく書いてある

と言われても、フ〜ンという感想しかなかったので、実際に、DoGフィルタとかGaborフィルタを通した結果が、どんな感じになるか見てみた。

DoGフィルタやGaborフィルタには、いくつかのパラメータが存在し、動物や人間の神経系のモデルとして、どのようなパラメータを選ぶべきか、通常、何の説明もない。
Analysis of multidimensional difference-of-Gaussians filters in terms of directly observable parameters
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3789628/

Modeling lateral geniculate nucleus response with contrast gain control. Part 1: Formulation
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3918962/

などでは、DoGカーネルを3つのパラメータで規定される
f(x,y) = \dfrac{1}{2 \pi \sigma_C^2} \exp(-\dfrac{x^2+y^2}{2\sigma_C^2}) - \dfrac{\beta}{2 \pi \sigma_S^2} \exp(-\dfrac{x^2+y^2}{2\sigma_S^2})
の形に取っている。βをbalance parameterと呼び、無次元量である。他の2つのパラメータは、長さの次元を持つので、面倒だけど、例えば、2つの比は無次元量である。積分すると、1-βになる。

CV業界では、β=1として、残り2つのパラメータ比は、1.6にすることが多いっぽい。上の論文は、観測可能な量から各パラメータを見積もろうというノリらしいけど、実際の値は与えられていない。後者の論文の§2に於ける記述によれば、LGNにおけるβの値は、生物種や細胞種ごとに、0.95から0.52まで、色んな見積もりがあるらしい。

DoGフィルタは、フィルタを通しただけでは、あまり意味はなくて、ゼロ交差の検出をしなければならない。このへんは、工夫の余地があるのかもしれないけど、何も考えない実装になっている。

あと、適当に検索すると、gray画像のピクセル値をuint8のまま、2つのGaussianフィルタに通して(cv2.filter2Dを使うと、適当に近い整数値を選んで、出力もuint8のままにしてくれる)、そのまま引くという実装をしている人がいた。大体の場合は、引き算した値は、0に近い値になるけど、uint8同士の引き算なので、オーバーフローを起こして、たまに大きい値になる。これが、ゼロ交差判定の代替として、うまく働くのか、こっちの方が、真面目に計算したものより、結果が綺麗に見えるっぽい。あまり意味はないけど、参考までに実装した

また、(1)の話からすると、網膜では、エッジ強調が行われるらしいので、簡単なエッジ強調フィルタも通してみることにした。で、以下がコード

import cv2
import numpy as np
import math


def sharpen(img):
    kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]], np.float32)
    return cv2.filter2D(img, -1, kernel)


def DoG(gray , W, sigma1, sigma2 ,beta = 1.0):
    assert(W > 0)
    assert(gray.dtype==np.uint8)
    k1 = cv2.getGaussianKernel(W , sigma1)
    k2 = cv2.getGaussianKernel(W , sigma2)
    dog_kernel = np.dot(k1 , k1.T) - beta*np.dot(k2 , k2.T)
    res = cv2.filter2D(np.float64(img), -1, dog_kernel)
    minNN = cv2.morphologyEx(res, cv2.MORPH_ERODE, np.ones((3,3)))
    maxNN = cv2.morphologyEx(res, cv2.MORPH_DILATE, np.ones((3,3)))
    zeroCross = np.logical_or(np.logical_and(minNN >= 0 , maxNN <= 0), np.logical_and(minNN<=0 , maxNN>=0))
    return np.uint8(zeroCross)*255


def DoG_int(gray , W, sigma1, sigma2 ,beta = 1.0):
    assert(W > 0)
    assert(gray.dtype==np.uint8)
    k1 = cv2.getGaussianKernel(W , sigma1)
    k2 = cv2.getGaussianKernel(W , sigma2)
    G1,G2 = np.dot(k1,k1.T) , np.dot(k2,k2.T)
    res = cv2.filter2D(img, -1, G1) - cv2.filter2D(img , -1, G2)
    return res


def gabor(gray,lam=10.0):
   assert(gray.dtype==np.uint8)
   sigma = lam*0.4
   gamma = 1.0
   imgs = [cv2.filter2D(gray , -1 ,cv2.getGaborKernel((int(lam), int(lam)), sigma, np.radians(5*n), lam, gamma, 0)) for n in range(36)]
   ret = 0*gray
   for img in imgs:
      ret += img
   return np.clip(ret , 0, 255)


if __name__=="__main__":
   img = cv2.cvtColor(cv2.imread("Lenna.png"),cv2.COLOR_BGR2GRAY)
   contours = []
   contours.append( DoG(img, 5, 2.2 , 2.2*1.6) )
   contours.append( DoG(sharpen(img), 5, 2.2 , 2.2*1.6) )
   contours.append( DoG_int(img, 5, 2.2 , 2.2*1.6) )
   contours.append( DoG_int(sharpen(img), 5, 2.2 , 2.2*1.6) )
   contours.append( DoG(img, 7, 7*math.sqrt(0.2459)/math.pi , 7*math.sqrt(0.9837)/math.pi , 0.891) )
   contours.append( DoG(sharpen(img), 7, 7*math.sqrt(0.2459)/math.pi , 7*math.sqrt(0.9837)/math.pi , 0.891) )
   contours.append( DoG_int(img, 7, 7*math.sqrt(0.2459)/math.pi , 7*math.sqrt(0.9837)/math.pi , 0.891) )
   contours.append( DoG_int(sharpen(img), 7, 7*math.sqrt(0.2459)/math.pi , 7*math.sqrt(0.9837)/math.pi , 0.891) )
   contours.append( cv2.Canny(img,100,200) )
   contours.append( cv2.Canny(sharpen(img),100,200) )
   contours.append( gabor(img) )
   contours.append( gabor(sharpen(img)) )
   contour = np.concatenate([np.concatenate(contours[0:4], axis=1),np.concatenate(contours[4:8], axis=1), np.concatenate(contours[8:12], axis=1)] , axis=0)
   cv2.imwrite("result.png",contour)


結果発表。合計12パターンの計算をやってみた
f:id:m-a-o:20190922185224p:plain

1行目:左2つが、真面目に計算したDoGで、エッジ強調なしとあり。右2つは、オーバーフローするDoGで、エッジ強調なし、あり
2行目:パラメータを変えて、一行目と同じ組み合わせの計算をしたもの
3行目:1列目と2列目は、Cannyエッジフィルタ(エッジ強調なし、あり)。3列目と4列目は、Gaborフィルタを5度ずつ回転して足したもの(エッジ強調なし、あり)


まぁ、エッジ強調なしで、Canny検出器が一番いいように思える。Cannyは、エッジ強調すると、(当然だが)全然ダメになる。Gaborも割といい結果になってる気がする。こっちは、エッジ強調なしでもありでも、それなりの成績を出す。

肝心のDoGフィルタは、まぁ、どう解釈したものか、よく分からない。とりあえず、エッジ強調の影響が全然見られない。2行目の1,2列目とか見ると、全然取れてないってこともないので、パラメータ次第では、よい結果が出ることもあるのかもなーという感じではある。

以上は、生理学側からのアプローチで、既に形成された神経回路の機能を解析した話。



一方で、そもそも、こういう都合の良い神経回路が、どうやって自然に形成されるのかという問題もある。

脳内情報表現への情報理論的アプローチ
http://www.jnns.org/previous/niss/1999/text/sakakaba.pdf

によれば、「1970年代には,視覚野に見られる特徴抽出細胞が生後の感覚体験を通じて形成されることを示唆する実験報告が相次いだ」らしい。

これに対して、色々なモデルを作って、シミュレーションで再現するという研究が色々出たっぽい。上の総説は2000年頃のもののようだけど、現在でも、この問題が解決してるのかは、よく分からない。

大体、基本になってるのはHebb則で、加えて、いくつかの補助的な機構が仮定されるという感じで、網膜〜一次視覚野でHebb則による学習が存在するのかは知らないけど、Hebb則自体は、海馬なんかでのLTPの発見によって、脳神経の学習の適切なモデル化だと考えられている。


1980年代後半に、Linskerという人も、この手のシミュレーションをして、Linskerは、シミュレーション結果から一歩進んで、Hebb則による学習が何を最適化しているのかという視点から、infomax原理を提唱した。今では、"入出力間の相互情報量を最大化する"と説明されてることが多い

From basic network princples to neural architecture:Emergence of spatial-opponent cells
https://www.pnas.org/content/83/19/7508

From basic network princples to neural architecture:Emergence of orientation-selective cells
https://www.pnas.org/content/83/21/8390

From basic network princples to neural architecture:Emergence of orientation columns
https://www.pnas.org/content/83/22/8779

Self-organization in a perceptual network
https://ieeexplore.ieee.org/document/36
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.183.1750


Linskerの論文は、結局、主成分分析が出るみたいな話に見えるけど、主成分分析とEdge detectorやGabor filterが、どう繋がってるのかは定かでない

Linskerが、infomax原理からPCAを導くに当たって、二次の統計量までを考慮するという近似と、noiseはgaussianであるという性質を仮定したが、1996年の以下の論文では、その点を批判している。

The "independent components" of natural scenes are edge filters
https://www.ncbi.nlm.nih.gov/pubmed/9425547

論文の主な主張は、PCAではなく、ICAをやると、エッジフィルターが出るという話。PCAとICAの比較がされていて、PCAだと、エッジフィルターとは思えないものが得られている

論文でも、Gabor-likeという表現が使われているけど、本当にGaborなのか?とか、ICAだと何故Gaborが出るのか?とかは説明がない。この論文の結果を追試しようかと思ったけど、論文を読んでから長時間放置してたら、やる気がなくなったので、まぁ、そのうち

【補足】使用した画像データなんかは、既に入手できなくなってるっぽいけど、2013年の以下の論文でも同じようなことをやっていて、こっちはデータが現時点でまだ入手できるので、こっちのデータを使えば、まぁいいかという感じ

Double-Gabor Filters Are Independent Components of Small Translation-Invariant Image Patches
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3693455/


1990年代とかに、どうだったのか知らないけど、PCAを適用してみた事例は、今では沢山あって、まぁ概して、特にうまくいってるという感じもない。ICAだったら、どうかっていうのは、よく分からない。

同じ著者による論文で、自然音声に対して、同様のテクニックを適用したという論文が以下。

Learning the higher-order structure of a natural sound.
https://www.ncbi.nlm.nih.gov/pubmed/16754385

以下の論文も同じようなことをやってるっぽいけど、Gammatoneフィルター(?)っぽいものが得られるとか書いてある
Efficient coding of natural sounds.
https://www.ncbi.nlm.nih.gov/pubmed/11896400

Efficient auditory coding.
https://www.ncbi.nlm.nih.gov/pubmed/16495999

Gammatone filter
https://en.wikipedia.org/wiki/Gammatone_filter

以下は、二次視覚野もICAでイケソウというような話っぽい
Statistical model of natural stimuli predicts edge-like pooling of spatial frequency channels in V2.
https://www.ncbi.nlm.nih.gov/pubmed/15715907