我想要优化的代码中有一个相当慢的点。在掩码图像中,我正在计算R,G和B通道的平均值。我想摆脱嵌套的for循环,并不确定如何实现它。有什么想法吗?
maskimage = cv2.imread(filename)
hsv = cv2.cvtColor(maskimage, cv2.COLOR_BGR2HSV)
boundaries = [([25, 146, 190], [62, 174, 250])]
for (lower, upper) in boundaries:
# create NumPy arrays from the boundaries
lower = np.array(lower, dtype = "uint8")
upper = np.array(upper, dtype = "uint8")
# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(hsv, lower, upper)
masked_img = cv2.bitwise_and(bgimage, bgimage, mask = mask)
meanblue = 0
meangreen = 0
meanred = 0
count = 0
H, W, b = masked_img.shape
for i in range(0,H,1):
for j in range(0,W,1):
if masked_img[i,j,0] > 1 or masked_img[i,j,1] > 1 or masked_img[i,j,2] > 1:
meanblue = meanblue + masked_img[i,j,0]
meangreen = meangreen + masked_img[i,j,1]
meanred = meanred + masked_img[i,j,2]
count = count+1
if count !=0:
omeanb = meanblue/count
omeang = meangreen/count
omeanr = meanred/count
if count ==0:
omeanb = 255
omeang = 255
omeanr = 255
答案 0 :(得分:2)
您可以使用矢量化方法替换最里面的两个嵌套循环。
因此,人们可以取代它 -
H, W, b = masked_img.shape
for i in range(0,H,1):
for j in range(0,W,1):
if masked_img[i,j,0] > 1 or masked_img[i,j,1] > 1 or masked_img[i,j,2] > 1:
meanblue = meanblue + masked_img[i,j,0]
meangreen = meangreen + masked_img[i,j,1]
meanred = meanred + masked_img[i,j,2]
count = count+1
用这个 -
mask = (masked_img > 1).any(2)
count = mask.sum()
mean_bgr = (masked_img*(mask[...,None])).sum(axis=(0,1))
在最后一步可能会有点冒险并使用np.einsum
,这可能会进一步提升效果,就像这样 -
mean_bgr = np.einsum('ijk,ij->k',masked_img.astype(int),mask)
运行时测试
功能定义 -
def original_app(masked_img):
meanblue = 0
meangreen = 0
meanred = 0
count = 0
H, W, b = masked_img.shape
for i in range(0,H,1):
for j in range(0,W,1):
if masked_img[i,j,0] > 1 or masked_img[i,j,1] > 1 or masked_img[i,j,2] > 1:
meanblue = meanblue + masked_img[i,j,0]
meangreen = meangreen + masked_img[i,j,1]
meanred = meanred + masked_img[i,j,2]
count = count+1
return [meanblue, meangreen, meanred], count
def vectorized_app1(masked_img):
mask = (masked_img > 1).any(2)
count = mask.sum()
mean_bgr = (masked_img*(mask[...,None])).sum(axis=(0,1))
return mean_bgr, count
def vectorized_app2(masked_img):
mask = (masked_img > 1).any(2)
count = mask.sum()
mean_bgr = np.einsum('ijk,ij->k',masked_img.astype(int),mask)
return mean_bgr, count
计时 -
In [235]: # Random image input array
...: masked_img = np.random.randint(0,255,(512,512,3)).astype('uint8')
In [236]: original_app(masked_img)
Out[236]: ([33273503, 33274596, 33323215], 262144)
In [237]: vectorized_app1(masked_img)
Out[237]: (array([33273503, 33274596, 33323215], dtype=uint32), 262144)
In [238]: vectorized_app2(masked_img)
Out[238]: (array([ 33273503, 33274596, 33323215]), 262144)
In [239]: %timeit original_app(masked_img)
1 loops, best of 3: 2.08 s per loop
In [240]: %timeit vectorized_app1(masked_img)
100 loops, best of 3: 17.9 ms per loop
In [241]: %timeit vectorized_app2(masked_img)
10 loops, best of 3: 16.5 ms per loop
那里的 100+x
加速了!
答案 1 :(得分:1)
您可以使用itertools.product。
,而不是嵌套for循环示例:
>>> from itertools import product
>>> [(i,j) for i, j in product((1,2,3), (4, 5, 6))]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]