python - 根据每个像素的位置有效地应用一个函数
问题描述
我想有效地迭代给定图像的每个像素,并根据像素的位置,应用一个函数并将输出放在这个位置。
这是我尝试过的:
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))
虽然它很幼稚,而且效率极低,特别是对于大图像。我知道我可以向量化一个函数,这样所有计算都将同时有效地完成,但我不确定它是否可能/如何向量化一个为每个像素获取像素位置的函数。
解决方案
鉴于函数将接收的是行和列的索引,您可以使用np.aranges
asx1
和y1
坐标直接以矢量化方式计算所有值:
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))
numexpr
我们还可以通过使用模块来加速计算:
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)
11000x
使用第二种方法可以加快速度!
推荐阅读
- python - 估计文本文件中值的函数
- jquery - 使用 Asp.net Core MVC Bootstrap 4,对于服务器端添加的模型状态错误,我无法让不显眼的验证正常工作
- linux - 如何使用 cURL 发布请求将文件内容作为数据原始有效负载中的字符串发送
- python - 根据多索引的级别过滤选择值
- postgresql-11 - Azure PostgreSQL 的 Azure DevOps
- android - 在 Android 应用程序上运行检测时获取 ClassNotFoundException
- php - 会议邀请未显示在我的日历中
- racket - 如何解决“未绑定标识符错误:球拍”
- php - Laravel 8图像未显示
- flutter - 提供程序在执行时未更新,Navigator.pop(context) 在颤动