ImageJ のKuwaharaフィルターに似たエッジ保持フィルターを実装する際に、各ピクセルをその周囲の偏差が最小の領域の平均に割り当てますが、パフォーマンスの問題に苦しんでいます。
直観に反して、行列を分離するための平均と偏差の計算は、最終的に出力配列をコンパイルするよりも高速です。ただし、上記の ImageJ の実装では、このステップの合計処理時間の約 70% が予想されるようです。
2 つの配列 mean と stds があり、そのサイズが各軸の出力配列 'res' よりも 2 カーネル サイズ p 大きい場合、偏差が最小の領域の平均にピクセルを割り当てたいとします。
#vector to middle of surrounding area (approx.)
p2 = p/2
# x and y components of vector to each quadrant
index2quadrant = np.array([[1, 1, -1, -1],[1, -1, 1, -1]]) * p2
形状 (asize、asize) の出力配列のすべてのピクセルを反復処理します。
for col in np.arange(asize) + p:
for row in np.arange(asize) + p:
現在の座標周辺の 4 つの象限で最小の std dev を検索し、対応するインデックスを使用して以前に計算された平均を割り当てます。
minidx = np.argmin(stds[index2quadrant[0] + col, index2quadrant[1] + row])
#assign mean
res[col - p, row - p] = means[index2quadrant[:,minidx][0] + col,index2quadrant[:,minidx][1] + row]
Python プロファイラーは、8x8 ピクセル カーネルを使用して 1024x1024 配列をフィルター処理すると、次の結果を示します。
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 30.024 30.024 <string>:1(<module>)
1048576 2.459 0.000 4.832 0.000 fromnumeric.py:740(argmin)
1 23.720 23.720 30.024 30.024 kuwahara.py:4(kuwahara)
2 0.000 0.000 0.012 0.006 numeric.py:65(zeros_like)
2 0.000 0.000 0.000 0.000 {math.log}
1048576 2.373 0.000 2.373 0.000 {method 'argmin' of 'numpy.ndarray' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
2 0.012 0.006 0.012 0.006 {method 'fill' of 'numpy.ndarray' objects}
8256 0.189 0.000 0.189 0.000 {method 'mean' of 'numpy.ndarray' objects}
16512 0.524 0.000 0.524 0.000 {method 'reshape' of 'numpy.ndarray' objects}
8256 0.730 0.000 0.730 0.000 {method 'std' of 'numpy.ndarray' objects}
1042 0.012 0.000 0.012 0.000 {numpy.core.multiarray.arange}
1 0.000 0.000 0.000 0.000 {numpy.core.multiarray.array}
2 0.000 0.000 0.000 0.000 {numpy.core.multiarray.empty_like}
2 0.003 0.002 0.003 0.002 {numpy.core.multiarray.zeros}
8 0.002 0.000 0.002 0.000 {zip}
私にとっては、argmin を除いて、合計時間は無視できるように見えるため、時間が失われる兆候はあまりありません (-> numpy?)。
パフォーマンスを改善する方法について何か提案はありますか?