前提
二次元配列の特定のセルに隣接する周囲8方向のセルに,ある数値が格納されているとき,
その数を高速で取得したいと考えています.ここで,隣接する特定の数値のカウントはできる一方で,
計算の高速化が実現できていません.実務で,1000×1000程度の配列で10万回以上同じ処理を繰り返すため,
現時点でのコードではどうしても時間がかかってしまいます.
実現したいこと
以下の二次元配列で1の部分に注目します.1に隣接する周囲8方向に0が入っている場合,
0が上下左右方向であればカウンターとして1を,
斜め方向であれば1/√2を追加する処理を高速で実現したいと考えています.
例として赤枠で囲まれた1には,1+1+(1/√2)+(1/√2)のカウントが貯まっていきます.
現在はscipyの畳み込みを使用していますが,より良いコードと高速化手法をご教授いただきたく投稿しました.
現在のコード
Python
1#モジュールのインポート 2import pandas as p 3import numpy as np 4import math 5from scipy.signal import convolve2d 6 7#配列準備 8land_sea_boundary = np.array([[2, 2, 2, 2, 2, 2], 9 [2, 2, 2, 2, 2, 2], 10 [2, 2, 1, 1, 1, 1], 11 [1, 1, 1, 0, 0, 0], 12 [0, 0, 0, 0, 0, 0], 13 [0, 0, 0, 0, 0, 0]]) 14 15#カウンター格納用の配列準備 16retreat_increment = np.zeros([6, 6]) 17 18#mainの処理 19up = np.array([[0, 1, 0], [0, 0, 0], [0, 0, 0]]) 20down = np.array([[0, 0, 0], [0, 0, 0], [0, 1, 0]]) 21left = np.array([[0, 0, 0], [1, 0, 0], [0, 0, 0]]) 22right = np.array([[0, 0, 0], [0, 0, 1], [0, 0, 0]]) 23 24up_right = np.array([[0, 0, 1], [0, 0, 0], [0, 0, 0]]) 25up_left = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]]) 26down_right = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 1]]) 27down_left = np.array([[0, 0, 0], [0, 0, 0], [1, 0, 0]]) 28 29retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, up, mode='same', boundary='fill', fillvalue=0) == 0), 1, 0) 30retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, down, mode='same', boundary='fill', fillvalue=0) == 0), 1, 0) 31retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, left, mode='same', boundary='fill', fillvalue=0) == 0), 1, 0) 32retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, right, mode='same', boundary='fill', fillvalue=0) == 0), 1, 0) 33retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, up_right, mode='same', boundary='fill', fillvalue=0) == 0), 1/math.sqrt(2), 0) 34retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, up_left, mode='same', boundary='fill', fillvalue=0) == 0), 1/math.sqrt(2), 0) 35retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, down_right, mode='same', boundary='fill', fillvalue=0) == 0), 1/math.sqrt(2), 0) 36retreat_increment = retreat_increment + np.where((land_sea_boundary == 1) & (convolve2d(land_sea_boundary, down_left, mode='same', boundary='fill', fillvalue=0) == 0), 1/math.sqrt(2), 0) 37 38#配列の四辺は内側の値をコピー 39retreat_increment = np.pad(retreat_increment[1:-1,1:-1], 1, 'edge') 40 41 42print(retreat_increment) 43 44#[[0. 0. 0. 0. 0. 0. ] 45 #[0. 0. 0. 0. 0. 0. ] 46 #[0. 0. 0.70710678 1.70710678 2.41421356 2.41421356] 47 #[2.41421356 2.41421356 3.41421356 0. 0. 0. ] 48 #[0. 0. 0. 0. 0. 0. ] 49 #[0. 0. 0. 0. 0. 0. ]] 50
試したこと
以前,for文を使用して周囲8方向を検索するプログラムを書いたのですが,
その手法では計算速度が出なかったため,scipyの畳み込みを使用しました.
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/08/13 06:22