首页 > 解决方案 > python - 如何在不使用for循环的情况下在python中使用numpy来实现矩阵映射?

问题描述

我有三个数组,一个srcshape数组,(width, height, 3)一个shapetemplate数组(640, 480, 3)和一个shapeimg_map数组(width, height, 2)

img_map存储 和 之间的 x,y 关系srctemplatesrc[4, 5] = template[img_map[0,4,5], img_map[1,4,5]]. 当映射建议的索引超出范围时,不会分配任何值。

如何在python中使用numpy在没有for循环的情况下实现这样的值赋值?

使用for循环会是这样,但是太慢了。

for x in range(0, width): 
  for y in range(0, height):
    u = img_map[x,y,0]
    v = img_map[x,y,1]
    if (u >= 0) and (v >= 0) and (u < 640) and (v < 480):
      src[x,y,:] = template[u,v,:]

标签: pythonnumpy

解决方案


这是一个可以完成这项工作的单线版本:

src = template[img_map[:,:,0].ravel(),img_map[:,:,1].ravel(),:].reshape((width,height,3))

这是一个小代码,用于验证结果的准确性并评估性能改进:

import numpy as np
import time

# Preparation of testdata
(width, height, depth) = (1000, 1000, 3)
template = np.random.randint(0, 256, (640,480,depth))
img_map = np.concatenate((
    np.random.randint(0, template.shape[0], (width*height,1)),
    np.random.randint(0, template.shape[1], (width*height,1))
  ), axis=1
).reshape(width,height,2)

# For loop verion
t_start = time.time()
src = np.zeros((img_map.shape[0],img_map.shape[1],template.shape[2]))
for x in range(0, img_map.shape[0]): 
  for y in range(0, img_map.shape[1]):
    u = img_map[x,y,0]
    v = img_map[x,y,1]
    if (u >= 0) and (v >= 0) and (u < template.shape[0]) and (v < template.shape[1]):
      src[x,y,:] = template[u,v,:]
print(f'Timer 1: {time.time()-t_start}s')

# One line version
t_start = time.time()
src2 = template[img_map[:,:,0].ravel(),img_map[:,:,1].ravel(),:].reshape((width,height,depth))
print(f'Timer 2: {time.time()-t_start}s')

# Verify that both gives the same result
print('Results are equal' if np.linalg.norm(src-src2)==0 else 'Results differ')

结果相等,执行时间显着提高:

% python3 script.py
Timer 1: 2.7333829402923584s
Timer 2: 0.0499570369720459s
Results are equal

如果您有任何问题,请不要犹豫。


推荐阅读