在实现类似于 ImageJ 的Kuwahara过滤器的边缘保留过滤器时,它将每个像素分配给周围偏差最小的区域的平均值,我正在努力解决性能问题。
与直觉相反,与最终编译输出数组相比,计算分离矩阵的均值和偏差要快。不过,上面的 ImageJ 实现似乎预计这一步的总处理时间约为 70%。
给定两个数组均值和标准差,其大小比每个轴上的输出数组“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 个象限中搜索最小标准差,并使用相应的索引来分配先前计算的平均值:
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}
对我来说,没有太多的迹象(-> numpy?),时间丢失了,因为除了 argmin,总时间似乎可以忽略不计。
你有什么建议,如何提高性能?