ライフゲーム / Python / numpy.convolve() でムーア近傍の和を求める
scipy.signal.convolve2d()
は使わずにnumpy.convolve()
でムーア近傍の和を求めてみる。numpy.convolve()
は1次元にしか使えないので次のように計算する。
import numpy as np from scipy.signal import convolve2d def moore(mat): # 現世代排列を取り込んで、念のためndarrayにしておく。 mat = np.asarray(mat, dtype=np.uint8) numOfRows, numOfCol = mat.shape # 現世代排列よりも一回り大きい空排列を作って、 matFat = np.empty(np.asarray(mat.shape)+2, dtype=np.uint8) # その空排列を利用して現世代排列の上下左右をコピーし合う。 matFat[1:numOfRows+1,1:numOfCol+1] = mat matFat[0] , matFat[-1] = matFat[-2] , matFat[1] matFat[:,[0]], matFat[:,[-1]] = matFat[:,[-2]], matFat[:,[1]] origin = matFat.copy() numOfRows, numOfCols = matFat.shape matFat = matFat.reshape(matFat.size) # トーラス排列を1行排列に変更して、 matFat = np.convolve(matFat, [1,1,1], mode="same") # 自分と両隣との和を求めて、 matFat = matFat.reshape(numOfRows, numOfCols) # また元の形状の排列に戻して、 matFat = matFat.T # 今度は自分と上下との和を求めたいので、排列を転置して、 matFat = matFat.reshape(matFat.size) # また1行排列に変更して、 matFat = np.convolve(matFat, [1,1,1], mode="same") # 自分と両隣との和(元の排列で言えば自分と上下との和)を求めて、 matFat = matFat.reshape(numOfCols, numOfRows) # またもとの形状の排列に戻して、 matFat = matFat.T return (matFat - origin)[1:-1, 1:-1] # (ここまでの計算では周囲8セルと自分との和を計算したことになるので)自分自身を引いて最外周を削って返す。 ################################################# a = np.random.randint(0, 2, [7, 10]) a1 = convolve2d(a, [[1,1,1], [1,0,1], [1,1,1]], mode="same", boundary="wrap") a2 = moore(a) print(a) print(a1) print(a2) print(np.equal(a1, a2))
実行結果:
上から
「現世代排列」
「scipy.signal.convolve2d()によるムーア近傍の和」
「numpy.convolve()によるムーア近傍の和」
「両者の全セルの比較」