根据位置将功能有效地应用于每个像素

时间:2019-05-09 13:09:12

标签: python performance numpy image-processing

我想有效地遍历给定图像的每个像素,并根据像素的位置应用函数并将输出放置在该位置。

这是我尝试过的:

def point_gaussian_value(p1, p2, sigma=0.8):
    x1, y1 = p1
    x2, y2 = p2

    return np.exp(-1 * (np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) / sigma ** 2))

point_annotation = np.zeros_like(sample).astype(np.float32)
for j in range(sample.shape[0]):
    for k in range(sample.shape[1]):

        value = point_gaussian_value(p1=(j, k), p2=(row[header[i]], row[header[i + 1]]))
        point_annotation[j, k] = point_gaussian_value(p1=(j, k), p2=(20, 20))

尽管它很幼稚,而且效率极低,特别是对于大图像。我知道我可以向量化一个函数,以便所有计算都可以同时高效地完成,但是我不确定是否可以/如何向量化每个像素得到一个像素位置的函数。

1 个答案:

答案 0 :(得分:4)

鉴于该函数将接收的是行和列的索引,因此可以通过将np.aranges用作x1和{{1},以向量化的方式直接计算所有值}坐标:

y1

我们还可以使用numexpr模块来加快计算速度:

rows = np.arange(sample.shape[0])
cols = np.arange(sample.shape[1])
x2, y2 = (row[header[i]], row[header[i + 1]])
out = np.exp(-1 * (np.sqrt((x2 - rows[:,None])**2 + (y2 - cols)**2) / 0.8**2))

快速检查和计时:

import numexpr as ne
rows = np.arange(sample.shape[0])
cols = np.arange(sample.shape[1])
x2, y2 = (row[header[i]], row[header[i + 1]])
out = ne.evaluate('exp(-1 * sqrt((x2- rows2D)**2 + (y2- cols)**2) / 0.8**2)', 
                 {'rows2D': rows[:,None]})

n_rows = 1000
n_cols = 1000
rows = np.arange(n_rows)
cols = np.arange(n_cols)
x2, y2 = 10, 12
out = ne.evaluate('exp(-1*sqrt((x2- rows2D)**2 + (y2- cols)**2) / 0.8**2)', 
                 {'rows2D': rows[:,None]})

np.allclose(out, point_annotation, rtol=1e-5)
# True

第二种方法可以使 def current_approach(n_rows, n_cols, x2, y2): point_annotation = np.zeros((n_rows,n_cols)).astype(np.float32) for j in range(n_rows): for k in range(n_cols): value = point_gaussian_value(p1=(j, k), p2=(x2,y2)) point_annotation[j, k] = point_gaussian_value(p1=(j, k), p2=(x2,y2)) def approach_1(n_rows, n_cols, x2, y2): rows = np.arange(n_rows) cols = np.arange(n_cols) out = np.exp(-1 * (np.sqrt((x2- rows[:,None])**2 + (y2- cols)**2) / 0.8**2)) def approach_2(n_rows, n_cols, x2, y2): rows = np.arange(n_rows) cols = np.arange(n_cols) out = ne.evaluate('exp(-1*sqrt((x2- rows2D)**2 + (y2- cols)**2) / 0.8**2)', {'rows2D': rows[:,None]}) %timeit current_approach(n_rows, n_cols, x2, y2) # 10.7 s ± 471 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) %timeit approach_1(n_rows, n_cols, x2, y2) # 59.3 ms ± 426 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) %timeit approach_2(n_rows, n_cols, x2, y2) # 965 µs ± 43.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 加速!