【发布时间】:2021-04-17 13:16:45
【问题描述】:
我有这个代码:
import numpy as np
from skimage.util import img_as_ubyte
from skimage.feature import canny
import math
image = img_as_ubyte(sf_img)
edges = np.flipud(canny(image, sigma=3, low_threshold=10, high_threshold=25))
non_zeros = np.nonzero(edges)
true_rows = non_zeros[0]
true_col = non_zeros[1]
plt.imshow(edges)
plt.show()
N_im = 256
x0 = 0
y0 = -0.25
Npx = 129
Npy = 60
delta_py = 0.025
delta_px = 0.031
Nr = 9
delta_r = 0.5
rho = 0.063
epsilon = 0.75
r_k = np.zeros((1, Nr))
r_min = 0.5
for k in range(0, Nr):
r_k[0, k] = k * delta_r + r_min
a = np.zeros((Npy, Npx, Nr))
#FOR LOOP TO BE TIME OPTIMIZED
for i in range(0, np.size(true_col, 0)): #true_col and true_rows has the same size so it doesn't matter
for m in range(0, Npy):
for l in range(0, Npx):
d = math.sqrt(math.pow(
(((true_col[i] - math.floor((N_im + 1) / 2)) / (N_im + 1) / 2) - (
l * delta_px - (Npx * delta_px / 2) + x0)),
2) + math.pow(
(((true_rows[i] - math.floor((N_im + 1) / 2)) / (N_im + 1) / 2) - (
m * delta_py - (Npy * delta_py / 2) + y0)),
2))
min_idx = np.argmin(np.abs(d - r_k))
rk_hat = r_k[0, min_idx]
if np.abs(d - rk_hat) < rho:
a[m, l, min_idx] = a[m, l, min_idx] + 1
#ANOTHER LOOP TO BE OPTIMIZED
# for m in range(0, Npy):
# for l in range(0, Npx): #ORIGINAL
# for k in range(0, Nr):
# if a[m, l, k] < epsilon * np.max(a):
# a[m, l, k] = 0
a[np.where(a[:, :, :] < epsilon * np.max(a))] = 0 #SUBSTITUTED
a_prime = np.sum(a, axis=2)
acc_x = np.zeros((Npx, 1))
acc_y = np.zeros((Npy, 1))
for l in range(0, Npx):
acc_x[l, 0] = l * delta_px - (Npx * delta_px / 2) + x0
for m in range(0, Npy):
acc_y[m, 0] = m * delta_py - (Npy * delta_py / 2) + y0
prod = 0
for m in range(0, Npy):
for l in range(0, Npx):
prod = prod + (np.array([acc_x[l, 0], acc_y[m, 0]]) * a_prime[m, l])
points = prod / np.sum(a_prime)
基于对an answer的评论:
true_rows = np.random.randint(0,256,10)
true_col = np.random.randint(0,256,10)
简单地说,它会扫描之前通过 Canny 边缘检测处理过的 256x256 图像。 For 循环因此必须扫描结果图像的每个像素,并且还必须计算 2 个嵌套的 for 循环,这些循环根据 'a' 矩阵的 l 和 m 索引的值执行一些操作。
由于边缘检测返回一个带有 0 和 1 的图像(与边缘相对应),并且由于内部操作必须仅针对单值点进行,所以我使用了
non_zeros = np.nonzero(edges)
只获取我感兴趣的索引。确实,以前的代码是这样的
for i in range(0, N_im):
for j in range(0, N_im):
if edges[i, j] == 1:
for m in range(0, Npy):
for l in range(0, Npx):
d = math.sqrt(math.pow(
(((i - math.floor((N_im + 1) / 2)) / (N_im + 1) / 2) - (
l * delta_px - (Npx * delta_px / 2) + x0)),
2) + math.pow(
(((j - math.floor((N_im + 1) / 2)) / (N_im + 1) / 2) - (
m * delta_py - (Npy * delta_py / 2) + y0)),
2))
min_idx = np.argmin(np.abs(d - r_k))
rk_hat = r_k[0, min_idx]
if np.abs(d - rk_hat) < rho:
a[m, l, min_idx] = a[m, l, min_idx] + 1
似乎我设法优化了前两个循环,但我的脚本需要比这更快。 运行大约需要 6~7 分钟,我需要执行 1000 次。你能帮我进一步优化这个脚本的 for 循环吗?谢谢!
【问题讨论】:
-
您的minimal reproducible example 是否包含for 循环操作的数据的代表性示例?我们可以直接从您的问题中复制和粘贴吗?如果您的问题中有任何不相关的代码(优化 for 循环),您可以将其配对到最低限度吗?
-
是的,当然。我唯一能做的就是通过这个链接给你“sf_img.npy”文件:wetransfer.com/downloads/…。你下载它,你通过
np.load()加载它,然后你可以复制粘贴所有代码 -
@wwii 我也添加了导入的库
-
The only thing I can do is- untrue ,您可以包含 for 循环使用的数组的最小示例。第一个需要true_col和true_rows的minimal 示例——看起来您已经提供了所有常量。我们不必去异地资源来回答您的问题。这些数组的示例不需要具有相同的维度,(4,4)数组可以满足(256,256)数组。 -
为什么
r_k的形状是(1,9)而不是(9,)?
标签: python performance numpy