对2d数组的for循环进行更快的迭代



我在优化计算视差图估计误差时遇到了一个问题。

为了计算错误,我创建了一个类,为每个错误调用方法。我需要迭代每一个像素来得到一个错误。这个数组很大,因为我迭代的图像大小是1937 x 1217。你知道如何优化它吗?

这是我的方法的代码:

编辑:

def mreError(self):
s_gt = self.ref_disp_norm
s_all = self.disp_bin
s_r = self.disp_norm 
s_gt = s_gt.astype(np.float32)
s_r = s_r.astype(np.float32)
n, m = s_gt.shape
all_arr = []
for i in range(0, n):
for j in range(0, m):
if s_all[i,j] == 255:
if s_gt[i,j] == 0:
sub_mre = 0
else:   
sub_mre = np.abs(s_gt[i,j] - s_r[i,j]) / s_gt[i,j]
all_arr.append(sub_mre)
mre_all = np.mean(all_arr)
return mre_all

方法的直接矢量化将是

def method_1(self):
# get s_gt, s_all, s_r
sub_mre = np.zeros((s_gt.shape), dtype=np.float32)
idx = s_gt != 0
sub_mre[idx] = np.abs((s_gt[idx] - s_r[idx]) / s_gt[idx])
return np.mean(sub_mre[s_all == 255])

但是由于您只对s_all为255的像素进行平均,您也可以先过滤这些像素,然后再进行其余的

def method_2(self):
idx = s_all == 255
s_gt = s_gt[idx].astype(np.float32)
s_r = s_r[idx].astype(np.float32)
sub_mre = np.zeros_like(s_gt)
idx = s_gt != 0
sub_mre[idx] = np.abs((s_gt[idx] - s_r[idx]) / s_gt[idx])
return np.mean(sub_mre)

就我个人而言,我倾向于第一种方法,除非第二种方法的结果快得多。只调用函数一次,花费的时间(例如,40毫秒vs 5毫秒)并不明显,函数的可读性更重要。

您可以简单地使用数组操作符,而不是将它们应用于for循环中的每个元素:

import numpy as np
# Creating 2000x2000 Test-Data
s_gt = np.random.randint(0,2,(2000,2000)).astype(np.float32)
s_r = np.random.randint(0,2,(2000,2000)).astype(np.float32)
s_all = np.random.randint(0,256,(2000,2000)).astype(np.float32)

def calc(s_gt, s_r, s_all):
n, m = s_gt.shape
all_arr = []
for i in range(0, n):
for j in range(0, m):
if s_gt[i,j] == 0:
sub_mre = 0
else:   
sub_mre = np.abs(s_gt[i,j] - s_r[i,j]) / s_gt[i,j]

if s_all[i,j] == 255:
all_arr.append(sub_mre)

mre_all = np.mean(all_arr)
return mre_all
def calc_optimized(s_gt, s_r, s_all):
sub_mre = np.abs((s_gt-s_r)/s_gt)
sub_mre[s_gt==0] = 0
return np.mean(sub_mre[s_all == 255])

当我测试两种不同方法的速度时:

%time calc(s_gt, s_r, s_all)
Wall time: 27.6 s
Out[53]: 0.24686379928315413
%time calc_optimized(s_gt, s_r, s_all)
Wall time: 63.3 ms
__main__:34: RuntimeWarning: divide by zero encountered in true_divide
__main__:34: RuntimeWarning: invalid value encountered in true_divide
Out[54]: 0.2468638

你可以把图像做成灰色(这将大大加快计算速度),去看看这个链接你怎么做。