让两个大的(2000x2000或更高).tiff图像只包含numpy float32值(没有rgb)。我把它们称为图像A和B.我想以一种特殊的方式将它们相乘:
两个图像总是相同的形状。 我提出了这个想法:
#A,B are loaded with PIL as numpy images and are flattend
B = np.roll(B, len(mult_img)-distance_to_max) #roll max to the first element
sum_arr = np.sum(B) #sum of B
for i in range(len(A)):
A = np.multiply(A, np.roll(B, i)) #roll B with i-increment and multiply
A[i] += sum_arr #add sum to A at index
在重新整形数组并保存之后,看起来它会完成这项工作。但是对于一个2000x2000的图像需要大约40秒,并且它们将有处理的内容。 问题是:如何改进?或者是否有更好的numpy解决方案来完成这项任务以加快速度?
提前致谢
答案 0 :(得分:2)
预期方法
考虑一下:
In [154]: B = np.arange(5)
In [155]: B
Out[155]: array([0, 1, 2, 3, 4])
使用B
的滚动版本:
In [156]: for i in range(len(B)):
...: print np.roll(B, i)
...:
[0 1 2 3 4]
[4 0 1 2 3]
[3 4 0 1 2]
[2 3 4 0 1]
[1 2 3 4 0]
因此,我们需要采用的技巧是创建一个可以切片以获得滚动版本的扩展数组。在NumPy切片的想法基本上是免费的。因此,扩展数组将是 -
In [157]: B_ext = np.concatenate((B[1:], B))
In [158]: B_ext
Out[158]: array([1, 2, 3, 4, 0, 1, 2, 3, 4])
因此,切片步骤将是 -
[1, 2, 3, 4, 0, 1, 2, 3, 4]
[ ]
[ ]
[ ]
[ ]
[ ]
使用
然后,可以像这样使用扩展数组 -
n = len(A)
for i in range(n-1,-1,-1):
Ac *= B_ext[i:i+n] #roll B with i-increment and multiply
Ac[n-1-i] += sum_arr #add sum to A at index
<强>结束写入强>
最终确定,方法是 -
def org_app(A, B, sum_arr): # Original approach
for i in range(len(A)):
A = np.multiply(A, np.roll(B, i)) #roll B with i-increment and multiply
A[i] += sum_arr #add sum to A at index
return A
def app1(A, B, sum_arr): # Proposed approach
B_ext = np.concatenate((B[1:], B))
n = len(A)
for i in range(n-1,-1,-1):
A *= B_ext[i:i+n] #roll B with i-increment and multiply
A[n-1-i] += sum_arr #add sum to A at index
return A
<强>基准强>
1)验证 -
In [144]: # Setup inputs
...: np.random.seed(1234)
...: N = 10000
...: A = np.random.randint(0,255,(N))
...: B = np.random.randint(0,255,(N))
...: A_copy = A.copy()
...: sum_arr = np.sum(B) #sum of B
...:
In [145]: out1 = org_app(A, B, sum_arr)
...: out2 = app1(A_copy, B, sum_arr)
...: print "Abs. Max. Error : " + str(np.abs(out1-out2).max())
...:
Abs. Max. Error : 0
2)运行时测试 -
In [146]: # Setup inputs
...: np.random.seed(1234)
...: N = 10000
...: A = np.random.randint(0,255,(N))
...: B = np.random.randint(0,255,(N))
...: A_copy = A.copy()
...: sum_arr = np.sum(B) #sum of B
...:
In [147]: %timeit org_app(A, B, sum_arr)
1 loop, best of 3: 196 ms per loop
In [148]: %timeit app1(A_copy, B, sum_arr)
10 loops, best of 3: 51.9 ms per loop